考虑以下代码
#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 ++中的错误修复,还是由于优化而偶然修复的错误?
答案 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: