Why does this code below compiles and executes but doesn't print anything in output,
int i = 0;
printf(i = 0);
but this gives a runtime error,
int i = 0;
printf(i = 1);
Why does this code below compiles and executes but doesn't print anything in output,
int i = 0;
printf(i = 0);
but this gives a runtime error,
int i = 0;
printf(i = 1);
int i = 0;
printf(i = 0);
The first argument to printf
must be a char*
value pointing to a format string. You gave it an int
. That's the problem. The difference in behavior between printf(i = 0)
and printf(i = 1)
is largely irrelevant; both are equally wrong. (It's possible that the first passes a null pointer, and that printf
detects and handles null pointers somehow, but that's a distraction from the real problem.)
If you wanted to print the value of i = 0
, this is the correct way to do it:
printf("%d\n", i = 0);
You have a side effect in the argument (i = 0
is an assignment, not a comparison), which is legal but poor style.
If you have the required #include <stdio.h>
, then your compiler must at least warn you about the type mismatch.
If you don't have #include <stdio.h>
, then your compiler will almost certainly warn about calling printf
without a declaration. (A C89/C90 compiler isn't strictly required to warn about this, but any decent compiler should, and a C99 or later compiler must.)
Your compiler probably gave you one or more warnings when you compiled your code. You failed to include those warnings in your question. You also failed to show us a complete self-contained program, so we can only guess whether you have the required #include <stdio.h>
or not. And if your compiler didn't warn you about this error, you need to find out how to ask it for better diagnostics (we can't help with that without knowing which compiler you're using).
Expressions i = 0
and i = 1
in printf
function will be evaluated to 0
and 1
(and i
will be initialized to 0
and 1
) respectively. So above printf
statements after their expression evaluation will be equivalent to
printf(0); // To be clear, the `0` here is not a integer constant expression.
and
printf(1);
respectively.
0
and 1
both will be treated as address in printf
statements and it will try to fetch string from these addresses. But, both 0
and 1
are unallocated memory addresses and accessing them will result in undefined behavior.
printf awaits a format string as its first argument. As strings (char*) are nothing else than pointers, you provide an address as the first parameter.
After an address and an integer are implicitly converted into each other,
printf(i = 0)
is (from the perspective of printf) the same as:
printf( 0 )
which is the same as
printf( NULL ) // no string given at all
If you provide 0 as parameter, printf will gracefully handle that case and don't do anything at all, because 0 is a reserved address meaning nothing at all
.
But printf( 1 )
is different: printf now searches for a string at address 1, which is not a valid address for your program and so your program throws a segmentation fault.
[update] The main reason why this works is a combination of several facts you need to know about how char arrays, pointers, assignments and printf itself work:
Pointers are implicitly convertible to int and vice versa, so the int value 17
for example gets converted to the memory address 0x00000011 (17) without any further notice. This is due to the fact that C is very close to the hardware and allows you to calculate with memory addresses. In fact, internally an int (or more specific: one special type of an integer) and a pointer are the same, just with a different syntax. This leads to a lot of problems when porting code from 32bit to 64bit-architecture, but this is another topic.
Assignments are different from comparations: i = 0
and i == 0
are totally different in meaning. i == 0
returns true when i contains the value 0
while i = 0
returns... 0
. Why is that? You can concatenate for example the following variable assignments:
a = b = 3;
At first, b = 3
is executed, returning 3
again, which is then assigned to a
. This comes in handy for cases like testing if there is more items in an array:
while( (data = get_Item()) )
This now leads to the next point:
NULL
is the same as 0 (which also is the same as false
). For the fact that integers and pointers can be converted into each other (or better: are physically the same thing, see my remarks above), there is a reserved value called NULL
which means: pointing nowhere
. This value is defined to be the virtual address 0x00000000
(32bit). So providing a 0 to a function that expects a pointer, you provide an empty pointer, if you like.
char* is a pointer. Same as char[] (there is a slight logical difference in the behaviour and in the allocation, but internally they are basically the same). printf expects a char*, but you provide an int. This is not a problem, as described above, int will get interpreted as an address. Nearly every (well written) function taking pointers as parameters will do a sanity check on these parameters. printf is no exclusion: If it detects an empty pointer, it will handle that case and return silently. However, when providing something different, there is no way to know if it is not really a valid address, so printf needs to do its job, getting interrupted by the kernel when trying to address the memory at 0x00000001 with a segmentation fault.
This was the long explanation.
And by the way: This only works for 32-bit pointers (so compiled as 32-bit binary). The same would be true for long int and pointers on 64-bit machines. However, this is a matter of the compiler, how it converts the expression you provide (normally, an int value of 0 is implicitly cast to a long int value of 0 and then used as a pointer address when assigned, but vice versa won't work without an explicit cast).
printf requires a const char * for input, whereas you're giving it an int
Why does this code below compiles and executes but doesn't print anything in output?
printf(i = 0);
The question embodies a false premise. On any modern C compiler, this clearly-erroneous code generates at least one error.