I am trying to run a simple C program but I am getting this error:
warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[20]’
Running Mac OSX Mountain Lion, compiling in terminal using gcc 4.2.1
#include <stdio.h>
int main() {
char me[20];
printf("What is your name?");
scanf("%s", &me);
printf("Darn glad to meet you, %s!\n", me);
return (0);
}
scanf("%s", &me);
should be
scanf("%s", me);
Explanation:
"%s" means that scanf is expecting a pointer to the first element of a char array.
me is an object array and could be evaluated as pointer. That's why you can use me directly without adding &. Adding & to me will be evaluated to 'char (*)[20]' and your scanf is waiting char *
Code critic:
Using "%s" could cause a buffer overflow if the user input string's length is bigger than 20, so change it to "%19s":
scanf("%19s", me);
Except when it is the operand of the sizeof, _Alignof, or unary & operators, or is a string literal being used to initialize an array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and it will evaluate to the address of the first element in the array.
The array me is declared as a 20-element array of char; normally, when the expression me appears in your code, it will be treated as an expression of type "pointer to char". If you had written
scanf("%s", me);
then you wouldn't have gotten the error; the expression me would have been converted to an expression of the correct type.
By using the & operator, however, you've bypassed that rule; instead of a pointer to char, you're passing a pointer to an array of char (char (*)[20]), which is not what scanf expects for the %s conversion specifier, hence the diagnostic.
Another way you could fix this issue is by doing this:
scanf("%s",&me[0]);
You actually have to give the array's starting point (which in most languages is 0).
Related
#include<stdio.h>
#include<stdlib.h>
int main()
{
char str1[20];
printf("Name: ");
scanf("%s",&str1);
printf("Your name is %s",str1);
return 0;
}
it outputs fine but the the build messages say
warning: format '%s' expects argument of type char ', but argument 2 has type 'char () [20]' [-Wformat=]
str1 has type "array of 20 char" (char[20]). & makes a pointer to the operand. So &str1 has the type "pointer to array of 20 char" (char(*)[20]).
But %s expects the argument to be "pointer to char" (char*) and will store the input characters to consecutive char in memory starting with the location that the argument points to. So &str1 is not the correct type.
Since str1 is an array of char, str1[0] does have just type char and is the first element of the array, where you want scanf to begin storing to and so &str1[0] would for example have type char* and point to the correct char.
Instead you can also just write str1 instead of &str1[0], because arrays will generally (but not when & is applied directly to them) decay to pointers to the first element automatically.
It works exactly the same for printf's %s, where you are using just str1 correctly.
FILE *fd;
char File_name[]="";
<...>
printf("Enter the name of the file where you want the results to be saved. \n");
printf("DON'T FORGET that file must end with .exe \n");
scanf("%s",&File_name);
while(strchr(File_name,'.txt')==NULL)
{
printf("The end of the file name is not correct. Please try again. \n");
printf("File name: ");
scanf("%s",&File_name);
}
Warning:
format specifies type 'char ' but the argument has type 'char ()[1]' [-Wformat]
scanf("%s",&File_name);
~~~~^~~~~~~~~~
Arrow goes to "&File_name".
How to fix it? Thank you.
scanf() expects char* for %s.
File_name has type char[1] because it is one-element array and the element is initialized to '\0'.
Most arrays in expressions are converted to a pointer, but one of the exception is an operand of unary & (this case).
Therefore, &File_name becomes a pointer to the array and its type is char(*)[1].
To fix, remove the &s before File_name. Then the array File_name will be converted to char* pointing at its first element.
Also:
1 element is definitely too short to read strings. Allocate more elements by specifying number of elements like char File_name[512] = "";.
'.txt' is a multi-character character constant. Its value is implementation-defined and will not be what you want. You should use strstr(File_name,".txt") instead of strchr(File_name,'.txt'). (strstr is for searching for strings (including middle), not for checking suffix, but it will behave better than strchr()).
This question already has answers here:
format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[64]
(3 answers)
Closed 9 years ago.
I got a warning in my program, and it says:
format '%c' expects argument of type 'char *' , but argument 2 has type 'char (*)[10]' [-Wformat]
Here's my program:
#include<stdio.h>
int main()
{
char array[10];
scanf("%10c", &array);
printf("%.10s", array);
return 0;
}
The warning disappears when I remove '&' from scanf.
I know, it's an array and doesn't require &. But don't they have same effect?
I mean both '&array' and 'array' give address of its first element, right?
If so, what's the difference here?
I read some related questions here, and googled a lot.
It has been said that '&array' is a pointer to an array of characters if 'array' is an array while 'array' itself is a pointer to char.
According to what it says, since I'm using %c, a pointer to an array of characters should be passed, I think.
Idk, I would very greatful if someone explains how %[width]c works.
I also verified that all 'array', '&array' and '&array[0]' give address of its first element.
Here's what I did:
int main()
{
char array[10];
puts("ADDRESS:");
printf(" %p \n %p \n %p", array, &array, &array[0]);
return 0;
}
If they all give same address, why is it giving such warnings?
It also works for %s.
They all work fine in most of windows compiler, without any warnings.
Since I'm a windows user, I never used gcc compiler before. And what I was thinking was it's just not mandatory to write & as with function pointers.
You don't necessarily have to write & with function pointers, I read.
I'm getting more and more confused, please help me get it.
Thank you.
array and &array both yield a pointer to the same address, but with different types. The former is equivalent in most situations to &array[0], a char * in your case. &array, however, is the address of the array itself, which has type char (*)[10] in your example.
array and &array are not the same... even if they have same address location in it.
array here being char array, it points to a single char, and if you increment it increases by 1 char size.
but &array points to the entire array and if increments it increases by the array size.
scanf function expects for the array.. not &array
Beginner question. I have the following code:
char input[10];
scanf("%s", &input);
My compiler throws the following warning:
warning: format '%s' expects type 'char *', but argument 2 has type 'char (*)[10]'
warning: format '%s' expects type 'char *', but argument 2 has type 'char (*)[10]'
Changing to:
char * input;
Does not seem to help. What am I doing wrong?
Because an array already can be used as a pointer, so you don't need to the address-of operator.
If you read the warning message again, you will see that when you use the address-of operator on the array, you get a pointer to the array.
Try,
char input[10];
scanf("%s", input);
You don't have to give the address-of operator (&) with the name of the array input.
%s format string accepts argument of type char* where as &intput is of type char (*)[10] that is the reason you are getting warning.
format '%s' expects type 'char *', but argument 2 has type 'char (*)[10]
Note argument 2 is &input in scanf()
scanf("%s", &input);
^ ^
| argument-2
argument-1
To correct this code you should write scanf like:
scanf("%s", input);
Side note:: value wise both &input and input are same if you string address but semantically both are diffrent.
&input is address of array that is char(*) [10] type whereas input type is char[10]
To understand difference between &input and input read this two answers:
What does sizeof(&arr) returns? , and
Issue with pointer to character array C++
Edit:
Changing to: char *input will not help you instead it becomes undefined behavoiur unless and until you allocated memory to input
char input[10] is a character array.
input itself represents the base address of the array, i.e a char *.
You do not need to use the address of operator (&)with it. instead, use:
char input[10];
scanf("%s", input);
If you use char * input;, you need to allocate space for it using malloc. But in this case also, no need to use the address of operator.
scanf("%s", input);
you will get the answer.
char input[10];
scanf("%s", &input);
scanf requires the address to store the data that will be recieved. Array names already act like pointers, So you don't need the & operator to obtain the address.
format '%s' expects type 'char *', but argument 2 has type 'char (*)[10]'
When you do &input it indicates a pointer that is pointing to a char array of 10 char. char (*)[10]
input is itself char* and is only necessary to be passed as 2nd argument to scanf.
Go through this too for arrays and pointers.
Python spoiled me and trying to wrap my mind around C now is being a bloodbath of stupid errors. This is one I can't quite understand.
I wanted the C equivalent of Python's os.path.split, but there's no exact equivalent. strsep looks similar enough, but needs some massaging to be used simply.
First off, I defined my path type: a string of given length.
#define MAX_PATH_LEN 200 /* sigh */
typedef char t_path[MAX_PATH_LEN];
Then I wrote some code that does the actual massaging, attempting to avoid side effects -- just to keep things fool proof.
typedef struct {
t_path next;
t_path remainder;
} t_path_next
t_path_next path_walk_into(t_path path) {
t_path_next output;
t_path my_next, my_remainder = "/";
strncpy(my_next, path, MAX_PATH_LEN);
strsep(&my_next, my_remainder);
output.remainder = my_remainder;
output.next = my_next;
return output;
}
gcc, however, is not impressed.
badp#delta:~/blah$ gcc path.c -Wall
path.c: In function ‘path_walk_into’:
path.c:39: warning: passing argument 1 of ‘strsep’ from incompatible pointer type
/usr/include/string.h:559: note: expected ‘char ** __restrict__’ but argument is of type ‘char (*)[200]’
path.c:41: error: incompatible types when assigning to type ‘t_path’ from type ‘char *’
path.c:42: error: incompatible types when assigning to type ‘t_path’ from type ‘char *’
I am baffled by the note -- how are char ** and char (*)[200] really different -- but the error is even weirder. I want to assign a variable I declared t_path in a field of type t_path, but I don't get to.
Why is that?
For anybody interest here's the correctly working version of the function:
t_path_next path_walk_into(t_path path) {
t_path_next output;
t_path my_path, delim = "/";
char* my_path_ptr = my_path;
strncpy(my_path, path, MAX_PATH_LEN);
strsep(&my_path_ptr, delim); //put a \0 on next slash and advance pointer there.
if (my_path_ptr == NULL) //no more slashes.
output.remainder[0] = 0;
else
strncpy(output.remainder, my_path_ptr, MAX_PATH_LEN);
strncpy(output.next, my_path, MAX_PATH_LEN);
return output;
}
The errors: You can't directly assign to an array, such as a string, in C. You need to copy char by char, or call str(n)cpy, which does it for you.
For the warning : you are probably already aware that array may decay to pointer. That is, for example, what makes an array acceptable as an argument to a function where a pointer is expected. In your case, what you have is a pointer to an array : there is no reason for such a thing to get converted to a pointer to pointer.
For the record, the C99 standard says (6.3.2.1/3) :
Except when it is the operand of the sizeof operator or the unary & operator, or is a
string literal used to initialize an array, an expression that has type ‘‘array of type’’ is
converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
the array object and is not an lvalue.
You're in the context of a unary & : no conversion for you.
For the error : it has already been answered, but array assignment is not directly possible. You might want to use strcpy or strncpy.