questions about arrays

C

copx

Q1:
If an array is declared static in file A is it still valid to access
it from file B?
I mean if a function form file A which returns a pointer to a
position inside of the array is called from file B can functions
in file B read/write to the array using this pointer?
I know that this works and doesn't produce a warning with
every compiler I've used but is this behaviour correct?
The question could be stated differently: does "static" really
make the memory area allocated for the array "static"?


Q2:
Can I save/restore an array to/from disk like this:

int my_array[100];

fwrite(my_array, sizeof my_array, 1, out_file);

fread(my_array, sizeof my_array, 1, in_file);

Again, it works mighty fine for me but is it
valid/portable?


copx
 
M

Michael Mair

copx said:
Q1:
If an array is declared static in file A is it still valid to access
it from file B?
I mean if a function form file A which returns a pointer to a
position inside of the array is called from file B can functions
in file B read/write to the array using this pointer?
I know that this works and doesn't produce a warning with
every compiler I've used but is this behaviour correct?
The question could be stated differently: does "static" really
make the memory area allocated for the array "static"?

First possibility: You are talking about using "static" to give static
storage duration to the qualified object and are referring to

/* file_A.c */
.......
T *ProvidePtr (void)
{
static T array[MANY];

return array;
}

/* file_B.c */
.......
T *ptr;
ptr = ProvidePtr();

where T is an appropriate type and MANY is #define'd and >0.

This is indeed standard conforming, portable and what you wish.

Second possibility: You are talking about static used on file scope;
in this case, the array already has static storage duration and
would have external linkage (sort of global visibility throughout
all modules) but due to static the linkage is internal (i.e. it
is only visible within file A).

/* file_A.c */
.......
static T array[MANY];
T *ProvidePtr (void)
{
return array;
}

also works, is legal and everything -- due to the static storage
duration the array exists throughout the life time of the program
and can be accessed using a pointer from about everywhere (this
holds in both cases).
BTW: You can also use this to pass function pointers to functions
with internal linkage.

Q2:
Can I save/restore an array to/from disk like this:

int my_array[100];

fwrite(my_array, sizeof my_array, 1, out_file);

fread(my_array, sizeof my_array, 1, in_file);

Again, it works mighty fine for me but is it
valid/portable?

It is valid but not portable. Even different implementations on
your platform might have different ideas about the representation
of ints and lead to incompatible binary files.
If you want to use binary files which are portable, you have to
define a file format and convert the ints into that format.
Example: Every Byte on disk shall store 8 bits (as opposed to
CHAR_BIT bits on a certain machine), ints are stored in 2s complement,
little endian and use up 16 bits. Then you write your conversion
routines and hope to live happily ever after on all platforms.

Text files are usually more robust, open to manipulations and
easy generation -- and easy checking.


Cheers
Michael
 
C

Chris Croughton

Q1:
If an array is declared static in file A is it still valid to access
it from file B?
I mean if a function form file A which returns a pointer to a
position inside of the array is called from file B can functions
in file B read/write to the array using this pointer?

Yes. You can also doi it with something delared static inside a
function:

#include <stdio.h>
#include <limits.h>

const char *to_binary(unsigned value)
{
static char str[sizeof(value) * CHAR_BIT + 1];
int i;
/* fill str with binary value, nul terminated */
return str;
}

int main(void)
{
printf("%s\n", to_binary(42));
return 0;
}
I know that this works and doesn't produce a warning with
every compiler I've used but is this behaviour correct?
The question could be stated differently: does "static" really
make the memory area allocated for the array "static"?

What do you mean by 'static'? C uses it in two different ways:

(within a function) the memory is not re-used between function calls
(contrasted with 'automatic' variables within functions).

(at file scope) the visibility of the name of the variable only lasts
until the end of the translation unit.

My code above illustrates the first feature, the arrat 'str' in the
function will keep its value and not be re-used when to_binary() exits,
whereas the (automatic) variable 'i' will have an undefined value after
to_binary() exits.

The second definition means that nothing ouside the translation unit can
see the /name/ of the variable, but nothing stops a function in that
translation unit from returning its /address/ to a calling function,
which can then access it through that address.
Q2:
Can I save/restore an array to/from disk like this:

int my_array[100];

fwrite(my_array, sizeof my_array, 1, out_file);

fread(my_array, sizeof my_array, 1, in_file);

Yes, provided the files are opened in binary mode and not text mode (on
systems where that makes a difference, like Windows). (And assuming
appropriate headers, like stdio.h, are included.)
Again, it works mighty fine for me but is it
valid/portable?

