Path: utzoo!news-server.csri.toronto.edu!rutgers!mit-eddie!andante!alice!ark From: ark@alice.att.com (Andrew Koenig) Newsgroups: comp.lang.c Subject: Re: Is this ok?? Keywords: pointer initialization Message-ID: <20043@alice.att.com> Date: 10 Mar 91 04:56:11 GMT References: <1991Mar08.191107.23161@pilikia.pegasus.com> Reply-To: ark@alice.UUCP () Distribution: comp Organization: AT&T Bell Laboratories, Liberty Corner NJ Lines: 117 John E. Davis asked a question about pointers in C. Art Neilson reponded with a rather nasty criticism of the question. The trouble with this sort of criticism is that it can be embarrassing if the criticism is mistaken. Let's take a look at the original program and the criticism with an eye towards sorting it all out. In what follows, >> precedes comments by Davis (article ) and > precedes comments by Neilson (article <1991Mar08.191107.23161@pilikia.pegasus.com>). >> #include >> void fm2(s) >> char **s; > ^ here we go yet again, this parameter doesn't match > what you're trying to pass in from fm1(). >> { >> *s = "Hello\n"; > ^ you can't do this. s points nowhere. > besides, you need to do strcpy(s, "Hello"), > the way you are initializing *s is wrong. > >> } Is it actually true that s points nowhere? It's hard to say without looking at the caller of fm2; we'll come to that presently. If we assume that s points somewhere, though, there is nothing wrong with saying *s = "Hello\n"; A string literal is essentially the "name" of an otherwise unnamed initialized character array. Thus the assignment above would make the pointer addressed by s point to the initial character of this array. That brings us back to the previous question: where does s point? Let's look at fm2's caller: >> void fm1(s) >> char **s; > ^ this formal parameter to fm1 doesn't match what > you're passing it from main. > >> { >> char *ss; >> fm2(&ss); > ^ here we go again. the & is not necessary. > >> *s = ss; >> } Aha! fm2 is passed the address of the local variable "ss" in function fm1. That variable is of type "char *" so its address is of type "char **", which matches the type of the formal parameter of fm2. Apparently that criticism is incorrect. We are now in a position to understand the assignment to *s in fm2; since s is the address of the variable ss in fm1, *s is that variable itself. Thus after executing this assignment, variable ss in fm1 will point to the initial character of "Hello\n". I see nothing wrong with that so far. Indeed, the second criticism in fm1 is also seen to be incorrect; the & is indeed necessary (else the call would not be type-safe) and the call fm2(&ss); has the same effect as ss = "Hello\n"; Now let's look at the first criticism in fm1, namely that the formal parameter to fm1 doesn't match what's passed from main. To check this, we need to look at main: >> int main() >> { >> char *s; >> >> fm1(&s); > ^why are you passing "address of" s ? > s is already an address, remove the &. > >> (void) fputs(s,stdout); >> return(0); >> } Variable s in main is of type "char *" so its address is of type "char **". That is the same type as the formal parameter to fm1, so the criticism of fm1 is incorrect. The criticism of "main" answers its own question: if fm1 were passed s rather than &s, the call would indeed be incorrect. What happens inside fm1? If we replace the call to fm2 by the assignment having the same effect, we get this: char *ss; ss = "Hello\n"; /* the effect of the call to fm2 */ *s = ss; What is *s? It's exactly the variable "s" in main. Thus, the effect of main should be as if its body were written: char *s; s = "Hello\n"; /* the effect of the call to fm1 */ (void) fputs(s,stdout); return(0); I don't see anything wrong with any of this, so I suspect a compiler bug. -- --Andrew Koenig ark@europa.att.com