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 requires a const char * for input, whereas you're giving it an int
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).
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.
Related
int main(void)
{
int b[5] = {1,2,3,4,5,6,7,8,9,10};
int i;
for(i=0;i<9;i++)
{
printf(" %d ",b[i]);
}
printf("\n address : %u",b);
return 0;
}
This is C program in which number of elements exceeds declared size. when i iterate through array it prints following output-
1 2 3 4 5 5 6422284 3854336 6422352
address : 6422288
compiler - gcc
i don't understand
why 5 is printed twice
why only 9 values are printed instead of 10
Because the behavior of the program is not defined, and thus it will do whatever. Your expectation that “5 should not be printed twice” is just as speculative as any other expectation. Why do you think 5 should not be printed twice?!
Because the behavior of the program is not defined. Thus your expectation as to the behavior of the loop is just idle speculation.
You’ll see even more interesting things happen if you do a release (optimized) build. It may do nothing whatsoever, or crash, or do the same thing, or do something else out of the blue if the CPU’s IP gets corrupted or sent into the “blue”.
And by the way, your original program could too :)
The C language specification contains the following constraint (C17 6.7.9/2):
No initializer shall attempt to provide a value for an object not
contained within the entity being initialized.
Your initialization of b ...
int b[5] = {1,2,3,4,5,6,7,8,9,10};
... violates that constraint by including ten values in b's initializer list when b has only five elements, all scalars. A conforming compiler is obligated to emit a diagnostic about that, and if gcc does not do so by default then it probably can be made to do so by including the -pedantic flag. Generally speaking, with gcc you should use both -Wall and -pedantic at least until you know enough to make an informed decision of your own.
Technically, the behavior of your program is undefined as a result, but that's probably not the main issue in practice. I expect that gcc is just ignoring the excess initializer values. The main issue is that no matter how many initializer elements you provide, you have specified that b has exactly 5 elements, but you attempt to access elements at indices above 4. Those are out of bounds array accesses, and their behavior is undefined. You have no valid reason to expect any particular results of those, or that anything be printed at all.
In fact, the whole program has undefined behavior as a result, so it is not safe to assume that a program that performed all the same things except the out-of-bounds accesses would produce a subset of the output of the erroneous program.
With respect to your particular questions:
why 5 is printed twice
The language specification does not say. The result of attempting to print b[5] is undefined.
why only 9 values are printed instead of 10
Probably because of the iteration bounds, i=0;i<9;i++. With those, and if the program otherwise conformed to the language specification, one would expect the loop body to be executed nine times (in particular, not when i has the value 9).
Note also that this ...
printf("\n address : %u",b);
... is wrong. The printf directive for printing pointers is %p, and, technically, it requires the argument to be a pointer to void (not, for example, a pointer to int). This would be fully correct:
printf("\n address : %p", (void *) b);
Addendum
If you want an array with exactly ten elements, then declare it so:
int b[10] /* initializer optional */;
If you want one whose size is chosen based on the number of elements in its initializer, then omit the explicit size:
int b[] = {1,2,3,4,5,6,7,8,9,10}; /* declares a 10-element array */
What this C statement does?
i=!({ printf("%d\n",r); });
i and r are integers.
I'm trying to parse it using pycparser which doesn't recognize it and raises an error:
pycparser.plyparser.ParseError: :7:6: before: {
Thanks
It looks like it is using a GNU C extension that allows to write a block statement where an expression is expected. The value of the block statement is the value of the last expression of the block.
For example:
int x = ({ int a = 1; a+2; });
will initialize x with 3.
In your particular case the extension does not look very useful, because:
i=!({ printf("%d\n",r); });
is identical to:
i=!printf("%d\n",r);
I'm guessing that your original code is probably generated by some dark magic macro.
BTW, this code does not make much sense. It looks like it wants to check whether printf failed or suceeded in writing the text. But according to the specification, printf will return the number of bytes written if success or a negative value if error. So it will return 0 only if it writes 0 chars, and that will not happen with a \n at the end, and i will always end up being 0, either with or without error.
This is not standard C, but a GCC statement expression extension, which allows putting blocks in expressions and returns the value of the last statement in the block.
Because the block here has only one statement which is itself an expression, this is equivalent to:
i = !printf("%d\n",r);
This sets i to 1 if printf returned 0 (i.e. it succeeded but didn't print any characters), or 0 otherwise. Since this printf will always print at least two characters when it succeeds, i will always be 0.
What is the output of this program and how?
#include<stdio.h>
int main(){
int a=0,b=10;
a=b---
printf("the value of b=%d",b);
printf("the value of a=%d",a);
return 0;
}
In your code, writing
a=b---
printf("the value of b=%d",b);
is same as
a = b---printf("the value of b=%d",b);
which is an expression with undefined behavior, as an attempt is made to change and use the value of variable b in two subexpressions without a sequence point in between. Hence, the output of this code cannot be justified.
Without the above problem, in general, the syntax is similar to
x = (y--) - (<return value of printf() call>)
which is a perfectly valid syntax.
Note:
Why a = b---<something> is treated as a = (b--) - <something> and not a = b - -- <something> is due to the maximal munch rule.
Strictly speaking, as others have said since this is undefined behaviour, the result could be anything . And while they're right, it doesn't explain why you get this specific answer in this specific compiler.
In practice b will usually be printed as 9, or 10 depending on whether the compiler does the decrememnt first or the printf first.
printf returns the number of characters printed. Which I think is 16 or 17 in this case.
So this is like writing a = (b--) - 16; b is 10 before the decrement and it's a post decrement so this is the value used.
Program 1:
#include<stdio.h>
void main()
{
int i=55;
printf("%d %d %d %d\n",i==55,i=40,i==40,i>=10);
}
Program 2:
#include<stdio.h>
void main(){
int i = 55;
if(i == 55) {
printf("hi");
}
}
First program give output 0 40 0 1 here in the printf i == 55 and output is 0 and in the second program too i ==55 and output is hi. why
In the first example, the operators are evaluated in reverse order because they are pushed like this on the stack. The evaluation order is implementation specific and not defined by the C standard. So the squence is like this:
i=55 initial assignment
i>=10 == true 1
i==40 == false (It's 55) 0
i=40 assignment 40
i==55 == false (It's 40) 0
The second example should be obvious.
There's no guarantee about the order in which arguments to a function are evaluated. There's also no sequence point between evaluating the different arguments to the function.
That means your first call gives undefined behavior, because it both uses the existing value of i and writes a new value to i without a sequence point between the two.
In a typical case, however, each argument to a function will be evaluated as a separate expression, with no interleaving between them. In other words, the compiler will impose some order to the evaluation, even though the standard doesn't require it to do so.
In the specific case of a variadic function, the arguments are typically pushed onto the stack from right to left, so the first argument (the format string) will be at the top of the stack. This makes it easy for printf to find the format string, and then (based on that) retrieve the rest of the arguments from further down the stack.
If (as is fairly typical) the arguments are evaluated immediately prior to being pushed on the stack, this will lead to the arguments being evaluated from right to left as well.
Functions with a fixed number of arguments aren't evaluated from right to left nearly as often, so if (for example) you wrote a small wrapper taking a fixed number of arguments, that then passed those through to printf, there's a greater chance that i would have the value 55 when the first argument to printf is evaluated, so that would produce a 1 instead of a 0.
Note, however, that neither result is guaranteed, nor is any meaningful result guaranteed--since you have undefined behavior, anything is allowed to happen.
The arguments of printf are evaluated from right to left here (this is unspecified behavior, but the behaviour you noticed shows that at least the first argument is evaluated after the second). In your argument list there ist i=40, which sets the value to 40. Therefore the first printed argument is false (0).
The function printf evaluates the expressions in implementation specific manner, in this case from right to left. Hence the output:
i==55(0),i=40(Assignment),i==40(0),i>=10(1)
The reason is that the order in which the arguments to the printf function (actually any function) are evaluated, before being passed to the function, is not defined by the C standard.
The problem is not with your understanding of the == operator.
Edit: Although many authors are pointing out that printf typically evaluates its arguments from right-to-left (which I wasn't aware of), I would say it's probably a bad idea to write code that depends on this, as the language does not guarantee it, and it makes the code much less readable. Nevertheless is is a good factoid to know in case you come across it in the wild.
In the first program: The order of evaluation of the printf() arguments is implimentation defined. So this program doesn't give the same result on different implimentation of printf() So there is no guarantee about what the program will result.
It could output 0 40 0 1 as it could output 1 40 1 1 if the order of evaluation is reversed.
What does the below code do? I'm very confused with its working. Because I thought that the if loop runs till the range of int. But I'm confused when I try to print the value of i. Please help me out with this.
#include<stdio.h>
void main()
{
static int i;
for (;;)
if (i+++”Apple”)
printf(“Banana”);
else
break;
}
It is interpreted as i++ + "Apple". Since i is static and does not have an initializer, i++ yields 0. So the whole expression is 0 + some address or equivalent to if ("Apple").
EDIT
As Jonathan Leffler correctly notes in the comments, what I said above only applies to the first iteration. After that it will keep incrementing i and will keep printing "Banana".
I think at some point, due to overflows (if it doesn't crash) "Apple" + i will yield 0 and the loop will break. Again, I don't really know what a well-meaning compiler should do when one adds a pointer and a large number.
As Eric Postpischil commented, you can only advance the pointer until it points to one-past the allocated space. In your exxample adding 7 will advance the pointer one-past the allocated space ("Apples\0"). Adding more is undefined behavior and technically strange things can happen.
Use int main(void) instead of void main().
The expression i+++"Apple" is parsed as (i++) + "Apple"; the string literal "Apple" is converted from an expression of type "6-element array of char" to "pointer to char", and its value is the address of the first element of the array. The expression i++ evaluates to the current value of i, and as a side effect, the value in i is incremented by 1.
So, we're adding the result of the integer expression i++ to the pointer value resulting from the expression "Apple"; this gives us a new pointer value that's equal or greater than the address of "Apple". So assuming the address of the string literal "Apple" is 0x80123450, then basically we're evaluating the values
0x80123450 + 0
0x80123450 + 1
0x80123450 + 2
...
all of which should evaluate to non-zero, which causes the printf statement to be executed. The question is what happens when i++ results in an integer overflow (the behavior of which is not well defined) or the value of i+++"Apple" results in an overflow for a pointer value. It's not clear that i+++"Apple" will ever result in a 0-valued expression.
This code SHOULD Have been written like this:
char *apple = "Apple";
for(i = 0; apple[i++];)
printf("Banana");
Not only is it clearer than the code posted in the original, it is also clearer to see what it does. But I guess this came from "Look how bizarre we can write things in C". There are lots of things that are possible in C that isn't a great idea.
It is also possible to learn to balance a plate of hot food on your head for the purpose of serving yourself dinner. It doesn't make it a particularly great idea - unless you don't have hands and feet, I suppose... ;)
Edit: Except this is wrong... The equivalent is:
char *apple = "Apple";
for(i = 0; apple+i++ != NULL;)
printf("Banana");
On a 64-bit machine, that will take a while. If it finishes in reasonable time (sending output to /dev/null), I will update. It takes approximitely three minutes on my machine (AMD 3.4GHz Phenom II).