The code is portable, the file may not be because the data is written
as a series of bytes, and there are a number of parameters which could
cause it to be read back incorrectly on another system (or even the same
system with a different compiler or different compiler options),
including:

size of the type (int could be 16, 32 or 64 bits, or others)

byte order ('endianness', whether bytes in an int are stored high to
low, low to high or some other order)

if it is an array of a struct, rather than an array of a simple type,
packing issues (whether space is left between members of the struct)

Chris C
 
C

copx

Chris Croughton said:
(within a function) the memory is not re-used between function calls
(contrasted with 'automatic' variables within functions).

(at file scope) the visibility of the name of the variable only lasts
until the end of the translation unit.

I meant file scope static (sorry, I forgot that "static" is "overloaded"
in C - a language design bug IMO).
The second definition means that nothing ouside the translation unit can
see the /name/ of the variable, but nothing stops a function in that
translation unit from returning its /address/ to a calling function,
which can then access it through that address.

But what's the whole point of file scope static in this case?
The name can't be seen outside of the translation unit anyway
unless it's explicitly imported (using "extern"), right?
I was wary because I read in a C book that "static" (file scope)
allows the compiler to do additional optimizations based on
the assumtion that the variable is only accessed in local scope.

[snip]
The code is portable, the file may not be because
[snip]

I'm aware of these problems. In the case of my program
portable files are not required, though.

copx
 
M

Michael Mair

copx said:
On Sat, 26 Mar 2005 09:07:36 +0100, copx
[snip]

What do you mean by 'static'? C uses it in two different ways:

(within a function) the memory is not re-used between function calls
(contrasted with 'automatic' variables within functions).

(at file scope) the visibility of the name of the variable only lasts
until the end of the translation unit.


I meant file scope static (sorry, I forgot that "static" is "overloaded"
in C - a language design bug IMO).

The second definition means that nothing ouside the translation unit can
see the /name/ of the variable, but nothing stops a function in that
translation unit from returning its /address/ to a calling function,
which can then access it through that address.

But what's the whole point of file scope static in this case?
The name can't be seen outside of the translation unit anyway
unless it's explicitly imported (using "extern"), right?

Nope. You may for example run into trouble with implicit int.

If you declare your array (or any variable or function) at file
scope, they have _external_ linkage and are (potentially) visible
_everywhere_.
The static gives _internal_ linkage, i.e. visibility is possible
only at file scope.
So, if you either ignore or do not receive warnings due to implicit
int assumptions, it is possible that (by typo or ill chance) you
get an executable program which works up to the moment when you
really need it...
If everything which needs no external linkage has internal linkage,
then you will get an error at linking as the symbols cannot be
resolved.

I was wary because I read in a C book that "static" (file scope)
allows the compiler to do additional optimizations based on
the assumtion that the variable is only accessed in local scope.

Aha. Which C book?


Cheers
Michael
 
E

Emmanuel Delahaye

copx wrote on 26/03/05 :
Q1:
If an array is declared static in file A is it still valid to access
it from file B?

What do you meant by file ? An executable file (application) ? C-source
file ? Hard to undestand what you meant...

static qualifiying a data means that its duration is the program life.
I mean if a function form file A which returns a pointer to a

'form' ? Do you meant 'from' ? Beware, we are a lot here whom first
language is not English.
position inside of the array is called from file B can functions
in file B read/write to the array using this pointer?

As long as the pointed data is static, yes, but using static data is
often a bad practice.
I know that this works and doesn't produce a warning with
every compiler I've used but is this behaviour correct?
Yes.

The question could be stated differently: does "static" really
make the memory area allocated for the array "static"?

It makes its duration equal to the one of the program.
Q2:
Can I save/restore an array to/from disk like this:

int my_array[100];

fwrite(my_array, sizeof my_array, 1, out_file);

fread(my_array, sizeof my_array, 1, in_file);

Yes, but ...
Again, it works mighty fine for me but is it
valid/portable?

.... it's not portable. A simple change in your compiler configuration
(data alignment, for example) could produce an undefined behaviour. I
use this trick in a testing context (to save some configuration, or
simulate a backuped memory on embedded systems I work on), but not in
production code.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

I once asked an expert COBOL programmer, how to
declare local variables in COBOL, the reply was:
"what is a local variable?"
 
C

CBFalconer

copx said:
.... snip ...

But what's the whole point of file scope static in this case?
The name can't be seen outside of the translation unit anyway
unless it's explicitly imported (using "extern"), right?

Wrong. Without the 'static' the defining file has no way of
preventing external use of that function or object. With it, it
remains under control, and can only be passed out by explicit use,
such as as a parameter value.
I was wary because I read in a C book that "static" (file scope)
allows the compiler to do additional optimizations based on
the assumtion that the variable is only accessed in local scope.

