scanf("%s", string) or scanf("%s", &string)? Both work, yet...
Author |
Message |
Scott Andre #1 / 9
|
 scanf("%s", string) or scanf("%s", &string)? Both work, yet...
Both work with gcc, cc, Mac THINK and CodeWarrior, still I can't believe both variants are semantically equivalent in C! BTW, I am an Ada semi-guru in real life. But I program exclusively in "high-style" C now, using # define's to obtain Ada front end. The ADAMANT project I conduct is to provide a convenient preprocessor level, semi-Ada "look and feel" in C. --
"Ceterum censeo Carthaginem esse delendam"-
|
Sat, 15 Nov 1997 03:00:00 GMT |
|
 |
Denizen of the De #2 / 9
|
 scanf("%s", string) or scanf("%s", &string)? Both work, yet...
Quote:
>Both work with gcc, cc, Mac THINK and CodeWarrior, still I can't >believe both variants are semantically equivalent in C! BTW, >I am an Ada semi-guru in real life. But I program exclusively in "high-style" >C now, using # define's to obtain Ada front end. The ADAMANT project I >conduct is to provide a convenient preprocessor level, semi-Ada >"look and feel" in C.
I assume that you have declared string as something like: char string[SIZE]; If so, then string has the type "array of SIZE chars". When you pass string as an argument to scanf, it "decays" into a pointer to the initial element of the array, which has type "pointer to char". Note that the actual value of the pointer will be the base address of the inital element. If you pass &string as an argument to scanf, string does NOT "decay" into a pointer, so the expression &string has type "pointer to array of SIZE chars". The important thing here is that the value of this pointer is the base address of the array, WHICH IS ALSO THE BASE ADDRESS OF THE INITIAL ELEMENT. In other words, the two pointers have the same address value, even though they are different types. Now scanf expects to receive a pointer of the first type as its argument (a pointer to char), so techically the second is not quite right. However, since scanf takes a variable number of arguments, the compiler is unable to do type checking, so it probably won't even give you a warning. In any case, they will both work, since all scanf does is look at the address value, regardless of the type. -Jon
|
Sat, 15 Nov 1997 03:00:00 GMT |
|
 |
Jeffrey N Woodfo #3 / 9
|
 scanf("%s", string) or scanf("%s", &string)? Both work, yet...
: Both work with gcc, cc, Mac THINK and CodeWarrior, still I can't : believe both variants are semantically equivalent in C! BTW, : I am an Ada semi-guru in real life. But I program exclusively in "high-style" : C now, using # define's to obtain Ada front end. The ADAMANT project I : conduct is to provide a convenient preprocessor level, semi-Ada : "look and feel" in C. Assuming that "string" was declared as a char*, wouldn't &string be the address of the pointer, and not the location of where the incoming data is to be stored? This does not give a segmentation fault error? I'm surprised. -Jeff -- Jeffrey N. Woodford | "All the world's indeed a stage, And we are merely
Physical Chemistry Graduate Student, University of Nebraska - Lincoln
|
Sun, 16 Nov 1997 03:00:00 GMT |
|
 |
Eric Roo #4 / 9
|
 scanf("%s", string) or scanf("%s", &string)? Both work, yet...
Quote:
>Both work with gcc, cc, Mac THINK and CodeWarrior, still I can't >believe both variants are semantically equivalent in C! BTW,
Yes, both are semantically equivalent -- in this particular case. Read chapter 2 of the FAQ. -- ---- Eric "If anyone finds this offensive, I am prepared not only to retract my words, but also to deny under oath that I ever said them." -- Tom Lehrer ----
|
Sun, 16 Nov 1997 03:00:00 GMT |
|
 |
Hans Steffa #5 / 9
|
 scanf("%s", string) or scanf("%s", &string)? Both work, yet...
assuming char string[LENGTH]; you can also try scanf("%s", &(string[0]) ); h.f.s. -- Hans Friedrich Steffani Institut fuer Elektrische Maschinen und Antriebe TU Chemnitz-Zwickau
|
Sun, 16 Nov 1997 03:00:00 GMT |
|
 |
Tanmoy Bhattachar #6 / 9
|
 scanf("%s", string) or scanf("%s", &string)? Both work, yet...
