C language, sometimes inexplicable, and sometimes amazing-small talk C language (25)

Source: Internet
Author: User

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



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.