Unless the local scope specifically passes it onwards. Any
occurances of this can be detected withing the one compilation
unit, so the compiler is justified.

All this barring the occurance of undefined behaviour.
 
C

copx

[snip]
Nope. You may for example run into trouble with implicit int.

If you declare your array (or any variable or function) at file
scope, they have _external_ linkage and are (potentially) visible
_everywhere_.

Ehm, I think there is a misunderstanding here. I meant this:

== f1.c ==

int my_array[100];


int main(void)
{
f2_func();

return 0;
}

=======

== f2.c ==

/* extern int my_array[100]; */

void f2_func(void)
{
my_array[0] = 1;

}

======

Compiled using GCC: gcc f1.c f2.c -o test.exe

Result:
f2.c: In function `f2_func':
f2.c:6: error: `my_array' undeclared (first use in this function)

If I remove the comment tags around the "extern" statement
everything compiles fine.
Without this explicit import no compiler I can think of would
compile this. That's what I meant.

So how is my_array "visible" in this case?
Aha. Which C book?

IIRC it was "C - Programmieren von Anfang an" by Helmut
Erlenkoetter (German book)

copx
 
C

copx

Emmanuel Delahaye said:
copx wrote on 26/03/05 :

What do you meant by file ? An executable file (application) ? C-source
file ? Hard to undestand what you meant...

How do you declare an array inside an executable file?!
Executables are created by the compiler and don't contain C syntax
constructs. Discussing their structure would be totally OT here so
I think it's rather easy to guess what I meant.
static qualifiying a data means that its duration is the program life.


'form' ? Do you meant 'from' ?

Of course.
As long as the pointed data is static, yes, but using static data is often
a bad practice.

Why?

copx
 
M

Michael Mair

copx said:
Ehm, I think there is a misunderstanding here. I meant this:

== f1.c ==
/* static
*/
int my_array[100];


int main(void)
{
f2_func();

return 0;
}

=======

== f2.c ==

/* extern int my_array[100]; */

void f2_func(void)
{
my_array[0] = 1;

}

======

Compiled using GCC: gcc f1.c f2.c -o test.exe

Result:
f2.c: In function `f2_func':
f2.c:6: error: `my_array' undeclared (first use in this function)

If I remove the comment tags around the "extern" statement
everything compiles fine.
Without this explicit import no compiler I can think of would
compile this. That's what I meant.

So how is my_array "visible" in this case?

Uncomment the static in f1.c and no extern int my_array[];
in this world can "help" you...

Implicit int can get you with functions.

BTW: If you want to be on the safe side with gcc for clc,
rather use gcc -Wall -std=c89 -pedantic -O :)

IIRC it was "C - Programmieren von Anfang an" by Helmut
Erlenkoetter (German book)

Thanks.


Cheers
Michael
 
M

Michael Mair

copx said:

This often can _unnecessarily_ affect reentrancy; example: strtok() vs.
strtok_r() in multithreaded applications. This is clearly a design error
as there is no _good_ reason for strtok() to store the pointer.
Similarly and more topically, this can hold for own applications:
Even if you think that there will be only one instance of a certain data
structure and that is better for data encapsulation or whatever to
handle all of it in one file, it is often better to give the user some
sort of handle to an opaque data type and provide ways to construct a
new instance -- whenever someone thinks it may be useful to have a
second instance, this is possible without any problems.
Even the classic
static int init=0;
if (!init) {
/* perform initialisation */
....
init = 1;
}
can turn ugly, if the initialisation depends on there being only one
scenario for which everything is to be initialised. If there are now
different scenarios, the data with static storage duration fits only
one.


Cheers
Michael
 
M

Martin Ambuhl

copx said:
Q1:
If an array is declared static in file A is it still valid to access
it from file B?

Yes, though a pointer (with the external linkage) that points to it.

Q2:
Can I save/restore an array to/from disk like this:
int my_array[100];
fwrite(my_array, sizeof my_array, 1, out_file);
fread(my_array, sizeof my_array, 1, in_file);

Yes, although the files need not be portable to a different environment.
 
A

Andrey Tarasevich

copx said:
Q1:
If an array is declared static in file A is it still valid to access
it from file B?

"Access" is a rather broad term. In general - yes.
I mean if a function form file A which returns a pointer to a
position inside of the array is called from file B can functions
in file B read/write to the array using this pointer?

Yes, of course.
I know that this works and doesn't produce a warning with
every compiler I've used but is this behaviour correct?
Yes.