Quote: Woodford) writes:
<snip> |> Assuming that "string" was declared as a char*, wouldn't &string be |> the address of the pointer, and not the location of where the incoming |> data is to be stored? This does not give a segmentation fault error? |> I'm surprised. _Assuming_ string was declared char*, and it was assigned to before being used in scanf, you are right. However, a more likely situation is that string was declared char[], in which case, string is valid; and &string is not because it has a different type; and hence possibly a different representation. Why it works is that char * and char(*)[] hardly ever have different representations: in fact this point is so subtle that even the standard gets it wrong (or else almost every program written in C so far is non-conforming :-) in the description of fprintf. Cheers Tanmoy --
Tanmoy Bhattacharya O:T-8(MS B285)LANL,NM87544-0285,USA H:#3,802,9 St,NM87545 Others see <gopher://yaleinfo.yale.edu:7700/00/Internet-People/internet-mail>, <http://alpha.acast.nova.edu/cgi-bin/inmgq.pl>or<ftp://csd4.csd.uwm.edu/pub/ internetwork-mail-guide>. -- <http://nqcd.lanl.gov/people/tanmoy/tanmoy.html> fax: 1 (505) 665 3003 voice: 1 (505) 665 4733 [ Home: 1 (505) 662 5596 ]
|
Sun, 16 Nov 1997 03:00:00 GMT |
|
 |
Scott Andre #7 / 9
|
 scanf("%s", string) or scanf("%s", &string)? Both work, yet...
