2

In C, when & is absent for an argument in scanf(), no compilation error is produced; instead, the displayed results are wrong (i.e. a semantic error occurs).

Consider the following code:

char str[30];
int a;
printf("Enter the value");
scanf("%s %d", str, a);       // This is the statement in question.
printf("You entered %s %d", str, a);

Here I know str is a character array so it will have a base address, and thus will not produce a compilation error. But why does the absence of & for the argument a not result in a compilation error?

Also str gives correct output, but the integer is always producing the value -28770 as the output. Why is this?

Sabuncu
  • 5,095
  • 5
  • 55
  • 89
Gon
  • 41
  • 3
  • What are you inputting? And what do you expect as output? – Mohit Jain Mar 11 '16 at 12:14
  • "integer always giving -28770 as output" - Uninitialized local variable `a`. Contains whatever was at that memory location (stack or register) before the declaration. May be the same at each run, may be different each time; that's why it's "undefined behaviour". - Didn't your compiler warn you about it? – JimmyB Mar 11 '16 at 12:21
  • okay. And compiler didn't gave any warning. Thanks for answering. – Gon Mar 12 '16 at 17:30

4 Answers4

4

scanf has the prototype:

int scanf(const char *fmt, ...);

The ... means that any number of arguments of any type may be specified after fmt. Hence it is the responsibility of the caller, not the compiler, to ensure that the provided arguments match what the function will be expecting.

alteous
  • 188
  • 2
  • 6
2
int scanf(const char *format, ...);

This is the prototype for scanf. First argument is char* and other arguments are variable lengths. So no error will be generated.

Umamahesh P
  • 1,224
  • 10
  • 14
  • To elaborate: The varargs in `scanf()` have no declared type and hence, for the compiler, can be absolutely anything. – JimmyB Mar 11 '16 at 12:19
1

As Umamahesh P wrote, you won't get a compilation error, because scanf is a variable-argument function. As to what happens when you run the program, it is what the C standard calls "undefined behaviour". Anything can happen. You need to look at what happens at the machine-instruction and memory address level to see what exactly scanf does with the integer value you gave it instead of a pointer.

Thomas Padron-McCarthy
  • 27,232
  • 8
  • 51
  • 75
  • Wouldn't `scanf(..., a)` even try and write the value input to a random location in memory, likely segfaulting? – JimmyB Mar 11 '16 at 12:24
  • @HannoBinder that could happen - but the behaviour is _undefined_, meaning that anything could happen. – davmac Mar 11 '16 at 12:26
  • 1
    @HannoBinder: As davmac wrote, that can happen, but no guarantees. Another behaviour that I have seen is that arguments are passed in registers, and 32-bit integers and 64-bit pointers are passed in different registers, so scanf will get a pointer to something, that happened to be in the right register. – Thomas Padron-McCarthy Mar 11 '16 at 15:25
  • @ThomasPadron-McCarthy Thanks for that interesting insight. – JimmyB Mar 11 '16 at 15:30
0

You can get a compiler warning, depending on what compiler you use and what options you specify.

Also even if it tries to show those warnings, your compiler will be totally unable to do it if you use vscanf() or if you use a dynamic string as your format parameter.

For instance, this is the output I get using mingw-64 gcc 4.5.4:

gcc -Wall -o small.exe small.c

small.c:7:3: warning: format '%d' expects type 'int *', but argument 3 has type 'int'
small.c:7:8: warning: 'a' is used uninitialized in this function

Just add -Werror option to turn these warnings into errors.

jdarthenay
  • 3,062
  • 1
  • 15
  • 20