473,398 Members | 2,389 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,398 software developers and data experts.

Global variable modifiable by some translation units but not others

Let's say I have a global variable int var which I want
to be known to translation units T1 and T2, I want T1
to be able to read its value and modify it and T2 to be
able to read its value but not modify it. Would it work
if I declare it inside T1 as "extern int var" and inside T2
as "extern const int var" ?

Dec 17 '06 #1
9 1919
"Spiros Bousbouras" <sp****@gmail.comwrote in message
news:11**********************@n67g2000cwd.googlegr oups.com...
Let's say I have a global variable int var which I want
to be known to translation units T1 and T2, I want T1
to be able to read its value and modify it and T2 to be
able to read its value but not modify it. Would it work
if I declare it inside T1 as "extern int var" and inside T2
as "extern const int var" ?
This may work with most development tools.

However, I wouldn't do it in quite that way.

There are two downsides of declaring something in multiple locations:

a)Extra work when something changes.

b)The risk of not changing all related items.

Linkers in general aren't smart enough to figure out that:

int c=0;

and

extern long c;

are inconsistent when they appear in different translation units (i.e.
changed one place but not the other), and bizarre results can be obtained at
runtime.

In your scenario, I would look at two alternate ways of doing it.

Method 1: Shared Header File

T1.C
----
#define MODULE_T1

#include "t1.h"

T2.C
----
#define MODULE_T2

#include "t1.h"

T1.H
----
#ifndef (T1_H_INCLUDED)
#define T1_H_INCLUDED

#ifdef (MODULE_T1)
#define DECMOD_T1
#else
#define DECMOD_T1 extern
#endif

DECMOD_T1
#ifndef (MODULE_T1)
const
#endif
int shared_var;

#endif

Method 2: Accessor Functions to T1-Static Variable

No further explanation needed for this method.

Dave.

Dec 17 '06 #2
David T. Ashley wrote:
"Spiros Bousbouras" <sp****@gmail.comwrote in message
news:11**********************@n67g2000cwd.googlegr oups.com...
Let's say I have a global variable int var which I want
to be known to translation units T1 and T2, I want T1
to be able to read its value and modify it and T2 to be
able to read its value but not modify it. Would it work
if I declare it inside T1 as "extern int var" and inside T2
as "extern const int var" ?

This may work with most development tools.

However, I wouldn't do it in quite that way.

There are two downsides of declaring something in multiple locations:

a)Extra work when something changes.

b)The risk of not changing all related items.

Linkers in general aren't smart enough to figure out that:

int c=0;

and

extern long c;

are inconsistent when they appear in different translation units (i.e.
changed one place but not the other), and bizarre results can be obtained at
runtime.

In your scenario, I would look at two alternate ways of doing it.

Method 1: Shared Header File

T1.C
----
#define MODULE_T1

#include "t1.h"

T2.C
----
#define MODULE_T2

#include "t1.h"

T1.H
----
#ifndef (T1_H_INCLUDED)
#define T1_H_INCLUDED

#ifdef (MODULE_T1)
#define DECMOD_T1
#else
#define DECMOD_T1 extern
#endif

DECMOD_T1
#ifndef (MODULE_T1)
const
#endif
int shared_var;

#endif
Why not simply write

#ifndef (T1_H_INCLUDED)
#define T1_H_INCLUDED

#ifdef (MODULE_T1)
int shared_var;
#else
extern const int shared_var;
#endif

#endif

It's certainly more readable.
Method 2: Accessor Functions to T1-Static Variable

No further explanation needed for this method.
Actually I would appreciate an example for this one too.

Dec 18 '06 #3
"Spiros Bousbouras" <sp****@gmail.comwrites:
Let's say I have a global variable int var which I want
to be known to translation units T1 and T2, I want T1
to be able to read its value and modify it and T2 to be
able to read its value but not modify it. Would it work
if I declare it inside T1 as "extern int var" and inside T2
as "extern const int var" ?
Any easy way is to not declare it at all in T2 and only give access via a "get"
function declared in T1. Or?
Dec 18 '06 #4
"Spiros Bousbouras" <sp****@gmail.comwrote in message
news:11**********************@73g2000cwn.googlegro ups.com...
>
Why not simply write

