Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!purdue!haven!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.lang.c Subject: Re: Why doesn't this work? Message-ID: <16508@mimsy.UUCP> Date: 23 Mar 89 10:31:57 GMT References: <1309@dukeac.UUCP> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 126 In article <1309@dukeac.UUCP> sbigham@dukeac.UUCP (Scott Bigham) writes: >typedef char **Block; > >Block > b1 ={"this","that"}, > b2={"yes","no"}, > B[]={b1,b2}; It does not work because b1, b2, and B[any] have type `pointer to pointer to char' and the first two { ... } lines are not valid initialisers for pointer-to-pointer-to-char, and indeed are not valid initialisers for anything but array-of-pointer-to-char. (The third initialiser would be correct if the first two were not rejected earlier.) The following rerun makes various salient points. From: chris@umcp-cs.UUCP (Chris Torek) Newsgroups: net.lang.c Subject: Re: C Coding Question Date: 16 Aug 86 00:58:44 GMT In many articles many USENET posters assert that >... about "char *help[]" and "char **help": the two forms are IDENTICAL >to virtually every C compiler (that's worth its salt). Arrays in C are >merely special cases of pointers. In other words, both forms are correct. NO! Ai! This has been asserted far too often. Arrays and pointers are not at all the same thing in C! Section 5.3 of K&R 1st ed. has this to say about it: The correspondence between indexing and pointer arithmetic is evidently very close. ... The effect is that an array name *is* a pointer expression. (p. 94) This does not say that arrays and pointers are *the same*. There is one difference between an array name and a pointer that must be kept in mind. Aha! See p. 94 for that difference. As formal parameters in a function defintion, char s[]; and char *s; are exactly equivalent.... (p. 95) Here they *are* the same---but note the qualifier: `As formal parameters'. The array must not be a global or static variable. There is one other thing which, I guess, adds to this confusion. Both of the following are legal global declarations in C: char msg0[] = "Hello, world"; char *msg1 = "Hello, world"; Given both declarations, printf("%s\n", msg0); and printf("%s\n", msg1); produce the same output. Yet msg0 and msg1 are not the same: printf("%d %d\n", sizeof (msg0), sizeof (msg1)); prints 13 4 on a Vax; for msg0 is an array, and msg1 is a pointer. The code generated for the two declarations is different: /* edited assembly output from ccom */ .data # Switch to data segment. .globl _msg0 # The array ... _msg0: .asciz "Hello, world" # and here it is. .data 2 # Switch to alternate data segment. L12: .asciz "Hello, world" # The object to which msg1 will point. .data # Back to regular data segment. .globl _msg1 # The pointer ... _msg1: .long L12 # which points to the object. String constants comprise two special cases in the compiler. The first case is when the constant appears anywhere *except* as an initialiser for a `char' array. Here the compiler uses the alternate data segment to suddenly `create' a new array, initialised to the string text; it then generates a pointer to that array. In the second case the string constant is generated in the primary data segment, and `is' the array being initialised: the constant is `unwrapped' into an aggregate initialisation. The second case is actually the more `conventional' of the two; other aggregates cannot be created at run time: int a[] = { 0, 1, 2, 3 }; is legal only outside functions. What seems surprising to some is that the same is true of char s[] = "foo"; because, unwrapped, this is equivalent to char s[] = { 'f', 'o', 'o', '\0' }; ---even though char *s = "foo"; is legal anywhere a declaration is legal. Ah, if only C had aggregate initialisers! -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris