c++におけるconst定数の記憶位置検討

2821 ワード

まず奇妙なコードを見てみましょう.
#include 

int main()
{	
	const float intValue=2.2;
	float *j=(float *)&intValue;
	*j=1.1;
	
	printf("intValue address:0x%x
",&intValue); printf("j address:0x%x
",j); printf("j:%f
",*j); printf("intValue:%f
",intValue); return 0; }
の出力結果は次のとおりです.
intValue address:bfd8dddc
j address:bfd8dddc
j:1.100000
intValue:2.200000
これは、なぜアドレスが同じなのか、指す値が異なるのか~~コンパイラがconst定数を処理するいくつかのメカニズムを検討します.以上のコード生成のアセンブリは以下の通りです.
.file	"constASM.cpp"
	.section	.rodata //rodata ,    printf      
.LC2:
	.string	"intValue address:0x%x
" .LC3: .string "j address:0x%x
" .LC4: .string "j:%f
" .LC6: .string "intValue:%f
" .text .globl main .type main, @function main: .LFB2: leal 4(%esp), %ecx //esp:Stack Pointer, , .LCFI0: andl $-16, %esp pushl -4(%ecx) .LCFI1: pushl %ebp //ebp .LCFI2: movl %esp, %ebp .LCFI3: pushl %ecx .LCFI4: subl $36, %esp //esp 36, 36 .LCFI5: movl $0x400ccccd, %eax //&intValue , , .LC5, movl %eax, -12(%ebp) // (ebp-12) 0x400ccccd,0x400ccccd, 2.2 leal -12(%ebp), %eax movl %eax, -8(%ebp) // (ebp-8) 0x400ccccd movl -8(%ebp), %edx // (ebp-8) edx movl $0x3f8ccccd, %eax movl %eax, (%edx) // (ebp-8) 0x3f8ccccd, 1.1 leal -12(%ebp), %eax movl %eax, 4(%esp) // (ebp-12) (4+esp) printf movl $.LC2, (%esp) // .LC2 (esp) , printf call printf //printf("intValue address:0x%x
",&intValue); movl -8(%ebp), %eax movl %eax, 4(%esp) movl $.LC3, (%esp) call printf //printf("j address:0x%x
",j); movl -8(%ebp), %eax flds (%eax) // , (ebp-8) fstpl 4(%esp) movl $.LC4, (%esp) call printf //printf("j:%f
",*j); fldl .LC5 // , LC5, !!! intValue, !! fstpl 4(%esp) // movl $.LC6, (%esp) call printf //printf("intValue:%f
",intValue); movl $0, %eax addl $36, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret .LFE2: .size main, .-main .section .rodata .align 8 .LC5: .long -1610612736 .long 1073846681 .section .eh_frame,"a",@progbits .Lframe1: .long .LECIE1-.LSCIE1 .LSCIE1: .long 0x0 .byte 0x1 . .// . .LEFDE1: .ident "GCC: (GNU) 4.3.0 20080428 (Red Hat 4.3.0-8)" .section .note.GNU-stack,"",@progbits

以上の分析から以上の結論を得ることができる:1.const定数に対してアドレスを取ると、コンパイラはメモリ割り当てを行い、定数テーブルに記録されたアドレスではなく即時数に変換してメモリに格納します.
2.定数を使用する場合、コンパイラは定数テーブルに戻って対応する定数をクエリーし、メモリ割り当てに関係なく、作成した定数のメモリアドレスにも関係なく置き換えます.