#ifndef (T1_H_INCLUDED)
#define T1_H_INCLUDED

#ifdef (MODULE_T1)
int shared_var;
#else
extern const int shared_var;
#endif

#endif

It's certainly more readable.
The hypothetical risk is that someone would accidentally do this:

#ifdef (MODULE_T1)
long shared_var;
#else
extern const int shared_var;
#endif

leading to some spectacular undefined behavior at runtime, as T1 will have
different ideas about shared_var than T2.

Repeating the type and/or the variable name makes this class of mistake
possible.

I agree with you about readability ... and one can certainly carry any idea
too far.

Repeating ANYTHING in a way where there can be a modification accident is
unwise.

Dec 18 '06 #5
"Spiros Bousbouras" <sp****@gmail.comwrote in message
news:11**********************@73g2000cwn.googlegro ups.com...
>
>Method 2: Accessor Functions to T1-Static Variable

No further explanation needed for this method.

Actually I would appreciate an example for this one too.
T1.H
----
extern int vomit_the_variable(void);
/* Note that I'm breaking my own rules here for brevity.
** Ideally this should be done so it serves both as
** an interface definition for T2 and a prototype to
** check linkage for T1. See my earlier post using
** DECMOD_...
*/
T1.C
-----
static int shared_variable;

int vomit_the_variable(void)
{
return(shared_variable);
}

P.S.--The other poster suggested this style, too.

Dec 18 '06 #6
>"Spiros Bousbouras" <sp****@gmail.comwrote in message
>news:11**********************@n67g2000cwd.googleg roups.com...
>Let's say I have a global variable int var which I want
to be known to translation units T1 and T2, I want T1
to be able to read its value and modify it and T2 to be
able to read its value but not modify it. Would it work
if I declare it inside T1 as "extern int var" and inside T2
as "extern const int var" ?
In article <NG******************@fe191.usenetserver.com>
David T. Ashley <dt*@e3ft.comwrote:
>This may work with most development tools.
[omitted: preprocessor tricks for avoiding various errors]

One possible problem here is that a compiler is free to assume
that all "const" objects are stored in a read-only segment, which
might for instance be based off the $24 register, while all
non-"const" objects are stored in a read/write area based off
the $25 register. Then:

/* foo.c */
extern const int var;
int retrieve(void) { return var; }

would compile to something like:

retrieve:
ld 400($24), $v0
ret

while:

/* bar.c */
int var = 42;
void set(int newval) { var = newval; }

would compile instead to:

set:
st $a0, 400($25)
ret

The linker makes sure to put the same offset (here, 400) into both
sections of code. Unfortunately, $24 points to 0x0001004080002000
(the pages where read-only data live; these are shared between all
running instances of the program), while $25 points to 0x000700408ca04000
(where read/write data for this particular instance of the program
live). So calling set() never changes the value returned from
retrieve(), which is not even 42 initially.

Practically speaking, this problem is rare. More commonly (but
equally surprising), programs that use a "small data segment" (on
systems that support such) misbehave if an array size is specified
differently in one module from another:

/* foo.c */
extern int arr[1];
... code using arr[i] ...

/* bar.c */
int arr[400];

