Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!umcp-cs!chris From: chris@umcp-cs.UUCP (Chris Torek) Newsgroups: net.lang.c Subject: Re: C Coding Question Message-ID: <2973@umcp-cs.UUCP> Date: Fri, 15-Aug-86 20:58:44 EDT Article-I.D.: umcp-cs.2973 Posted: Fri Aug 15 20:58:44 1986 Date-Received: Sun, 17-Aug-86 07:13:05 EDT References: <248@killer.UUCP> <138@darth.UUCP> Reply-To: chris@umcp-cs.UUCP (Chris Torek) Organization: University of Maryland, Dept. of Computer Sci. Lines: 110 In article <138@darth.UUCP> gary@darth.UUCP (Gary Wisniewski) writes: >As far as your question 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 explain this more fully. Indeed it does, and I suggest you read it rather more carefully. 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'. In the (unquoted) original example, the array was a global 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 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu