ページ 11

ポインタのキャストにおけるメモリのアロケーション

Posted: 2016年1月26日(火) 07:14
by lisp implementer
お世話になります。

ある型へのポインタを別の型へのポインタにキャストする時、型変換の結果を新たな変数に代入しない場合にも、新たなメモリ領域がアロケートされているのでしょうか? それとも元のポインタのメモリ領域を別の型として解釈し直しているのでしょうか? やや細かい質問ですが、よろしくお願いします。

Re: ポインタのキャストにおけるメモリのアロケーション

Posted: 2016年1月26日(火) 08:06
by みけCAT
コンパイラやインタプリタの実装によるかもしれません。
あるコンパイラの仕様を推測するには、コンパイラの出力するアセンブリコードを読むといいでしょう。

Re: ポインタのキャストにおけるメモリのアロケーション

Posted: 2016年1月26日(火) 22:55
by lisp implementer
ありがとうございます。簡単なテストコードを書いてアセンブリコード化してみました。

コード:

#include <stdint.h>
#include <stdio.h>

int main() {
    void *p;
    printf("%llu\n", (uint64_t)(p));
    return 0;
}
このコードと、

コード:

#include <stdint.h>
#include <stdio.h>

int main() {
    void *p;
    printf("%llu\n", (uint64_t)((int *)(p)));
    return 0;
}
このコードを比較したところ、一つ目のコードのアセンブリコードが以下のようになり、

コード:

	pushq	%rbp
Ltmp0:
	.cfi_def_cfa_offset 16
Ltmp1:
	.cfi_offset %rbp, -16
	movq	%rsp, %rbp
Ltmp2:
	.cfi_def_cfa_register %rbp
	subq	$32, %rsp
	leaq	L_.str(%rip), %rdi
	movl	$0, -4(%rbp)
	movq	-16(%rbp), %rsi
	movb	$0, %al
	callq	_printf
	xorl	%ecx, %ecx
	movl	%eax, -20(%rbp)         ## 4-byte Spill
	movl	%ecx, %eax
	addq	$32, %rsp
	popq	%rbp
	retq
ポインタをキャストしたほうのコードが以下のようになりました。

コード:

	pushq	%rbp
Ltmp0:
	.cfi_def_cfa_offset 16
Ltmp1:
	.cfi_offset %rbp, -16
	movq	%rsp, %rbp
Ltmp2:
	.cfi_def_cfa_register %rbp
	subq	$32, %rsp
	leaq	L_.str(%rip), %rdi
	movl	$0, -4(%rbp)
	movq	-16(%rbp), %rax
	movq	%rax, %rsi
	movb	$0, %al
	callq	_printf
	xorl	%ecx, %ecx
	movl	%eax, -20(%rbp)         ## 4-byte Spill
	movl	%ecx, %eax
	addq	$32, %rsp
	popq	%rbp
	retq
変わった箇所は一つで、

movq -16(%rbp), %rsi

これが

movq -16(%rbp), %rax
movq %rax, %rsi

こうなったようです。アセンブリはほとんど分からないのですが、これは新たにメモリ領域が確保されているということで良いのですよね?

単純にアセンブリコードを比較するとコンパイラ側で簡単に最適化できそうなものですが、Cのコードに忠実にコンパイルするように出来ているのでしょうか。

Re: ポインタのキャストにおけるメモリのアロケーション

Posted: 2016年1月26日(火) 23:11
by みけCAT
lisp implementer さんが書きました:これは新たにメモリ領域が確保されているということで良いのですよね?
プログラムのサイズが増えるという意味ではメモリ領域が確保されているかもしれない(ページ単位などに切り上げると変わらないかもしれない)ですが、
単にポインタの値を一旦レジスタに格納しているだけなので、データ用のメモリ領域が新たに確保されているとはいえないでしょう。
lisp implementer さんが書きました:単純にアセンブリコードを比較するとコンパイラ側で簡単に最適化できそうなものですが、Cのコードに忠実にコンパイルするように出来ているのでしょうか。
コンパイラとコンパイルオプションによるでしょう。

Re: ポインタのキャストにおけるメモリのアロケーション

Posted: 2016年1月27日(水) 00:28
by lisp implementer
よく分かりました。ありがとうございます。アセンブリのmovを誤解していたようです。

キャストのコストは一応あるものの、メモリ内ではなくCPU内でのステップが1つ増えるだけならば、それほどのコストではないというところでしょうか。ありがとうございました。助かりました。