The correct way to read in a string is either of these:
scanf("%s", &str1[0]); // Correct
scanf("%s", str1); // Also correct
The first one is explicitly correct--you want to pass the address of the first char
. The second, it turns out, is equivalent. When you pass an array to a function, it silently "decays" to a pointer. The compiler converts arguments like array
into &array[0]
.
scanf("%c",str1[0]); // Incorrect
Passing the first character instead of the address of the first character is flat out wrong. This will either fail to compile, or will very likely crash when you run the program. A character is very different from an address.
scanf("%s", &str1); // Undefined behavior
This is wrong, but not "flat out" wrong, if I may be allowed to make such a distinction.
Passing &str1
is a common error. The reason is subtle indeed. &str[0]
is the address of the first character of the string. &str
is the address of the entire 50-character array. The subtlety here is that these will in fact be the same address in memory--an array starts at its first character.
So why is this wrong?
The answer is in typing.
The type of &str[0]
is char *
-- pointer to character. That's the expected type when you use %s
.
The type of &str
is char (*)[50]
-- pointer to a 50-character array. This is not the same thing as char *
. For further explanation, see: How come an array's address is equal to its value in C?.
The values of &str
and &str[0]
are equal, but the types are different. This type mismatch is, pedantically speaking, an error. It causes undefined behavior.
I know what you're thinking. "Okay, smart guy--if this is an error, then why does it work, huh?" Well, C is a funny language. It's really trusting. Overly trusting, really. If you tell it to jump off a cliff, it'll jump off that cliff. It doesn't go out of its way to verify that you're doing absolutely correct and sensible things.
There are lots of times when you can ask it to do something that's technically invalid. Compilers aren't required to diagnose and prevent undefined behavior. In the name of efficiency, it's permissible for them to do anything they want: crash, or print an error message... or, commonly, appear to actually work. This is one of those cases. The values of &str
and &str[0]
are the same, and because scanf()
is a varargs function, not all compilers will catch the type mismatch.
The morale is: don't rely on the compiler to tell you every time you make a mistake. If you mess up and invoke undefined behavior, you may get away with it for a while. Your code may appear to work. But you're sitting on a ticking time bomb. One day it will blow up in your face.