Question: extern *array and array[] 
Author Message
 Question: extern *array and array[]

Hi!

I observed strange (?) behavior of the C compiler (SG IRIS, MIPS cc)

First I defined a global array (in the file "incl.h"):
int array[100];

and included that file in various routines and the 'main' program,
all modules in separate files.
The compiler told me I repeat the definition of "array" and the second
one is ignored.

OK, so I changed the "incl.h" file:

#ifdef MAIN_MODULE
  int array[100];
#else
  extern int *array;
#endif

and defined the MAIN_MODULE in only main.c The compiler stopped {*filter*}ing
but when I tried to do anything with the "array" in any routine other than
"main" I got "Segmentation fails" every time (That means "Illegal memory
reference" for non-UNIX people).

But when I changed the "extern int *array" to "extern int array[100]"
all seems to be ok.

W-H-Y ????

The array is declared globally. It exists in the memory when the "main"
module is executed. Routines should address that memory as an "extern"
pointer. Why they don't ? Why the first method (*array) is wrwong ??

Anthony



Wed, 29 May 1996 06:55:52 GMT  
 Question: extern *array and array[]

Quote:

> I observed strange (?) behavior of the C compiler (SG IRIS, MIPS cc)

> First I defined a global array (in the file "incl.h"):
> int array[100];

> OK, so I changed the "incl.h" file:

> #ifdef MAIN_MODULE
>   int array[100];
> #else
>   extern int *array;

Nope. array isn't a pointer to an integer, it is an array of integers.
You are confusing the fact that C lets you use the name of an array by
itself as a pointer to the first element of the array, but it doesn't
go any further than that.

Try:

#ifdef MAIN_MODULE
  int array [100];
#else
  extern int array [100];
#endif

Quote:
> #endif

> Anthony

--- Lee Crawford
    Thinking Machines Corporation



Thu, 30 May 1996 03:02:43 GMT  
 Question: extern *array and array[]

Quote:

>Hi!

>I observed strange (?) behavior of the C compiler (SG IRIS, MIPS cc)

>First I defined a global array (in the file "incl.h"):
>int array[100];

>and included that file in various routines and the 'main' program,
>all modules in separate files.
>The compiler told me I repeat the definition of "array" and the second
>one is ignored.

>OK, so I changed the "incl.h" file:

>#ifdef MAIN_MODULE
>  int array[100];
>#else
>  extern int *array;
>#endif

>and defined the MAIN_MODULE in only main.c The compiler stopped {*filter*}ing
>but when I tried to do anything with the "array" in any routine other than
>"main" I got "Segmentation fails" every time (That means "Illegal memory
>reference" for non-UNIX people).

>But when I changed the "extern int *array" to "extern int array[100]"
>all seems to be ok.

>W-H-Y ????

Repeat after me, everyone:  "ARRAYS ARE NOT POINTERS".  Please consult
the Frequently Asked Questions.

Dave Kristol



Thu, 30 May 1996 05:18:47 GMT  
 Question: extern *array and array[]

Quote:

>Hi!
>I observed strange (?) behavior of the C compiler (SG IRIS, MIPS cc)
>First I defined a global array (in the file "incl.h"):
>int array[100];
>and included that file in various routines and the 'main' program,
>all modules in separate files.
>The compiler told me I repeat the definition of "array" and the second
>one is ignored.

All variables defined outside a function are considered as global variables.
For every global variable, there is only one variable definition.  By
definition under ANSI C, the variable needs to be initialized to indicate
that is a varaible definition, not a variable declaration.  The memory is
allocated for it here and only once.  (I am sure that there are conventions
for declaring global variables, please refer to your favorite C books under
the "storage class section.")  The scope of the variable is from the end of
the variable definition to the end of the file.  Other places that are not
part of the scope of variable and wish to refer to it can use "extern"
keyword to extend its scope.

A valid global variable declaration will be the keyword "extern" follows
by the variable you wish to refer to but without the initialization.

Since you included the header file in all your files but did not indicate
which one was the variable definition, the compiler could not figure out
what was your intention.  It assumed that each variable declared inside
the header file is a variable definition.  Thus, the compiler complained.

A proper way of manipulating a global variable in this particular case
would be :

   - Declaring the array "array" outside a function with initialization.
     This variable should be placed in the file where you mainly use it.
     eg:
          int   array[100] = 0;

   - For other files that wish to refer to the variable, a variable
     declaration is needed to extend the scope of the variable.
     eg:

          extern int   array[100];

     Note that "extern" informs the compiler that the variable "array"
     is declared elsewhere.  If it cannot find a varaible definition,
     don't complain yet!  You are postponing the variable decalaraion
     error to the linking time.

     You may include the statement in one of your header file and include
     it each time you need.

Quote:
>OK, so I changed the "incl.h" file:
>#ifdef MAIN_MODULE
>  int array[100];
>#else
>  extern int *array;
>#endif
>and defined the MAIN_MODULE in only main.c The compiler stopped {*filter*}ing
>but when I tried to do anything with the "array" in any routine other than
>"main" I got "Segmentation fails" every time (That means "Illegal memory
>reference" for non-UNIX people).

In the #else part, you declared a variable of "pointer to int".  Its
definition was declared somewhere else.  Although the names of the two
variables were looked the same, the compiler treated them separately.
While you were using the variable, which was a pointer to int, it was
pointing no objects.  The pointer was initialized to NULL by default.
Thus, an error of segmentation fault was caused when you were trying to
access the pointer.

If the "extern" keyword was omitted when you declared the variable, the
same error message would have be generated for the same reason as your
first proposal.  However, since the "extern" keyword was proceded in each
declaration of the variable, the compiler would treat any one of them as
the variable definition and the rest as the variable declarations.  There
is no guarantee that which one will be chosen.

Quote:
>But when I changed the "extern int *array" to "extern int array[100]"
>all seems to be ok.
>W-H-Y ????
>The array is declared globally. It exists in the memory when the "main"
>module is executed. Routines should address that memory as an "extern"
>pointer. Why they don't ? Why the first method (*array) is wrwong ??
>Anthony

Lin.
--
Lin Hung-Ta



Thu, 30 May 1996 21:50:30 GMT  
 Question: extern *array and array[]

Quote:
> OK, so I changed the "incl.h" file:

> #ifdef MAIN_MODULE
>   int array[100];
> #else
>   extern int *array;
> #endif

> and defined the MAIN_MODULE in only main.c The compiler stopped {*filter*}ing
> but when I tried to do anything with the "array" in any routine other than
> "main" I got "Segmentation fails" every time (That means "Illegal memory
> reference" for non-UNIX people).

> But when I changed the "extern int *array" to "extern int array[100]"
> all seems to be ok.

From the comp.lang.c frequently-asked questions (FAQ) list:

Section 2. Arrays and Pointers

2.1:    I had the definition char a[6] in one source file, and in
        another I declared extern char *a.  Why didn't it work?

A:      The declaration extern char *a simply does not match the actual
        definition.  The type "pointer-to-type-T" is not the same as
        "array-of-type-T."  Use extern char a[].

        References: CT&P Sec. 3.3 pp. 33-4, Sec. 4.5 pp. 64-5.

Write me if you are unable to locate a copy of the FAQ list.

                                        Steve Summit



Thu, 30 May 1996 07:41:11 GMT  
 Question: extern *array and array[]


:>
:>Hi!
:>
:>I observed strange (?) behavior of the C compiler (SG IRIS, MIPS cc)
:>
:>First I defined a global array (in the file "incl.h"):
:>int array[100];
:>
:>and included that file in various routines and the 'main' program,
:>all modules in separate files.
:>The compiler told me I repeat the definition of "array" and the second
:>one is ignored.
:>
:>OK, so I changed the "incl.h" file:
:>
:>#ifdef MAIN_MODULE
:>  int array[100];
:>#else
:>  extern int *array;
:>#endif
:>
:>and defined the MAIN_MODULE in only main.c The compiler stopped {*filter*}ing
:>but when I tried to do anything with the "array" in any routine other than
:>"main" I got "Segmentation fails" every time (That means "Illegal memory
:>reference" for non-UNIX people).
:>
:>But when I changed the "extern int *array" to "extern int array[100]"
:>all seems to be ok.
:>
:>W-H-Y ????
:
:Repeat after me, everyone:  "ARRAYS ARE NOT POINTERS".  Please consult
:the Frequently Asked Questions.
:
:Dave Kristol

BTW, the conditional portion is totally unnecessary.  Just have the .h file
define the "extern int array[100]" and include it EVEN IN THE MAIN.  Then put
the "int array[100]" in the main.  You are allowed to have both extern and the
actual instantiation in a given module.  Of course, if you want all that stuff
in one place, the conditional compilation approach IS necessary

Dan



Sat, 01 Jun 1996 00:00:27 GMT  
 Question: extern *array and array[]

Quote:

>Hi!

>I observed strange (?) behavior of the C compiler (SG IRIS, MIPS cc)

>First I defined a global array (in the file "incl.h"):
>int array[100];

[problems omitted]

>OK, so I changed the "incl.h" file:

>#ifdef MAIN_MODULE
>  int array[100];
>#else
>  extern int *array;
>#endif

>and defined the MAIN_MODULE in only main.c The compiler stopped {*filter*}ing
>but when I tried to do anything with the "array" in any routine other than
>"main" I got "Segmentation fails" every time (That means "Illegal memory
>reference" for non-UNIX people).

>But when I changed the "extern int *array" to "extern int array[100]"
>all seems to be ok.

FAQ Section 2.1 and 2.2.  A pointer is not an array. One module thinks you
have an array and all the other modules think you have a pointer. You can't
lie to your compiler like that and get away with it :-).

Change the pointer declaration to "extern int array[];"

Quote:
>W-H-Y ????

>The array is declared globally. It exists in the memory when the "main"
>module is executed. Routines should address that memory as an "extern"
>pointer. Why they don't ? Why the first method (*array) is wrwong ??

>Anthony

--

Chris Volpe                             Phone: (518) 387-7766 (Dial Comm 8*833
GE Corporate R&D                    Fax:   (518) 387-6560



Sat, 01 Jun 1996 09:18:55 GMT  
 Question: extern *array and array[]

Quote:


>>int array[100];
>>and included that file in various routines and the 'main' program,
>>The compiler told me I repeat the definition of "array" and the second

        Why did you include the file in various ROUTINES?  Or did you
mean modules?  But in that case, it is highly unlikely the compiler would
have warned you - more likely it would have been the linker.

Quote:
>All variables defined outside a function are considered as global variables.
>For every global variable, there is only one variable definition.  By
>definition under ANSI C, the variable needs to be initialized to indicate
>that is a varaible definition, not a variable declaration.

        Oh, no.  A global object variable with an initializer or one
without the linkage specifier "extern" prepended to it classifies as a
definition.  Thus extern int i = 0; and int i; and static int i; are all
definitions. (This is really a simplification, I am assuming that no
variable is being declared more than once in the same file.)

Quote:
>The memory is
>allocated for it here and only once.  (I am sure that there are conventions
>for declaring global variables, please refer to your favorite C books under
>the "storage class section.")  The scope of the variable is from the end of
>the variable definition to the end of the file.  

        Actually the scope of the variable starts from the point of
occurrence of the *variable name* in the declaration.
        Thus int i = sizeof(i); is valid.
        I know, it matters not, still ....

Quote:
>Other places that are not
>part of the scope of variable and wish to refer to it can use "extern"
>keyword to extend its scope.

        Right.
        To elaborate, the "extern" keyword can also be used to refer to
a file-scope variable which has been hidden by a declaration in an outer
block;
        int i;
        int main(void){int i = 10; .... {extern int i;...}}

        The "i" in the innermost block will now refer to the i declared at
file-scope.  If you really are including a .h file in several _routines_,
you might just have to take this into consideration.

        (I never post on issues of programming style; so I will refrain from
pointing out that this type of usage is bad style.)

Quote:
>Since you included the header file in all your files but did not indicate
>which one was the variable definition, the compiler could not figure out
>what was your intention.  It assumed that each variable declared inside
>the header file is a variable definition.  Thus, the compiler complained.

        Doubtful.  More likely it was the linker that would have complained.
Can the compiler have enough intelligence to do this? Possible, of course,
but in practice, do such compilers exist?  Lint should help out, however.

Quote:
>A proper way of manipulating a global variable in this particular case
>would be :
>   - Declaring the array "array" outside a function with initialization.
>     This variable should be placed in the file where you mainly use it.
>     eg:
>          int   array[100] = 0;

        Ooops, what sort of an initialization is that?
        Do int array[100] = {0};
        An ANSI-conforming compiler should be able to accept just
        int array[100]; in place of this.

Quote:
>>OK, so I changed the "incl.h" file:
>>#ifdef MAIN_MODULE
>>  int array[100];
>>#else
>>  extern int *array;
>>#endif
>In the #else part, you declared a variable of "pointer to int".  Its
>definition was declared somewhere else.

        Actually there would be *no* definition for array (of type int *)
in this case.  This is undefined behaviour.  But I believe you are talking of
a typical UNIX environment, which, as you say, might end up taking any one
of the declarations as a definition.

        But as others have pointed out, his problem is that the #else
should have had extern int array[100];.

Quote:
>Although the names of the two
>variables were looked the same, the compiler treated them separately.
>While you were using the variable, which was a pointer to int, it was
>pointing no objects.  The pointer was initialized to NULL by default.
..
>However, since the "extern" keyword was proceded in each
>declaration of the variable, the compiler would treat any one of them as
>the variable definition and the rest as the variable declarations.  There
>is no guarantee that which one will be chosen.

        This also is doubtful.  If one of the extern int *array; declarations
is taken to be a definition (by the linker), it means the linker would have
two objects with the same name array (one of type int [100] and the other of
type int *).  Shouldn't the linker complain then and there itself?

        What looks to me more likely is that the compiler exports the
definition of array (int array[100]) from one file.  It also reports
unresolved external references of array from all other files (the compiler
thinks these are references to int *).  The linker does not know about
"C" types, so it just goes ahead and resolves all references to "array"
(which the compiler had coded to be references to int *) to refer to the
array "array" (ie., to int array[100]).  The code runs, and as explained
by Chris Volpe in a previous posting, crashes.

------
/* Pointers are, more often that not, pointlessly used. */

/* Ajoy Krishnan T,
   Software Engineer, Hughes Software Systems,
   New Delhi - 19, India.




Thu, 06 Jun 1996 17:01:00 GMT  
 Question: extern *array and array[]

Quote:

>> The scope of the variable is from the end of the variable
>> definition to the end of the file.  

>    Actually the scope of the variable starts from the point of
> occurrence of the *variable name* in the declaration.
>    Thus int i = sizeof(i); is valid.
>    I know, it matters not, still ....

Actually, the scope of the variable starts from the end of the
variable's _declarator_.  (A declarator is half an element in the
comma-separated list that is called a declaration.  The other,
optional, half is an '=' and an initializer.)

Thus,
        char i[23];
        main() {
                int i[ sizeof(i) ];
                return 0;
        }

is valid, and allocates an array of 23 integers.




Thu, 06 Jun 1996 20:14:23 GMT  
 Question: extern *array and array[]

Quote:


>>>int array[100];
>>>and included that file in various routines and the 'main' program,
>>>The compiler told me I repeat the definition of "array" and the second
>    Why did you include the file in various ROUTINES?  Or did you
>mean modules?

I did not, but the original poster did. :)
In fact, he included the header file to all his files.

Quote:
>But in that case, it is highly unlikely the compiler would
>have warned you - more likely it would have been the linker.

Since the linker is normally invoked by a C compiler automatically, it
is often to say that an error was generated by the compiler in the first
place.

Quote:
>>definition under ANSI C, the variable needs to be initialized to indicate
>>that is a varaible definition, not a variable declaration.
>    Oh, no.  A global object variable with an initializer or one
>without the linkage specifier "extern" prepended to it classifies as a
>definition.  Thus extern int i = 0; and int i; and static int i; are all
>definitions.

I did say that "according to ANSI C definition" though.  Certainly, there
are other conventions.

Quote:
>>The scope of the variable is from the end of the variable definition to
>>the end of the file.  
>    Actually the scope of the variable starts from the point of
>occurrence of the *variable name* in the declaration.
>    Thus int i = sizeof(i); is valid.
>    I know, it matters not, still ....

okay!  However, that was I had been told as a rule during the implementation
of a subset of a C compiler.  I just have checked the notes again though.
Besides, shouldn't the declaration of "i" be finished even though the
declaration part has not actually reached to the end?  "= sizeof(i)" is part
of its initialization, isn't?

[ comments about extension of global variables' scope deleted. ]
[ other stuff deleted as well. ]

Quote:
>>A proper way of manipulating a global variable in this particular case
>>would be :
>>   - Declaring the array "array" outside a function with initialization.
>>     This variable should be placed in the file where you mainly use it.
>>     eg:
>>          int   array[100] = 0;
>    Ooops, what sort of an initialization is that?
>    Do int array[100] = {0};

sorry! A typing mistake. :)

Quote:
>    An ANSI-conforming compiler should be able to accept just
>    int array[100]; in place of this.

Surely, this would be accepted by an ANSI-conforming compiler.  However,
the compiler would probably have to wait until the end of the file or
the link time to decide whether this is a definition or a declaration.
Thus, it is better to explicitly initialize the variable while declaring
it.  This makes both you and the compiler knows this is definition for
sure.

[ stuff deleted again. ]

Quote:
>    This also is doubtful.  If one of the extern int *array; declarations
>is taken to be a definition (by the linker), it means the linker would have
>two objects with the same name array (one of type int [100] and the other of
>type int *).  Shouldn't the linker complain then and there itself?
>    What looks to me more likely is that the compiler exports the
>definition of array (int array[100]) from one file.  It also reports
>unresolved external references of array from all other files (the compiler
>thinks these are references to int *).  The linker does not know about
>"C" types, so it just goes ahead and resolves all references to "array"
>(which the compiler had coded to be references to int *) to refer to the
>array "array" (ie., to int array[100]).  The code runs, and as explained
>by Chris Volpe in a previous posting, crashes.

sorry!  My explanation most likely was not appropriate in this case.
I am sorry for the confusion that I have mode in my previous article.

Quote:
>------
>/* Pointers are, more often that not, pointlessly used. */
>/* Ajoy Krishnan T,
>   Software Engineer, Hughes Software Systems,
>   New Delhi - 19, India.



Lin.
--
Lin Hung-Ta



Sat, 08 Jun 1996 16:00:14 GMT  
 Question: extern *array and array[]

Quote:




>>>> The scope of the variable is from the end of the variable
>>>> definition to the end of the file.  

>>>    Actually the scope of the variable starts from the point of
>>> occurrence of the *variable name* in the declaration.
>>>    Thus int i = sizeof(i); is valid.
>>>    I know, it matters not, still ....
>>Actually, the scope of the variable starts from the end of the
>>variable's _declarator_.  (A declarator is half an element in the
>>comma-separated list that is called a declaration.  The other,
>>optional, half is an '=' and an initializer.)
>Yep! This is what I thought, too.
>>Thus,
>>        char i[23];
>>        main() {
>>                int i[ sizeof(i) ];

                              ^... the scope of array i is still active
                                   at this point.

Quote:
>>                return 0;
>>        }
>>is valid, and allocates an array of 23 integers.
>I am not quite sure about this one.
>Could someone please explain?

Actually, the size of i inside the block will be 92 byets if the size
of "int" is allocated to 4 bytes.  The "i" inside the sizeof() operator
referred to the one declared outside the main() function since the
declaration of "i" in the function body has not been finished yet.
Thus, the scope of the global variable "i" is still active at that point.

- Show quoted text -

Quote:

>Lin.
>--
>Lin Hung-Ta




Sat, 08 Jun 1996 16:46:25 GMT  
 Question: extern *array and array[]

Quote:



>>> The scope of the variable is from the end of the variable
>>> definition to the end of the file.  

>>        Actually the scope of the variable starts from the point of
>> occurrence of the *variable name* in the declaration.
>>        Thus int i = sizeof(i); is valid.
>>        I know, it matters not, still ....
>Actually, the scope of the variable starts from the end of the
>variable's _declarator_.  (A declarator is half an element in the
>comma-separated list that is called a declaration.  The other,
>optional, half is an '=' and an initializer.)

Yep! This is what I thought, too.

Quote:
>Thus,
>    char i[23];
>    main() {
>            int i[ sizeof(i) ];
>            return 0;
>    }
>is valid, and allocates an array of 23 integers.

I am not quite sure about this one.
Could someone please explain?

Lin.
--
Lin Hung-Ta



Sat, 08 Jun 1996 16:08:53 GMT  
 
 [ 25 post ]  Go to page: [1] [2]

 Relevant Pages 

1. extern *array, array[] - again.

2. char array (array of array...) question

3. Question about adding an array to existing array.

4. size of array in extern declaration?

5. how to extern an array.

6. extern'ing arrays

7. extern char array

8. Global and Extern Pointers, Arrays

9. sizeof extern array

10. How to do: extern ARRAY matrix[];

11. Question: extern char * versus extern char[]

12. array question - beginner question

 

 
Powered by phpBB® Forum Software