Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!samsung!munnari.oz.au!metro!wolfen!pejn From: pejn@wolfen.cc.uow.oz (Paul Nulsen) Newsgroups: comp.lang.c Subject: Re: extern char *foo vs. extern char foo[] Summary: Not the same at all Message-ID: <6263@wolfen.cc.uow.oz> Date: 31 May 90 00:01:02 GMT References: <1990May30.001219.23564@uunet!unhd> Reply-To: pejn@wolfen.UUCP (Paul Nulsen) Distribution: comp Organization: Uni. of Wollongong, NSW, Australia. Lines: 82 In article <1990May30.001219.23564@uunet!unhd> rg@unhd.unh.edu.UUCP (Roger Gonzalez ) writes: >According to K&R, there should be no difference between the two extern >defs in my subject header. ... Here's a >more detailed example of what I mean: > >FILE #1: > > char hello[100]; > main() > { > strcpy(hello, "Hello, world.\n"); > printf("In main(), hello is at %06X\n", hello); > foo(); > } > >FILE #2: > > extern char *hello; > foo() > { > printf("In foo(), hello is at %06X\n", hello); > } > >... I stopped the output at the assembler stage, and >looked at the .s files for file #2 (using the first method of correction, >namely declaring extern char hello[]), did a diff, and guess what I found? > >> >mov hello, (sp%) I know, I know. This isn't *quite* what I >< found, but I'm typing it from memory, and its >mov &hello, (sp%) close enough for government work. > >Aha! Zees eez very wrong! The declaration: char *hello; tells the compiler to reserve storage for a one pointer to char. It also announces that that (global) storage space will be referred to by the name hello. The declaration: extern char *hello; announces that this has been done somewhere else your program. The statement: char hello[100]; tells the compiler to reserve storage for 100 chars and that this storage is to be referred to by the name hello. If you inspect the assembler output you will see that this is indeed how it has interpreted your program. The two are not equivalent. The confusion over the difference between char * and char [] is very common. I believe that it is due to the way that C handles the passing of array arguments to functions. As rule C passes arguments by value, but it passes an array argument by reference. This means that passing a char [] to a function results in the creation of a char * on the stack. As a result, the programmer is permitted to refer to passed array as either char * or char [], and the two types of reference are treated in much the same way within the function. Another anomaly that we get from this is illustrated by the fragment: char *pointer_array[] = {"One", "Two", "Three"}; char two_d_array[3][10]; main () { int i,j; for (i = 0; i < 3; i++) { strcpy (two_d_array[i], pointer_array[i]); } /* Now (with i,j in bounds) pointer_array[i][j] == two_d_array[i][j] */ /* but these two references are quite different and generate different */ /* code */ ... }