Reputation: 39
So I'm fairly new to programming and I started C about 3 days ago. I was creating this short program to test myself. It's just an extremely basic C program asking for your first and last name. Here is the code:
#include <stdio.h>
int main()
{
char first[20];
char last[20];
printf("Please enter your first name:");
scanf("%s",&first);
printf("\nand Please enter your last name:");
scanf("%s",&last);
printf("Greetings fellow %s %s!\n",first,last);
return(0);
}
But when I go to compile I get this error every single time:
checkname.c:9: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
checkname.c:11: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
I know I can use gets()
except apparently it's bad and I shouldn't use it. What is wrong with this code? I don't understand what the problem is.
Upvotes: 2
Views: 721
Reputation: 17258
Remove the & from the scanf
statements.
scanf("%s", first); // first is pointer to start of first
scanf("%s", last); // last is pointer to start of last
In C the name of an array is a pointer to the start of the array.
After the format parameter scanf
requires pointer argument or arguments.
scanf( "%s", first );
scanf format-arg input-args
For example, if a integer parameter were being used for scanf
, the & (take the address of) operator would be required.
int n;
scanf("%d", &n); // &n is pointer to n
Upvotes: 1
Reputation: 490108
Try changing scanf("%s",&first);
to scanf("%s",first);
(and similarity for last
).
Under normal circumstances (including these) the name of an array evaluates to the address of the first element in the array. In this case, that's a pointer to char, which is the type scanf
expects for a %s
conversion.
With the &
on the beginning, you get the same pointer value (i.e., the same address), but as a pointer to an array instead of a pointer to the element of the array. Since this doesn't match the type expected by %s
, the result is undefined behavior (though since it's the right address, this will usually work with most typical compilers/CPUs).
Upvotes: 1
Reputation:
I know I can use
gets()
except apparently it's bad and I shouldn't use it.
Exactly, exactly - it's prone to buffer overflow errors. And scanf()
is equally evil (partially for the same reason - it's not trivial to specify the buffer length, and anyways, it's way more complex than necessary, it's hard to get it right, and it's superfluously expensive for simple raw I/O), don't use it either. Use fgets()
for acquiring user input, it saves your from being shot in the foot by letting you pass it the length of the buffer to be written to:
char buf[0x40];
fgets(buf, sizeof(buf), stdin);
Now that you know the "how", I'll explain to you the "why".
Arrays, when passed to functions, are said to decay into pointers. If you pass a char []
to a function, it will see that as a char *
that points to the first element to the array. That's why you don't have to explicitly use the "addressof" (&
) operator for a (char) array (which is conceptually a string in C).
If you use it, you don't get a pointer to the first element of the array, but a pointer to the array itself, and that's not what you want.
(In general, it could work, as it apparently did for you, but in theory it invokes undefined behavior because the actual type of the expression passed in and the type expected by the %s
conversion specifier don't match.)
This document is a good read about arrays and pointers, make sure to read and understand it.
Upvotes: 7
Reputation: 860
scanf need an address, however a char array [] is already an address and scanf doesnt need the reference sign & because the name itself is an address
Upvotes: 0
Reputation: 3143
You are using array. Dont use &
with scanf
while input to array
e.g: scanf("%s",first);
Arrays are already passed by reference. You don't need to put &
as array is already passed as a pointer to the first element in C
Upvotes: 2