能够在C中更改const的值,但不能在C ++中更改

时间:2014-04-16 05:51:11

标签: c++ c optimization const

考虑以下代码

#include <stdio.h>
#include <string.h>

main()
{
   const int a = 2;
   long p = (long)&a;
   int *c = (int *)p;
   *c =3;
   printf("%d", a);
}

此代码可以将值更改为C中的a,但不能更改为C ++中的值。我了解C ++正在应用优化并将a的实例替换为2。那么这是一个C ++中的错误修复,还是由于优化而偶然修复的错误?

5 个答案:

答案 0 :(得分:6)

这不是C与C ++问题。通过修改const值(以及通过long双重转换指针),您输入两种语言中undefined behaviour的领域。因此,差异仅仅取决于未定义行为如何表现出来。

答案 1 :(得分:6)

无论是直接还是间接,修改const值都是未定义的行为。这可能在C中编译,甚至可能在您的机器上运行没有问题,但它仍然是未定义的行为。

C和C ++之间的区别在于:使用const int a = 2,C ++将a视为常量表达式,例如,您可以使用a作为数组维度:

int n[a];  //fine in C++

但在C语言中,a不是常量表达式,代码相同:

int n[a];  //VLA in C99

此处n不是固定大小的数组,而是可变长度数组。

答案 2 :(得分:1)

你正在抛弃&a中的常量并修改指向值,这在C和C ++中都是未定义的行为(通过long的行程只会增加一些无偿的UB)。在C ++中,您的编译器恰好会更加积极地优化常量,但情况的关键不变。

答案 3 :(得分:0)

您的代码在C ++上生成未定义的行为,因为您访问的内存不应该

include <stdio.h>
#include <string.h>

void main()
{
   const int a = 2;
   printf("%x != %x !!", sizeof(long), sizeof(void*)); // on a x64 system 4 != 8
   long p = (long)&a;
   int *c = (int *)p;
   *c =3;
   printf("%d", a);
}

即使它在32位系统上工作,通过丢弃常量修改const内存也是两种语言中未定义的行为。

答案 4 :(得分:0)

以下是g ++生成的汇编代码。编译器静态使用“$ 2”而不是“a”,但是在gcc的情况下,它不执行任何静态优化。我想不应该有任何未定义的行为。

    .Ltext0:
                    .section    .rodata

                .LC0:
0000 256400         .string "%d"
                    .text
                    .globl  main
                main:

                .LFB0:

                    .cfi_startproc
                    .cfi_personality 0x3,__gxx_personality_v0
                    .cfi_lsda 0x3,.LLSDA0
0000 55             pushq   %rbp
                    .cfi_def_cfa_offset 16
                    .cfi_offset 6, -16
0001 4889E5         movq    %rsp, %rbp
                    .cfi_def_cfa_register 6
0004 4883EC20       subq    $32, %rsp

                .LBB2:

0008 C745EC02       movl    $2, -20(%rbp)
     000000

000f 488D45EC       leaq    -20(%rbp), %rax
0013 488945F0       movq    %rax, -16(%rbp)

0017 488B45F0       movq    -16(%rbp), %rax
001b 488945F8       movq    %rax, -8(%rbp)

001f 488B45F8       movq    -8(%rbp), %rax
0023 C7000300       movl    $3, (%rax)
     0000

0029 488B45F8       movq    -8(%rbp), %rax
002d 8B00           movl    (%rax), %eax
002f 89C6           movl    %eax, %esi
0031 BF000000       movl    $.LC0, %edi
     00
0036 B8000000       movl    $0, %eax
     00

                .LEHB0:

003b E8000000       call    printf
     00

0040 BE020000       movl    $2, %esi
     00
0045 BF000000       movl    $.LC0, %edi
     00
004a B8000000       movl    $0, %eax
     00
004f E8000000       call    printf
     00

                .LEHE0:

0054 B8000000       movl    $0, %eax
     00
0059 EB08           jmp .L5

                .L4:

005b 4889C7         movq    %rax, %rdi

                .LEHB1:

005e E8000000       call    _Unwind_Resume
     00

                .LEHE1:

                .L5:

                .LBE2:

0063 C9             leave
                    .cfi_def_cfa 7, 8
0064 C3             ret
                    .cfi_endproc

                .LFE0:

                    .globl  __gxx_personality_v0
                    .section    .gcc_except_table,"a",@progbits

                .LLSDA0:

0000 FF             .byte   0xff
0001 FF             .byte   0xff
0002 01             .byte   0x1
0003 08             .uleb128 .LLSDACSE0-.LLSDACSB0

                .LLSDACSB0:

0004 3B             .uleb128 .LEHB0-.LFB0
0005 19             .uleb128 .LEHE0-.LEHB0
0006 5B             .uleb128 .L4-.LFB0
0007 00             .uleb128 0
0008 5E             .uleb128 .LEHB1-.LFB0
0009 05             .uleb128 .LEHE1-.LEHB1
000a 00             .uleb128 0
000b 00             .uleb128 0

                .LLSDACSE0:

                    .text

                .Letext0: