C编译器(clang)如何执行const?

Ama*_*asu 4 c const

使用Clang,以下内容:

#include <stdio.h>

int main(void)
{   double const x = 1.234;
    double *p = (double *) &x;
    /* Same with double *p = &x; but with a mere warning from clang
       Clang++ does raise an error in this case.
    */
    *p = 5.678;

    printf("*p = %f\n", *p);
    printf(" x = %f\n", x);

    if (&x == p) {
        printf("&x = %p\n", &x);
        printf(" p = %p\n", p);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

给出输出:

* p = 5.678000
x = 1.234000
&x = 00000080288FFEA8
p = 00000080288FFEA8

编译器究竟如何做到这一点?编译器如何成功编译避免出现以下输出:

* p = 5.678000
x = 5.678000
&x = 00000080288FFEA8
p = 00000080288FFEA8

Bat*_*eba 9

修改对象的行为,该行为最初是const通过强制类型转换将const未定义的类型删除。

编译器是否会警告您有关未定义的行为,取决于编译器。完全笼统地做到这一点是不可能的。

优化编译器将基于您的程序不包含未定义行为的事实做出假设。铛输出与它保持一致代替1.234xprintf通话; 这是合法的,因为x不允许更改。


Chr*_*ons 5

Bathsheba假设编译器可能会将硬编码的值传递给printf。我以为我要查看生成的程序集,看看是否可以验证假设。

我对所讨论的代码进行了一些小的修改:将doubles 更改为s以便int于理解我在程序集中看到的内容,并且还添加了另一个print语句,将这些值加在一起。

编译与 clang -std=c11 -g -O2

#include <stdio.h>

int main(void)
{   int const x = 1;
    int *p = (int *) &x;
    *p = 2;

    printf("*p = %d\n", *p);
    printf(" x = %d\n", x);
    printf(" x + p = %d\n", x + *p);

    if (&x == p) {
        printf("&x = %p\n", (void *)&x);
        printf(" p = %p\n", (void *)p);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

反汇编的代码(仅是主要部分):

0000000000400510 <main>:
  400510:   53                      push   %rbx
  400511:   48 83 ec 10             sub    $0x10,%rsp
  400515:   c7 44 24 0c 02 00 00    movl   $0x2,0xc(%rsp)
  40051c:   00 
  40051d:   bf 10 06 40 00          mov    $0x400610,%edi
  400522:   be 02 00 00 00          mov    $0x2,%esi <----- hard-coded 2 passed in
  400527:   31 c0                   xor    %eax,%eax
  400529:   e8 c2 fe ff ff          callq  4003f0 <printf@plt>
  40052e:   bf 19 06 40 00          mov    $0x400619,%edi
  400533:   be 01 00 00 00          mov    $0x1,%esi <----- hard-coded 1 passed in
  400538:   31 c0                   xor    %eax,%eax
  40053a:   e8 b1 fe ff ff          callq  4003f0 <printf@plt>
  40053f:   bf 22 06 40 00          mov    $0x400622,%edi
  400544:   be 03 00 00 00          mov    $0x3,%esi <----- hard-coded 3 passed in (2+1)
  400549:   31 c0                   xor    %eax,%eax
  40054b:   e8 a0 fe ff ff          callq  4003f0 <printf@plt>
  400550:   48 8d 5c 24 0c          lea    0xc(%rsp),%rbx
  400555:   bf 2f 06 40 00          mov    $0x40062f,%edi
  40055a:   31 c0                   xor    %eax,%eax
  40055c:   48 89 de                mov    %rbx,%rsi
  40055f:   e8 8c fe ff ff          callq  4003f0 <printf@plt>
  400564:   bf 38 06 40 00          mov    $0x400638,%edi
  400569:   31 c0                   xor    %eax,%eax
  40056b:   48 89 de                mov    %rbx,%rsi
  40056e:   e8 7d fe ff ff          callq  4003f0 <printf@plt>
  400573:   31 c0                   xor    %eax,%eax
  400575:   48 83 c4 10             add    $0x10,%rsp
  400579:   5b                      pop    %rbx
  40057a:   c3                      retq   
  40057b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
Run Code Online (Sandbox Code Playgroud)

实际上,编译器正在传递硬编码的值。