The question could be stated differently: does "static" really
make the memory area allocated for the array "static"?

Yes, it does make it 'static'. But the only effect of 'static' that is
relevant to an object ("memory area", as you say) is that the storage
duration of this object becomes static, i.e. it exists as long as the
program runs. It has absolutely no effect on the "accessibility" of the
object. If you can "locate" that object form other point in your
program, you can access it without any concerns, regardless of where you
access it from. Returning a pointer to such an object (just like you
described above) is one way to locate it.

Accessibilty-related effects of 'static' do not apply to objects. They
apply to _identifiers_ of objects. An identifier declared as 'static' at
file scope gets internal linkage. This only means that this identifier
is not related in any way to identical identifiers in other translation
units. Note, that strictly speaking, this only changes the properties of
the identifier of the object and has ho effect on the properties of the
object itself. In other words, declaring an object as 'static' prevents
you from locating the corresponding object form other translation units
by using the "traditional" method: providing a declaration of the
identifier and expecting the compiler (and linker) to do the rest.
Q2:
Can I save/restore an array to/from disk like this:

int my_array[100];

fwrite(my_array, sizeof my_array, 1, out_file);

fread(my_array, sizeof my_array, 1, in_file);

Again, it works mighty fine for me but is it
valid/portable?

Well, it is valid, assuming that the level of portability/file format
consistency provided by this method is sufficient for your application.

The answer depends on the lifetime of the file you are trying to write/read.

This file definitely will not be cross-platform portable. I.e. if you
want to be able to save data by using this method on one platform and
then read it on the other (even into the same program compiled for
different platform), then you'll have to use different method of saving
and reading data. This one will not do.

If you don't really care about cross-platform portability, i.e. you are
limited to a single platform, still remember that this method will not
immediately provide any file format consistency between different
versions of your program. Tomorrow you decide to change 'int' to 'long'
and the data is no longer readable.

This method does provide a reasonable level of data consistency between
different sessions of the same program. I.e. if you are planning to save
this file and then expect to read it later into the very same
executable, it should work fine.

And finally, this method has absolutely no problems if the lifetime of
the file is limited to one session of the program (temporary swap file
is one example of such file). Actually, this is how it should be done in
this case.

What are your requirements?
 
B

Barry Schwarz

Q1:
If an array is declared static in file A is it still valid to access
it from file B?
I mean if a function form file A which returns a pointer to a
position inside of the array is called from file B can functions
in file B read/write to the array using this pointer?
I know that this works and doesn't produce a warning with
every compiler I've used but is this behaviour correct?
The question could be stated differently: does "static" really
make the memory area allocated for the array "static"?

A static object is initialized prior to program start-up and continues
to exist for the life of the program. It is therefore possible for
any function to reference that object anytime. The only two methods
of achieving such a reference that come to mind are external linkage
and a pointer, but maybe someone else can think of others.
Q2:
Can I save/restore an array to/from disk like this:

int my_array[100];

fwrite(my_array, sizeof my_array, 1, out_file);

fread(my_array, sizeof my_array, 1, in_file);

Again, it works mighty fine for me but is it
valid/portable?

It is not portable. Some machines are big-endian: some are
little-endian. Some use 2s complement; others use 1s complement. I
wouldn't be surprised if some use signed magnitude. On some systems,
an int is 32 bits; on others 16 bits; on some newer ones 64 bits.
fwrite and fread have no ability to compensate for any of these
differences.

As long as the function containing the fread was compiled and linked
with the same compiler and library as the function containing the
fwrite, I would expect it to continue working on a single system.



<<Remove the del for email>>
 
C

CBFalconer

copx said:
.... snip ...

Ehm, I think there is a misunderstanding here. I meant this:

== f1.c ==
int my_array[100];
int main(void)
{
f2_func();
return 0;
}

== f2.c ==

/* extern int my_array[100]; */
void f2_func(void)
{
my_array[0] = 1;
}
======

Compiled using GCC: gcc f1.c f2.c -o test.exe

Result:
f2.c: In function `f2_func':
f2.c:6: error: `my_array' undeclared (first use in this function)

If I remove the comment tags around the "extern" statement
everything compiles fine.
Without this explicit import no compiler I can think of would
compile this. That's what I meant.

As far as I am concerned the above is a misuse of the system. The
extern statement belongs in a f1.h file, which in turn specifies
what f1 exports. f2.c (and f1.c) should #include that .h file. I
assume this is your practice anyhow, but leaving the shortened
version around is likely to mislead newbies.

I would go so far as to say an extern statement in a .c file is a
sign of misuse.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top