When compiling foo.c, the compiler sees that the array "arr" is
small enough to place it in .sdata; but when compiling bar.c, it
sees that the array is large enough that it must go in .data. (The
solution, at least in C, is to omit the size in foo.c -- this must
work no matter whether bar.c places the array in .data or .sdata,
so the implementation may have to "work hard" to get this right.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Dec 18 '06 #7
"David T. Ashley" wrote:
[...]
Linkers in general aren't smart enough to figure out that:

int c=0;

and

extern long c;

are inconsistent when they appear in different translation units (i.e.
changed one place but not the other), and bizarre results can be obtained at
runtime.
[...]

FYI -

I have used systems where the size of the variables is checked at
link time. So, if sizeof(int)!=sizeof(long), you would get an error
at link time.

However, this doesn't help with something like:

long c = 0;
and
extern void *c;

when sizeof(long)==sizeof(void *).

But you are probably correct that linkers "generally" aren't smart
enough to do this, as many platforms I use don't report such things.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>
Dec 18 '06 #8
"David T. Ashley" wrote:
>
"Spiros Bousbouras" <sp****@gmail.comwrote in message
news:11**********************@73g2000cwn.googlegro ups.com...

Why not simply write

#ifndef (T1_H_INCLUDED)
#define T1_H_INCLUDED

#ifdef (MODULE_T1)
int shared_var;
#else
extern const int shared_var;
#endif

#endif

It's certainly more readable.

The hypothetical risk is that someone would accidentally do this:

#ifdef (MODULE_T1)
long shared_var;
#else
extern const int shared_var;
#endif

leading to some spectacular undefined behavior at runtime, as T1 will have
different ideas about shared_var than T2.
[...]

#ifdef MODULE_T1
#define T1_EXTCONST /* "T1_" prefix to allow "T2_" and so on. */
#else
#define T1_EXTCONST extern const
#endif

T1_EXTCONST int shared_var;
T1_EXTCONST void *shared_ptr;

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>

Dec 18 '06 #9
"Chris Torek" <no****@torek.netwrote in message
news:em*********@news4.newsguy.com...
"Spiros Bousbouras" <sp****@gmail.comwrote in message
news:11**********************@n67g2000cwd.google groups.com...
>>Let's say I have a global variable int var which I want
to be known to translation units T1 and T2, I want T1
to be able to read its value and modify it and T2 to be
able to read its value but not modify it. Would it work
if I declare it inside T1 as "extern int var" and inside T2
as "extern const int var" ?

In article <NG******************@fe191.usenetserver.com>
David T. Ashley <dt*@e3ft.comwrote:
>>This may work with most development tools.
[omitted: preprocessor tricks for avoiding various errors]

One possible problem here is that a compiler is free to assume
that all "const" objects are stored in a read-only segment, which
might for instance be based off the $24 register, while all
non-"const" objects are stored in a read/write area based off
the $25 register. Then:
Agreed.

In the systems I use, the const objects in FLASH and non-near RAM variables
both require 16-bit addresses, and the compiler won't distinguish them (i.e.
the machine instructions will be compatible with both).

But, in the general case, this ain't true.

So I guess we're back to the accessor function idea.
More commonly (but
equally surprising), programs that use a "small data segment" (on
systems that support such) misbehave if an array size is specified
differently in one module from another:

/* foo.c */
extern int arr[1];
... code using arr[i] ...

/* bar.c */
int arr[400];
In the systems I use, I could also see a compiler only using 8 bits of the
pointer offset math because it reasons that the array is < 256 bytes so
nobody would dare index beyond the end.

Dec 19 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Richard Hayden | last post by:
Hi, I'm wondering if there is any order in the calling of global and static member objects' constructors which occurs before a C++ program can run. For example, what if I wish to use static...
2
by: Thomas Matthews | last post by:
Hi, I'm getting linking errors when I declare a variable in the global scope, but not inside a function. The declarations are the same (only the names have been changed...). class Book {...
9
by: Tony Johansson | last post by:
Hello! I know it's bad design to use global variables. I just want to ask a question about them. Is global variables and global static variables the same. These are define outside any...
7
by: Brian Sammon | last post by:
According to my programming textbook, "int a;" at the top level of a file is a definition which shouldn't go in a header file. However, I'm running into a lot of online documentation that treats...
7
by: Michael | last post by:
Hi newsgroup, as the subject indicates I am looking for an advice using global variables. I am not if this problem is more about style then C. If its wrong in thi group, sorry. So I have a...
8
by: Morpheus | last post by:
Hello, Say I have a class with a member... char mId; Whenever an object is created, I want to assign an incrementing character to this member, for instance the first would be A, then B, C,...
1
by: dilabox | last post by:
Hello, I have overloaded the global new, delete, new and delete operators inside a "static library". The library uses private memory allocation routines that must not be accessible from other...
10
by: subramanian100in | last post by:
Suppose I declare a global variable int g; in two different files say a.c which has main() and b.c When I compile them to build an executable under gcc in Redhat Linux with the command ...
2
by: Mark | last post by:
Hi, So I came across some source code... "static int slices = 16;" which is outside of any class or function. I know what statics are used for inside classes/functions, but what does it mean if...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.