Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting warnings about this code example? What is proper?

Tags:

c

I'm learning some C, and was reading up on scanf from this tutorial where the following code block is included:

#include <stdio.h>

int main()
{
   char str1[20], str2[30];

   printf("Enter name: ");
   scanf("%s", &str1);

   printf("Enter your website name: ");
   scanf("%s", &str2);

   printf("Entered Name: %s\n", str1);
   printf("Entered Website:%s", str2);

   return(0);
}

However I get warnings that:

"Format specifies type 'char *' but the argument has type 'char (*)[20]'

Is the tutorial wrong?

like image 467
Doug Smith Avatar asked Jan 06 '15 19:01

Doug Smith


3 Answers

This should work for you:

#include <stdio.h>

int main()
{
   char str1[20], str2[30];

   printf("Enter name: ");
   scanf("%19s", str1);
         //^^   ^ Removed address operator
         //So only the right amount of characters gets read   

   printf("Enter your website name: ");
   scanf(" %29s", str2);
        //^ Added space to catch line breaks from the buffer

   printf("Entered Name: %s\n", str1);
   printf("Entered Website:%s", str2);

   return(0);
}
like image 150
Rizier123 Avatar answered Nov 13 '22 09:11

Rizier123


There is a bug in the example of the tutorial.

Change:

scanf("%s", &str1);

to

scanf("%s", str1);

s conversion specifier requires a pointer to char but you are passing a pointer to an array.

like image 39
ouah Avatar answered Nov 13 '22 09:11

ouah


The lines

scanf("%s", &str1);

and

scanf("%s", &str2);

are indeed wrong (at the very least, they both contain a typo). They should be written as

scanf("%s", str1);  // no & operator

and

scanf("%s", str2); // ditto

Arrays and array expressions are special in C. Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another 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 the value of the expression will be the address of the first element of the array.

The expression str1 has type "20-element array of char". If str1 appears in a context where it's not the operand of the sizeof or unary & operators, it will be converted to an expression of type "pointer to char", and the value of the expression will be the same as &str1[0]; this is why you don't need to use the & for reading strings, since the array expression will be treated as a pointer. However, when it's the operand of the unary & operator, the conversion rule doesn't apply, and the type of the expression &str1 is "pointer to 20-element array of char" (char (*)[20]). Hence your warning.

The value of str1 and &str1 will be the same (the address of the first element array is the same as the address of the array), but the types of the expressions are different, and type matters. A pointer to char will be treated differently from a pointer to array of char.

90% of C books and tutorials are crap; be very skeptical of any C reference that isn't the actual standard. Harbison & Steele's C: A Reference Manual (currently 5th edition) has been my go-to reference since the late '80s, but even it has small errors.

like image 27
John Bode Avatar answered Nov 13 '22 10:11

John Bode