Author: Chen Xi
Date: 12:53:12
Environment: [Mac 10.7.1 lion intel I3 supports 64-bit gcc4.2.1 xcode4.2]
Reprinted please indicate the source
Q1: Why is the output below not displayed in the code order?
#include <stdio.h>#include <unistd.h>int main(int argc, char **argv){ while(1) { fprintf(stdout, "stdout."); fprintf(stderr, "stderr."); sleep(1); } return 0; }
A: If you change the code to the following, the output is displayed in the code order:
#include <stdio.h>#include <unistd.h>int main(int argc, char **argv){ setbuf(stdout, NULL); // set stdout to no buffer while(1) { fprintf(stdout, "stdout."); fprintf(stderr, "stderr."); sleep(1); } return 0; }
Q2: Why is the result of the printf function returned in the following code not 1?
# Include <stdio. h> # define print_d (intvalue) printf (# intvalue "is % d \ n", (intvalue); int main (INT argc, char ** argv) {char * STR = "I"; print_d (printf (STR); Return 0 ;}
The code above saves the code as a UTF-8.
A: I have explained in detail in another post: http://blog.csdn.net/cxsjabcabc/article/details/7528227.
If you change the code file encoding to another one, the answer is: printf returns the actual number of bytes output. For example.
Q3: Why does the output of the following code change the value of B?
#include <stdio.h>#define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue));int main(int argc, char **argv){ int a = 1; switch(a) { int b = 2; case 1: PRINT_D(b) break; default: PRINT_D(b) break; } return 0; }
A: The reason is that in the composite statement of the switch statement body, the statement located before the first case or default label will never be executed. Therefore, B is not initialized.
In addition, let's look at the assembly and draw a conclusion that the case and default labels are equivalent to an address. The compiler uses statements such as JMP, je, and JNE to directly jump to the corresponding position for execution, instead of analyzing the initialization process.
0x00001f10 <main+0>:push %ebp0x00001f11 <main+1>:mov %esp,%ebp0x00001f13 <main+3>:sub $0x28,%esp0x00001f16 <main+6>:mov 0xc(%ebp),%eax0x00001f19 <main+9>:mov 0x8(%ebp),%ecx0x00001f1c <main+12>:movl $0x0,-0x4(%ebp)0x00001f23 <main+19>:mov %ecx,-0x8(%ebp)0x00001f26 <main+22>:mov %eax,-0xc(%ebp)0x00001f29 <main+25>:movl $0x1,-0x10(%ebp)0x00001f30 <main+32>:xor %dl,%dl0x00001f32 <main+34>:test %dl,%dl0x00001f34 <main+36>:jne 0x1f52 <main+66>0x00001f36 <main+38>:jmp 0x1f38 <main+40>0x00001f38 <main+40>:lea 0x1fa0,%eax0x00001f3e <main+46>:mov -0x14(%ebp),%ecx0x00001f41 <main+49>:mov %eax,(%esp)0x00001f44 <main+52>:mov %ecx,0x4(%esp)0x00001f48 <main+56>:call 0x1f7a <dyld_stub_printf>0x00001f4d <main+61>:mov %eax,-0x18(%ebp)0x00001f50 <main+64>:jmp 0x1f6a <main+90>0x00001f52 <main+66>:lea 0x1fa0,%eax0x00001f58 <main+72>:mov -0x14(%ebp),%ecx0x00001f5b <main+75>:mov %eax,(%esp)0x00001f5e <main+78>:mov %ecx,0x4(%esp)0x00001f62 <main+82>:call 0x1f7a <dyld_stub_printf>0x00001f67 <main+87>:mov %eax,-0x1c(%ebp)0x00001f6a <main+90>:mov $0x0,%eax0x00001f6f <main+95>:add $0x28,%esp0x00001f72 <main+98>:pop %ebp0x00001f73 <main+99>:ret
Note the assembly at the position of main + 36 and main + 38. The two jump statements directly find the label and ignore the previous code.
If you change the source code to the following, 3 cannot be output:
int main(int argc, char **argv){ int a = 2; switch(a) { int b = 2; case 1: PRINT_D(b) break; b = 3; case 2: PRINT_D(b) break; default: PRINT_D(b) break; } return 0; }
Q4: the sizeof operator is followed by I ++. Why is I not auto-incrementing?
#include <stdio.h>#define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue));int main(int argc, char **argv){ int i = 1; PRINT_D(sizeof(i++)) PRINT_D(i) return 0; }
A: The reason is that sizeof automatically calculates its value during compilation. For I ++, the compiler only sees its type, but does not calculate its value. Let's look at the Assembly:
0x00001ef0 <main+0>:push %ebp0x00001ef1 <main+1>:mov %esp,%ebp0x00001ef3 <main+3>:push %ebx0x00001ef4 <main+4>:push %edi0x00001ef5 <main+5>:push %esi0x00001ef6 <main+6>:sub $0x2c,%esp0x00001ef9 <main+9>:mov 0xc(%ebp),%eax0x00001efc <main+12>:mov 0x8(%ebp),%ecx0x00001eff <main+15>:mov $0x0,%edx0x00001f04 <main+20>:lea 0x1fa7,%esi0x00001f0a <main+26>:lea 0x1f94,%edi0x00001f10 <main+32>:mov $0x4,%ebx0x00001f15 <main+37>:movl $0x0,-0x10(%ebp)0x00001f1c <main+44>:mov %ecx,-0x14(%ebp)0x00001f1f <main+47>:mov %eax,-0x18(%ebp)0x00001f22 <main+50>:movl $0x1,-0x1c(%ebp)0x00001f29 <main+57>:mov %edi,(%esp)0x00001f2c <main+60>:movl $0x4,0x4(%esp)0x00001f34 <main+68>:mov %edx,-0x20(%ebp)0x00001f37 <main+71>:mov %ebx,-0x24(%ebp)0x00001f3a <main+74>:mov %esi,-0x28(%ebp)0x00001f3d <main+77>:call 0x1f6e <dyld_stub_printf>0x00001f42 <main+82>:mov -0x1c(%ebp),%ecx0x00001f45 <main+85>:mov -0x28(%ebp),%edx0x00001f48 <main+88>:mov %edx,(%esp)0x00001f4b <main+91>:mov %ecx,0x4(%esp)0x00001f4f <main+95>:mov %eax,-0x2c(%ebp)0x00001f52 <main+98>:call 0x1f6e <dyld_stub_printf>0x00001f57 <main+103>:mov -0x20(%ebp),%ecx0x00001f5a <main+106>:mov %eax,-0x30(%ebp)0x00001f5d <main+109>:mov %ecx,%eax0x00001f5f <main+111>:add $0x2c,%esp0x00001f62 <main+114>:pop %esi0x00001f63 <main+115>:pop %edi0x00001f64 <main+116>:pop %ebx0x00001f65 <main+117>:pop %ebp0x00001f66 <main+118>:ret
Note the position of main + 60. It puts the value 4 obtained by sizeof (I ++) into the stack and does not auto-increment I.
Q5: Why does an expression like 2 ["hello"] mean?
#include <stdio.h>#define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue));#define PRINT_CH(charValue) printf(#charValue" is %c\n", (charValue));int main(int argc, char **argv){ char ch = 2["hello"]; PRINT_CH(ch) return 0; }
A: 2 ["hello"] is equivalent to "hello" [2], and char * STR = "hello"; STR [2]. But why?
Because the compiler uses the pointer addition and subtraction Calculation Method for array access, that is, 2 ["hello"] = * (2 + "hello"), "hello" is a character pointer, * (2 + "hello") = * ("hello" + 2), so the conclusion is displayed.
Q6: Why is the output result of an integer in % F format changed?
#include <stdio.h>#define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue));#define PRINT_F(floatValue) printf(#floatValue" is %f\n", (floatValue));int main(){ int d = 2; PRINT_F(d) return 0;}
A: The reason is that when printf analyzes the % F format, sizeof (float) bytes are retrieved from the corresponding address and then output as float format. Therefore, the output is generally incorrect.
For the internal float format, the IEEE 754 standard is clearly written. If a similar problem occurs, you can use the following structure for simple verification:
// IEEE 754 single floating number's format(intel little-endian mode)typedef union{ // float value float f; // intel bits mode that stands for float value struct { unsigned int dot : 23; // low bits unsigned int exp : 8; // middle bits unsigned int sign : 1; // highest bit }float_bit;}float_value;
A simple test code:
#include <stdio.h>#define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue));#define PRINT_F(floatValue) printf(#floatValue" is %f\n", (floatValue));// IEEE 754 single floating number's format(intel little-endian mode)typedef union{ // float value float f; // intel bits mode that stands for float value struct { unsigned int dot : 23; // low bits unsigned int exp : 8; // middle bits unsigned int sign : 1; // highest bit }float_bit;}float_value;int main(int argc, char **argv){ float_value fv; fv.float_bit.sign = 1; fv.float_bit.exp = 128; fv.float_bit.dot = 0; PRINT_F(fv.f); return 0; }
Output:
fv.f is -2.000000
Author: Chen Xi
Date: 12:53:12
Environment: [Mac 10.7.1 lion intel I3 supports 64-bit gcc4.2.1 xcode4.2]
Reprinted please indicate the source