読者です 読者をやめる 読者になる 読者になる

ゆとりーなの日記

日記的な事を書いて行くと思はれる

最近マイブームの可變長引數

風呂あがりに何となく

Binary Hacks ―ハッカー秘伝のテクニック100選
Binary Hacks ―ハッカー秘伝のテクニック100選高林 哲 鵜飼 文敏 佐藤 祐介 浜地 慎一郎 首藤 一幸

オライリー・ジャパン 2006-11-14
売り上げランキング : 131355


Amazonで詳しく見る
by G-Tools
を讀んでゐたのですが64bit環境のLinuxでNULLを0にすると可變長引數で殘當するみたいな話が氣になつたのでチロチロ遊んでみました。だつて、古のC++だとNULLが(void *)0ぢやないから詰んでるぢやないですか。
と言ふわけでC言語で書いてダンプを吐いて見ました。

#include <stdarg.h>
#include <stdio.h>

void foo(const char *fmt, ...);

int main(void) {
  foo("fmt", "1", "2", "3", "4", "5", "6", "7", "8", "9", 0);
  return 0;
}

void foo(const char *fmt, ...) {
  va_list args;
  const char *s;
  va_start(args, fmt);
  puts(fmt);
  s = va_arg(args, const char *);
  while (s) {
    puts(s);
    s = va_arg(args, const char *);
  }
  va_end(args);
}

まあ64ビット環境は結構引數積まないとレジスタつてしまふので頑張りました(謎)。で、結果です。

0000000000400440 <main>:
  400440:	48 83 ec 38          	sub    $0x38,%rsp
  400444:	31 c0                	xor    %eax,%eax
  400446:	41 b9 c4 06 40 00    	mov    $0x4006c4,%r9d
  40044c:	c7 44 24 20 00 00 00 	movl   $0x0,0x20(%rsp)
  400453:	00 
  400454:	48 c7 44 24 18 d2 06 	movq   $0x4006d2,0x18(%rsp)
  40045b:	40 00 
  40045d:	41 b8 c6 06 40 00    	mov    $0x4006c6,%r8d
  400463:	48 c7 44 24 10 d4 06 	movq   $0x4006d4,0x10(%rsp)
  40046a:	40 00 
  40046c:	48 c7 44 24 08 d6 06 	movq   $0x4006d6,0x8(%rsp)
  400473:	40 00 
  400475:	b9 c8 06 40 00       	mov    $0x4006c8,%ecx
  40047a:	48 c7 04 24 d8 06 40 	movq   $0x4006d8,(%rsp)
  400481:	00 
  400482:	ba ca 06 40 00       	mov    $0x4006ca,%edx
  400487:	be cc 06 40 00       	mov    $0x4006cc,%esi
  40048c:	bf ce 06 40 00       	mov    $0x4006ce,%edi
  400491:	e8 fa 00 00 00       	callq  400590 <foo>
  400496:	31 c0                	xor    %eax,%eax
  400498:	48 83 c4 38          	add    $0x38,%rsp
  40049c:	c3                   	retq   
  40049d:	0f 1f 00             	nopl   (%rax)

當然の樣にmovlですね。實行結果も殘當です。

fmt
1
2
3
4
5
6
7
8
9
Segmentation fault

で、ここまでがC言語の話、古へのC++はどうなつてるんだらうみたいな話になるわけでして、

#include <stddef.h>
#include <stdio.h>

int main() {
  printf("%d\n", sizeof(NULL));
  return 0;
}

見るとNULLのサイズは8でした。耐へてますね。型を調べてみたら

#include <stddef.h>
#include <stdio.h>
#include <typeinfo> 

int main() {
  printf("%s\n", typeid(NULL).name());
  return 0;
}
l

と出てきたのでどうもlongらしいです。long intつて8バイトなんですね(long longが8バイトだと思つてたりしました)。
何となくグダりましたが眠いのを言ひ訣に今日はこの邊で...