Hi all, thanks for the interesting replies on the obscure (<=> C-ish) scanf(). (-; Our local mailserver has a slow link, annoying me when doing article body search, thus I gained access to the central server of our Internet provider (our corporate account there is for "compcom"). It's not telnet that matters, but the search, which then happens directly there. Hope it isn't worth explaining in every posting? A pseudonim Scott Andrews, popping out of the setting, is OK, I can answer to that... (-: (Would appreciate an advice.) The following is a rhethoric dialogue with an anomymous Ada observer (who has a very respectable real prototype, but w/o approval to disclose yet). Quote: > Um, why did you post this to comp.lang.ada?
It's because of the below ADAMANT context. If we don't have to attach the '&' in front of the string, which indeed is char *string, we get closer to Ada! Quote: > Anyway, in C the name of an array object, in most expression contexts, > evaluates to a pointer to the array's first element (exceptions include > operands of the sizeof and "&" operators; there may be others). > So, assuming the declaration of "string" is "char *string", yes, > scanf("%s", string) and scanf("%s", &string) are essentially equivalent. > Section 6.2.2.1 of the ISO C standard says > Except when it is the operand of the sizeof operator or the unary > & operator [...], an lvalue that has type "array of _type_" is > converted to an expression that has type "pointer to _type_" that > points to the initial element of th array object and is not an lvalue. > The deleted text ("[...]") discusses string literals; _type_ denotes > the word "type" in italics. > As I understand it, there may be a slight semantic difference in that > "string" evaluates to a pointer to a character while "&string" evaluates > to a pointer to an array of character, but I don't *think* it's likely > to matter.
I'll use angle brackets <> below in BNF sense <=> [], as denoting optional code, or even pseudocode, not to confuse BNF with the C array[] issue at hand. Surely I felt by heart that string, whether declared as char *string, or char string[], denotes the address of the first element. That's why taking one more address _must_ be semantically different! The second scanf ought to fill string[0] (read string[0] as "memory block, starting with string[0]," depending on the address size) with an address, so that (char **)string[0<..n-1>] must be this very address! Of course it will be garbage, produced from an input string, according to the scanf's format specifier for our <&>string, the specifier "%s". I'm inclined to believe it's a quirk in the implementation of C library, and how scanf translates "%s" to resolve &string to the same as string. It may be how scanf/printf associates the specifiers with the objects list (NAMELIST in fortran 90 sense :). It's known how easy one can get in trouble when the number of format specifiers doesn't equal the number of the objects on the NAMELIST, so the issue "string == &string" may hold only "when it comes to scanf". That's exactly what stuns a disciplinary Adaist when looking at the code in the subject -- in Ada, an access type is always a next level "wrapper", which doesn't undermine the accessed object pre-existed structure. I've seen an interesting "destructor" implementation in an Ada/Pascal language, and the behavior of '&' as you describe above reminds me of an "intrusive" destructor, because its attachment is context-sensitive, not just taking the address, but implies "evaluation" depending on the argument. After all, we don't expect "overloading" for & in C! Yes, it's implicitly present for "+", "*", etc. C built-in types, but the address is something which ought to be unequivocal and straightforward! My busy job with C programming for Ada 83 compiler-related tools has prevented me from staying on top of Ada 95 issues. Do people side with a common complaint, when you have to supply a generic parameter type which, say, is a vector, you also have to supply its element type separately? A _type destructor_ would get to every component of a _type_, with potential nesting, i.e. one have to supply only the vector, quite naturally. Of course, the destructor is a dangerous thing in the limited/private sense, but why not to allow it in the generic section of a library compilation unit, and some other well-defined contexts? I quote a reply, reminding of a type destructor's behavior, here: comp.lang.c #126023 (1110 more)
Subject: Re: scanf("%s", string) or scanf("%s", &string)? Both work, yet... Date: Tue May 30 16:34:46 EDT 1995 Organization: Computer Science Department, Stanford University. Lines: 40
>Both work with gcc, cc, Mac THINK and CodeWarrior, still I can't >believe both variants are semantically equivalent in C! BTW, >I am an Ada semi-guru in real life. But I program exclusively in "high-style" >C now, using # define's to obtain Ada front end. The ADAMANT project I >conduct is to provide a convenient preprocessor level, semi-Ada >"look and feel" in C. I assume that you have declared string as something like: char string[SIZE]; If so, then string has the type "array of SIZE chars". When you pass string as an argument to scanf, it "decays" into a pointer to the initial element of the array, which has type "pointer to char". Note that the actual value of the pointer will be the base address of the inital element. If you pass &string as an argument to scanf, string does NOT "decay" into a pointer, so the expression &string has type "pointer to array of SIZE chars". The important thing here is that the value of this pointer is the base address of the array, WHICH IS ALSO THE BASE ADDRESS OF THE INITIAL ELEMENT. In other words, the two pointers have the same address value, even though they are different types. Now scanf expects to receive a pointer of the first type as its argument (a pointer to char), so techically the second is not quite right. However, since scanf takes a variable number of arguments, the compiler is unable to do type checking, so it probably won't even give you a warning. In any case, they will both work, since all scanf does is look at the address value, regardless of the type. -Jon So the author in comp.lang.c uses the actual term "decay", describing to the behavior of & applied to my char *string. It means that & in C behaves similarly to the _type destructor_ described above... at least "when it comes to scanf". --
``Age Quod Agis'' (Do what you're doing.)
|
Mon, 17 Nov 1997 03:00:00 GMT |
|
 |
David Moo #8 / 9
|
 scanf("%s", string) or scanf("%s", &string)? Both work, yet...
Quote:
> Woodford) writes: > <snip> > _Assuming_ string was declared char*, and it was assigned to before being > used in scanf, you are right. However, a more likely situation is that string > was declared char[], in which case, string is valid; and &string is not > because it has a different type; and hence possibly a different > representation. Why it works is that char * and char(*)[] hardly ever have > different representations: in fact this point is so subtle that even the > standard gets it wrong (or else almost every program written in C so far is > non-conforming :-) in the description of fprintf.
Actually it's worse than that (Jim). C leads you to think that char s[]="abcde" and char *s="abcde" are the same thing, but they are not. In the former, s is a constant while in the latter it is a variable. Consider the following code: char *t="abcde"; char s[]="12345"; main () { printf("%08X\n",t); printf("%08X\n",&t); printf("%08X\n",s); printf("%08X\n",&s); } The output is: 000040C8 000040B8 000040BC 000040BC (On Sunos using acc) So in the last printf, the & is a no-op. It should really be flagged as an error. For example, when I try: int i; main () { printf("%08X\n",&i); printf("%08X\n",& &i ); } I get the error message: line 4: unacceptable operand for unary & I bet if one actually implemented it that way though, there would be a long line of users outside one's door bearing fire-brands.
|
Mon, 17 Nov 1997 03:00:00 GMT |
|
 |
Dik T. Wint #9 / 9
|
 scanf("%s", string) or scanf("%s", &string)? Both work, yet...
[About: string s[] and the use of &s ] ... > It should really be flagged as an error. For example, when I > try: ... > I get the error message: line 4: unacceptable operand for unary & > > I bet if one actually implemented it that way though, there would > be a long line of users outside one's door bearing fire-brands. > Indeed because &s is correct (but not of type pointer to char it is of type pointer to array of char). -- dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924098
|
Tue, 18 Nov 1997 03:00:00 GMT |
|
|
|