-1
#include<stdio.h>  

static char c;  
static int i;  
static float f;   
static char s[100];  

void main ()  
{  
    printf("%d %d %f %s",c,i,f); 
}  

I expect the error in output, but the actual output is 0 0 0.000000 (null)

dbush
  • 205,898
  • 23
  • 218
  • 273
Murali
  • 9
  • 2
  • 1
    Why do you think there will be an error?, it is undefined behavior I would think – Inian Jul 17 '19 at 03:08
  • we dint pass any variable or value for %s – Murali Jul 17 '19 at 03:09
  • 1
    `void main ()` should be `int main(void)`. If you have a book that tells you to use `void main ()`, replace it with one written by someone who knows C. – Keith Thompson Jul 17 '19 at 03:14
  • What compiler are you using? Any compiler will likely warn (at least) you when compiling that code. – alx - recommends codidact Jul 17 '19 at 03:26
  • 2
    If you expect C to check your code for errors at runtime and issue sensible error messages if your code violates some constraint, then you need to adjust your expectations. For better or worse, that's not C's philosophy. C does not spend the extra cycles at runtime to check validity, on the basis that programmers who accept the responsibility of ensuring their code is correct don't want to pay the cost of double-checking it. However, you can ask the C compiler to warn you about things which are likely to be problems, and you absolutely should do that. – rici Jul 17 '19 at 03:34

1 Answers1

4

Your format string expects 4 arguments but you only pass 3. Doing so invokes undefined behavior, meaning you can't predict the behavior of the program.

In this case the string "(null)" is printed, but your code could print some random sequence of characters, no extra characters, or it could crash. There's no guarantee.

What probably happened is that the %s format specifier attempted to read the next 8 bytes on the stack to get a pointer, and those 8 bytes happened to all be 0, so the string "(null)" is printed because it read a NULL pointer. But again, there's no guarantee of that.

Also see, What is the behavior of printing NULL with printf's %s specifier?.

Inian
  • 80,270
  • 14
  • 142
  • 161
dbush
  • 205,898
  • 23
  • 218
  • 273
  • 2
    It's also worth pointing out that having `%s` print `(null)` if the argument is a null pointer is not required, but it's a common extension. The behavior would still be undefined if an explicit null pointer were passed. – Keith Thompson Jul 17 '19 at 03:13
  • @KeithThompson It's also worth noting that there's a known problem with that extension: when the compiler decides to optimize a `printf` and calls `puts` instead, the extension doesn't come into play, and boom! I wouldn't rely on that extension, although it's nice having it as extra safety. – alx - recommends codidact Jul 17 '19 at 03:21
  • @CacahueteFrito Eh? The "extension" only comes into play when the format contains `%s`, but the optimization only comes into play when the format string is constant and contains no `%` signs at all. So they shouldn't ever conflict with each other (let alone go "boom"), right? What am I missing? – Steve Summit Jul 17 '19 at 05:20
  • 1
    @SteveSummit `char *s = NULL; printf("%s\n", s);` should be enough to halt & catch fire with a decent optimizer :-) (it's equivalent to `puts(s);`). If the compiler is very aggressive at optimizing, some other less obvious cases may result in UB. The link recently added into the answer reflects that. – alx - recommends codidact Jul 17 '19 at 05:44
  • @CacahueteFrito: Yes, gcc transforms `printf("%s\n", s;` to `puts(s)` at all optimization levels, and clang at `-O1` and higher. (gcc 7.4.0, clang 6.0.0, Ubuntu 18.04.2 x86_64) – Keith Thompson Jul 17 '19 at 09:23
  • @SteveSummit: See my previous comment (can't "@" more than one person). – Keith Thompson Jul 17 '19 at 09:24