kuan@iris.ucdavis.edu (Frank [Who me?] Kuan) (09/22/90)
In file "a.c", I declare: char targ[128]; In file "b.c" I do: extern char *targ; Result: I got massive errors. When I source debugged it, it told me that the char pointer "targ" was 0x000000. By chance, I tried redeclaring it as "extern char targ[]" and the problem was fixed. Now, I always thought that "targ[]" and "char *targ" were equivalent. I have several places in my program where I use those two notations interchangeably, and this was the first time I've ever had a problem with it. Could a C wizard explain to me what I'm doing wrong and what the correct practice is so I don't run into these horrible bugs again? Thanks in advance. - f
eyal@echo.canberra.edu.au (Eyal Lebedinsky) (09/22/90)
In article <8103@aggie.ucdavis.edu> kuan@iris.ucdavis.edu (Frank [Who me?] Kuan) writes: > >In file "a.c", I declare: >char targ[128]; > >In file "b.c" I do: >extern char *targ; > >Result: I got massive errors. When I source debugged it, it told me >that the char pointer "targ" was 0x000000. > >By chance, I tried redeclaring it as "extern char targ[]" and >the problem was fixed. > >Now, I always thought that "targ[]" and "char *targ" were equivalent. >I have several places in my program where I use those two notations >interchangeably, and this was the first time I've ever had a problem >with it. > >Could a C wizard explain to me what I'm doing wrong and what the >correct practice is so I don't run into these horrible bugs again? No wizard, but here it is. The compiler will allow you to mix the array/pointer notation and will get it right. To do this it needs to know what the reality is. In other words, once you declare the array/pointer correctly, you cac then access it either way. The generates assembler to access a pointer is not the same as accessing an array. C has some 'promotion rules' which define the behaviour of the expression array[index] and pointer[index]: the name of an array is promoted to 'a pointer to the first element'. Anyway, the short answer is YOU MUST DECLARE IT CORRECTLY, CANNOT MIX POINTER/ARRAY IN THE DECLARATION. BTW, in function arguments there is another promotion rule which allows you to mix pointer/array here. Any clearer now ? hope so.> >Thanks in advance. > >- f -- Regards Eyal
cpcahil@virtech.uucp (Conor P. Cahill) (09/22/90)
In article <8103@aggie.ucdavis.edu> kuan@iris.ucdavis.edu (Frank [Who me?] Kuan) writes: >Now, I always thought that "targ[]" and "char *targ" were equivalent. >I have several places in my program where I use those two notations >interchangeably, and this was the first time I've ever had a problem >with it. They are equivalent (with respect to referencing data) for just about all cases EXCEPT for global variables. The reason that they are equivalent for function calls is that the array is acutally converted to (and passed as) a pointer. For global variables "targ" will represent a location in memory assigned by the linker. Any mention of the variable "targ" will be replaced by an absolute memory location by the linker. The contents of this memory location will differ depending upon the declaration of targ. If it is declared as "char * targ;", the compiler will expect a character pointer at this location If it is declared as "char targ[xx];" the compiler will expect a character arrry starting at this location >correct practice is so I don't run into these horrible bugs again? The correct practice is that global declarations and references much match exactly (except initializations of course). -- Conor P. Cahill (703)430-9247 Virtual Technologies, Inc., uunet!virtech!cpcahil 46030 Manekin Plaza, Suite 160 Sterling, VA 22170
jdarcy@encore.com (Jeff d'Arcy) (09/23/90)
In case nobody else has mentioned it (I came in late on this one), there is a difference between *x and x[] besides allocation and semantics for globals: sizeof(). A lot of times I've been tempted to write static char *message = "hello"; /* ... */ write(fd,message,sizeof(message)); within a routine. Obviously this won't work, but static char message[] = "hello"; will. It's amazing how easy it is to forget this little detail and how many times I've seen it done. Usuaully it's much more insidious than this example. -- Jeff d'Arcy, Generic Software Engineer - jdarcy@encore.com Nothing was ever achieved by accepting reality
throopw@sheol.UUCP (Wayne Throop) (09/23/90)
> From: kuan@iris.ucdavis.edu (Frank [Who me?] Kuan) > Now, I always thought that "targ[]" and "char *targ" were equivalent. As an aside, I took a survey a while back about this. It turns out that the reason for this frequent misconception is (essentially) poor teaching and poor reference materials. Essentially teachers TEACH people this, sometimes inadvertantly. My main suggestion to Frank Kuan is to read the "Frequently Asked Questions" posting when it comes around again. You will find the answer to the [] vs * question, along with a slew of other things that teachers (apparently) often mis-teach students. > From: cpcahil@virtech.uucp (Conor P. Cahill) > They are equivalent (with respect to referencing data) for just about all > cases EXCEPT for global variables. And automatic variables. And objects in the malloc/free heap. And variables with static visibility/persistence. I think that Conor may be taking "equivalent" to mean that the two objects can appear in lexically identical references. Which is correct. But the semantics which apply to the two cases are distinct. The fact is, there is only ONE place where the two are semantically equivalent, and that is as definitions of formal parameters. Again, see the FAQ for details, but code generated for subscripting, "sizeof" results, and in essence *everything* is different for these two declarations, with only the one exception. So, while Conor is technically correct, I think it is much more important to emphasize the differences here, rather than the similarities. The similarities are superficial, and the differences important, fundamental, and often overlooked. -- Wayne Throop <backbone>!mcnc!rti!sheol!throopw or sheol!throopw@rti.rti.org
tih@barsoom.nhh.no (Tom Ivar Helbekkmo) (09/23/90)
In a fit of pure idiocy, I wrote:
> global unsigned long avail[A,B,C];
and as several people have pointed out already, that's not how you declare
a multi-dimensional array in C. *blush*
What can I say? I'd just resurfaced after a lot of FORTRAN programming
involving arrays, though... Still, I must have been temporarily blind.
Thanks to all who took the time to point this out to me! :-)
-tih
--
Tom Ivar Helbekkmo, NHH, Bergen, Norway. Telephone: +47-5-959205
tih@barsoom.nhh.no, thelbekk@norunit.bitnet, edb_tom@debet.nhh.no
enag@ifi.uio.no (Erik Naggum) (09/24/90)
Let me venture a concise explanation to this difference: extern char *arr declares an object, containing a pointer to a character extern char arr[] declares a constant pointer to a character Hope this helps. -- [Erik Naggum] Naggum Software; Gaustadalleen 21; 0371 OSLO; NORWAY I disclaim, <erik@naggum.uu.no>, <enag@ifi.uio.no> therefore I post. +47-295-8622, +47-256-7822, (fax) +47-260-4427
chris@mimsy.umd.edu (Chris Torek) (09/24/90)
In article <ENAG.90Sep23231057@hild.ifi.uio.no> enag@ifi.uio.no (Erik Naggum) writes: >Let me venture a concise explanation to this difference: > > extern char *arr declares an object, containing a > pointer to a character > > extern char arr[] declares a constant pointer to a > character Concise, yes; correct, no. Both declare objects; the latter declares an object that is an array. It IS an array; it is NOT a pointer. The confusion occurs because objects that are arrays are *converted into* VALUES that are pointers, whenever the value is called for. In other words, if `x' is an array, one might try to describe the `value' of x as the values of all elements of x. (Mathematically, `the value of x' would be `the set of all values x[i] such that x[i] exists.') If `x' is a large array, that would be an awful lot of values. Most computers can only work on one or two or maybe a dozen or a hundred values at a time, and x could easily contain several thousand values. So the C language does not provide a way to talk about this kind of `value of x'. Instead, when you ask for the `value' of x (where x is some array), the language gives you a convenient place to start if you wanted to go about finding all of the (possibly many thousands of) values x[i]. Indeed, it tells you where the very first such value is stored. In other words, it changes an <object, array 8000 of int, x> into a <value, pointer to int, &x[0]> and you can then go about fetching all 8000 values yourself, using this pointer. Since it changes the <object, array N of T> into a <value, pointer to T>, the result is not something you can change---you cannot, after the fact, change the place the system decided to store the array, at least not in the C language proper (assembly language hacking is another matter)---and this leads people to (incorrectly) decide that an array `is' a constant. It is nothing of the sort: an array IS an array. It is not something you can change, but it is also not a constant, as the (nonportable) program #include <stdio.h> void f(v) int v; { int arr[1000]; printf("%lx\n", (long)arr); if (v) f(0); } int main() { f(1); return 0; } will demonstrate on those systems that do not remove the tail recursion. (You will get two different numbers.) (N.B.: By switching from one meaning to another, you *can* say that an array `is a constant'. In C, as in many languages, `constant' is a language concept meaning `a value that never changes'. But the location of an array *can* change, at least if that array is automatic. You, as a programmer, may not change it; the system can. If you decide that you want the word `constant' to mean `I, as a programmer, may not change this', then of course the location is *that* sort of `constant'. But you will confuse everyone else---as I probably just did with this whole aside.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
enag@ifi.uio.no (Erik Naggum) (09/25/90)
In article <ENAG.90Sep23231057@hild.ifi.uio.no>, Erik Naggum (I) wrote: > Let me venture a concise explanation to this difference: > > extern char *arr declares an object, containing a > pointer to a character > > extern char arr[] declares a constant pointer to a > character In article <26680@mimsy.umd.edu>, Chris Torek (you) write: > Concise, yes; correct, no. Both declare objects; the latter declares > an object that is an array. It IS an array; it is NOT a pointer. The > confusion occurs because objects that are arrays are *converted into* > VALUES that are pointers, whenever the value is called for. Rather, "char arr[14]" declares an array, but "extern char arr[]" only declares that "arr" is some constant pointer the value of which is to be resolved by the linker. "char *arr" declares an object, and "extern char *arr" declares that "arr" is some object the address of which is to be resolved by the linker. I think you overlooked the "extern" up there. I follow your arguments for locally declared objects down to the finest details. Strictly speaking, I have to correct my own explanation: Neither declares objects, but instead object names with types and values of that type to be resolved by the linker (or later, anyhow). I hope this gets a "concise, no; correct, yes" response, at least. -- [Erik Naggum] Naggum Software; Gaustadalleen 21; 0371 OSLO; NORWAY I disclaim, <erik@naggum.uu.no>, <enag@ifi.uio.no> therefore I post. +47-295-8622, +47-256-7822, (fax) +47-260-4427
karl@haddock.ima.isc.com (Karl Heuer) (09/25/90)
In article <ENAG.90Sep25005953@hild.ifi.uio.no> enag@ifi.uio.no (Erik Naggum) writes: >Rather, "char arr[14]" declares an array, but "extern char arr[]" only >declares that "arr" is some constant pointer the value of which is to >be resolved by the linker. I disagree. Both are *declarations*; the one without "extern" happens to also serve as a *definition*. So I would say that "char arr[14]" declares an array and (being a definition) also causes storage to be allocated for it (probably by a linker), while "extern char arr[]" declares an array and causes the name "arr" to be associated with the same storage that was allocated under that name in some other compilation unit. There are no pointers (in the C sense) involved here, at least not until such time as the name "arr" is used in an rvalue context. Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
bengsig@oracle.nl (Bjorn Engsig) (09/25/90)
In article <26680@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) once again
explained why 'extern char *arr' and 'extern char arr[]' isn't the same thing.
I admire you, Chris, for having so much patience. The answer I had expected was
RTFM or RTFFAQ.
--
Bjorn Engsig, Domain: bengsig@oracle.nl, bengsig@oracle.com
Path: uunet!mcsun!orcenl!bengsig
From IBM: auschs!ibmaus!cs.utexas.edu!uunet!oracle!bengsig
eyal@echo.canberra.edu.au (Eyal Lebedinsky) (09/26/90)
Following the discussion, I feel that two issues are beeing mixed: 1 - an object is either an array OR a pointer with no ambiguity. 2 - a reference to an object can mix array/pointer notation. If an object is declared/defined so as to lead the compiler to see it as an array then all references will follow this notion, same with pointer. So: a[4] can be used to refer to 'a' (regardless if 'a' is arr/point) and the appropriate code will be emitted depending on THE TYPE of a. '*(a+4)' will do the same. The C syntax/semantics defines this clearly. -- Regards Eyal
seanf@sco.COM (Sean Fagan) (09/27/90)
In article <ENAG.90Sep25005953@hild.ifi.uio.no> enag@ifi.uio.no (Erik Naggum) writes: >Rather, "char arr[14]" declares an array, but "extern char arr[]" only >declares that "arr" is some constant pointer the value of which is to >be resolved by the linker. *NO NO NO NO*! 'extern char arr[]' does *not* declare, in any way, shape, or form, a pointer. What it *does* declare is the label of a block of memory (size currently unknown), which will be (hopefully) resolved at link time. The difference between extern char arr[]; and extern char *ptr; is that the first one is not indirected to get the address; the other one is. That is, ptr is actually a double-indirect variable: one indirection to get its value, and another one to dereference it. arr, on the other hand, is just indirected once, to get it's value (which is arr[0]). -- -----------------+ Sean Eric Fagan | "Never knock on Death's door: ring the bell and seanf@sco.COM | run away! Death really hates that!" uunet!sco!seanf | -- Dr. Mike Stratford (Matt Frewer, "Doctor, Doctor") (408) 458-1422 | Any opinions expressed are my own, not my employers'.
enag@ifi.uio.no (Erik Naggum) (10/03/90)
In article <7920@scolex.sco.COM> seanf@sco.COM (Sean Fagan) writes: In article <ENAG.90Sep25005953@hild.ifi.uio.no> enag@ifi.uio.no (Erik Naggum) writes: >Rather, "char arr[14]" declares an array, but "extern char arr[]" only >declares that "arr" is some constant pointer the value of which is to >be resolved by the linker. *NO NO NO NO*! 'extern char arr[]' does *not* declare, in any way, shape, or form, a pointer. I'm sorry for all the confusion my severely overloaded use of "constant" has caused. I have been corrected by what seems like all the ANSI C programmers in the known and not-so-known universe, and they all point out that we have a "char * const ptr" construct, which I have always thought was a horrible abomination, and thus totally forgot that people could think I meant. Other than this unfortunate choice of words, we all agree. Relax, all. My mailbox is off limits, already. Next time I want to overload, I'll post to comp.lang.c++. -- [Erik Naggum] Naggum Software; Gaustadalleen 21; 0371 OSLO; NORWAY I disclaim, <erik@naggum.uu.no>, <enag@ifi.uio.no> therefore I post. +47-295-8622, +47-256-7822, (fax) +47-260-4427