Why does my C compiler give a warning? - c

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.

Related

warning: format '%s' expects argument of type char problem in a simple program

#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.

Trying to scan and print a string in a structure [duplicate]

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).

Problem with " 'char *' but the argument has type 'char (*)[1]'"

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()).

What is the return value of &"suchString"?

The output of this snippet of code:
char* str1 = "suchString";
printf("%s %s\n", &"suchString", &str1);
is:
suchString �WO:+(or any unknown symbols)
What is the difference and why the output not the same?
EDIT
If you trying to eliminate the & operator as follows:
char* str1 = "suchString";
printf("%s %s\n", "suchString", &str1);
The output is the same of the first snippet of code.
Now, is how the "suchString" is the same of &"suchString"?
This:
&"suchString"
takes the address of a string literal. String literals are arrays, not pointers.
Had you compiled with warnings enabled, you had knew already:
prog.c:5:14: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[11]' [-Wformat=]
printf("%s %s\n", &"suchString", &str1);
~^ ~~~~~~~~~~~~~
prog.c:5:17: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'char **' [-Wformat=]
printf("%s %s\n", &"suchString", &str1);
~^ ~~~~~
The first is of type char (*)[11], while the second is of type char **.
As for the garbage values, you are providing an address of a pointer to %s format, thus ruining the print. If you used %p instead, you would see an address being printed out, e.g. "0x7ffe676f5588".
Same goes for when attempting to print the address of the string literal, with the string specifier in printf().
Moreover, you should cast to void*, like this:
printf("%p %p\n", (void*)"suchString", (void*)str1);
char* str1 = "suchString";
printf("%s %s\n", &"suchString", &str1);
The %s specifier requires an argument of type char*, which must be a pointer to a string. You've provided arguments of types char (*)[11] and char**. Your code has undefined behavior, which means that in principle it could do literally anything.
A string literal is an array. The address of an array refers to the same memory location as the address of the array's first element, but it's of a different type. Passing just "suchString" as the second argument would be correct, since the array "decays" to a pointer to its first element.
In an implementation where all pointers have the same representation (which is typical but not required), passing a pointer to the same memory location but with the wrong type is likely to "work". printf is special in that it can accept arguments of different types, so the compiler can't necessarily diagnose type errors. For a non-variadic function, an error like this would probably be rejected at compile time.
str1 is a pointer, not an array. You've initialized it to point to the initial character of the string literal. You could pass str1 to printf, but &str1 is the address of a pointer object, which is not only of the wrong type, but doesn't point to a string at all. Thus the output is garbage.
If you want to print the string values, you can do this:
const char* str1 = "suchString";
printf("%s %s\n", "suchString", str1);
(I've added const so the compiler will complain if you try to modify the contents of the string literal.)

Problems with scanf on strings with spaces

I have this simple code in C to scan and print a string with a whitespace:
#include <stdio.h>
#include <string.h>
int main()
{
char myName[50];
printf("Enter your name: ");
scanf("%[^\n]s", &myName);
printf("Your name is: %s", myName);
return 0;
}
The compiler (gcc, part of the command line tools that come with Xcode on my mac) is returning this error:
name.c: In function ‘main’:
name.c:7: warning: format ‘%[^
’ expects type ‘char *’, but argument 2 has type ‘char (*)[50]’
name.c:7: warning: format ‘%[^
’ expects type ‘char *’, but argument 2 has type ‘char (*)[50]’
What's the problem here?
NOTE: I am required to use scanf. No fgets for me :(
You should pass to scanf argument of type char* (format %[^\n]s expects so), but in your code:
char myName[50];
scanf("%[^\n]s", &myName);
you pass an address of myName array (i.e. char (*)[50]). You should change it either to:
scanf("%[^\n]", myName);
or:
scanf("%[^\n]", &myName[0]);
What's the problem here?
Well, here it is:
format expects type ‘char *’, but argument has type ‘char (*)[50]’
A pointer to an array is not the same as a pointer to the first element of an array. You should get rid of that & operator.
Couple issues
Wrong scanf() format s. The s is not part of the format specifier. The %[] format specifier ends with the ].
Wrong scanf() parameter &myName. Rather than passing the address of &myName, which is type char (*)[50] , simply use myName. This will pass the address of the first element of myName which is a char *, the expected matching type for %[].
Use
scanf("%[^\n]", myName);
Further recommend to consume leading white space and limit text read. The 49 limits the input to 49 characters, leaving 1 more byte for the terminating \0.
scanf(" %49[^\n]", myName);
In C, myName (when passed to a function) decays to a pointer to the first element of array (myname) of characters. &myName is a pointer to the array myname. &myName[0] would be a pointer to the first character, which is correct, but looks like you tried stuff at random until you chanced on something that worked.
Your problem is that your are passing the address to the pointer of the start of the string, rather than the pointer to the string. Simply, remove the &.
scanf("%[^\n]", myName);

Resources