Why Does Reading into a String Buffer with Scanf Work Both with and Without the Ampersand (&)?
I'm a Little Bit Confused About Something. I Was Under the Impression That the Correct Way of Reading a C String with Scanf() Went Along the Lines of (Never...
I'm a little bit confused about something. I was under the impression that the correct way of reading a C string with scanf() went along the lines of
(never mind the possible buffer overflow, it's just a simple example)
char string[256];
scanf( "%s" , string );
However, the following seems to work too,
scanf( "%s" , &string );
Is this just my compiler (gcc), pure luck, or something else?
2 Answers
An array "decays" into a pointer to its first element, so scanf("%s", string) is equivalent to scanf("%s", &string[0]). On the other hand, scanf("%s", &string) passes a pointer-to-char[256], but it points to the same place.
Then scanf, when processing the tail of its argument list, will try to pull out a char *. That's the Right Thing when you've passed in string or &string[0], but when you've passed in &string you're depending on something that the language standard doesn't guarantee, namely that the pointers &string and &string[0] -- pointers to objects of different types and sizes that start at the same place -- are represented the same way.
I don't believe I've ever encountered a system on which that doesn't work, and in practice you're probably safe. None the less, it's wrong, and it could fail on some platforms. (Hypothetical example: a "debugging" implementation that includes type information with every pointer. I think the C implementation on the Symbolics "Lisp Machines" did something like this.)
I think that this below is accurate and it may help. Feel free to correct it if you find any errors. I'm new at C.
char str[]
- array of values of type char, with its own address in memory
- array of values of type char, with its own address in memory as many consecutive addresses as elements in the array
including termination null character
'\0'&str,&str[0]andstr, all three represent the same location in memory which is address of the first element of the arraystrchar *strPtr = &str[0]; //declaration and initialization
alternatively, you can split this in two:
char *strPtr; strPtr = &str[0];
strPtris a pointer to acharstrPtrpoints at arraystrstrPtris a variable with its own address in memorystrPtris a variable that stores value of address&str[0]strPtrown address in memory is different from the memory address that it stores (address of array in memory a.k.a &str[0])&strPtrrepresents the address of strPtr itself
I think that you could declare a pointer to a pointer as:
char **vPtr = &strPtr;
declares and initializes with address of strPtr pointer
Alternatively you could split in two:
char **vPtr;
*vPtr = &strPtr
*vPtrpoints at strPtr pointer*vPtris a variable with its own address in memory*vPtris a variable that stores value of address &strPtr- final comment: you can not do
str++,straddress is aconst, but you can dostrPtr++