Cにおけるローカル変数の宣言時ゼロクリア
スポンサーリンク
このドキュメントの内容は、以下の通りです。
10年ぐらい前に libc を使わない、自分だけが書いたコードだけのプログラムを書いているときに、コンパイル時に memset() がない
とエラーが出て、コンパイルが止まったことがありました。
自分のコードは memset() なんて明示的に呼んでないので、
なんでかと思って、調べてみると、gcc から吐き出される
コードのなかに memset() が入っていました。
以下のようなコードは、配列の宣言時に、メモリをゼロクリアする
ことになります。
char s [ 255 ] = { 0 };
実行時に、スタックに確保した領域をゼロクリアしなければなりません。
メモリをゼロクリアするときにどうするかというと、
たいていのプログラマは、memset()/bzero() を利用するかと思います。
そういうわけで、ローカル変数の配列をゼロクリアする宣言を
した場合には、自動的に memset() で 0 で埋めるコードが
コンパイラによって出力されるわけです。
zero_clear.c
実際にそれが起こるコードを書いてみます。
#include <stdio.h> #include <stdlib.h> int main (int argc, char *argv[]) { char s [ 255 ] = { 0 }; exit (EXIT_SUCCESS); }
アセンブラコードの生成を行う。
gcc -S zero_clear.c
zero_clear.s
gcc に出力されたアセンブラのソースコードは以下の通りです。
.file "zero_clear.c" .text .p2align 4,,15 .globl main .type main, @function main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $276, %esp leal -259(%ebp), %edx movl $255, %eax movl %eax, 8(%esp) movl $0, 4(%esp) movl %edx, (%esp) call memset movl $0, (%esp) call exit .size main, .-main .ident "GCC: (GNU) 4.2.1 20070719 [FreeBSD]"
memsetが呼ばれないケース
どんなコードでもゼロクリアにmemset()が呼ばれるわけでもないようです。
配列のサイズを 1 にしてみます。
char s [ 1 ] = { 0 };
movb で 0 を書きこむだけになってます。
main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $20, %esp movb $0, -5(%ebp) movl $0, (%esp) call exit .size main, .-main
char s [ 2 ] = { 0 };
サイズを 2 にすると movw で 0 を書き込みます。
.file "zero_clear.c" .text .p2align 4,,15 .globl main .type main, @function main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $20, %esp movw $0, -6(%ebp) movl $0, (%esp) call exit .size main, .-main .ident "GCC: (GNU) 4.2.1 20070719 [FreeBSD]"
char s [ 3 ] = { 0 };
サイズを 3 にすると movw と movb で 0 を書き込みます。
.file "zero_clear.c" .text .p2align 4,,15 .globl main .type main, @function main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $20, %esp movw $0, -7(%ebp) movb $0, -5(%ebp) movl $0, (%esp) call exit .size main, .-main .ident "GCC: (GNU) 4.2.1 20070719 [FreeBSD]"
配列のサイズが64の場合。
.file "zero_clear.c" .text .p2align 4,,15 .globl main .type main, @function main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $100, %esp leal -69(%ebp), %edx movl $65, %eax movl %eax, 8(%esp) movl $0, 4(%esp) movl %edx, (%esp) call memset movl $0, (%esp) call exit .size main, .-main .ident "GCC: (GNU) 4.2.1 20070719 [FreeBSD]"
配列のサイズが 65 から memset を呼び出すコードが出力されるようです。
スポンサーリンク
スポンサーリンク
いつもシェア、ありがとうございます!
もっと情報を探しませんか?
関連記事
最近の記事
- パナソニック ジェットウォッシャードルツ EW-DJ61-Wのホースの修理
- LinuxセキュリティモジュールIntegrity Policy Enforcement
- アマゾンのEcho Show 5を買ったのでレビューします
- アマゾンのサイバーマンデーはAlexa Echo Show 5が安い
- Android スマートフォン OnePlus 7T と OnePlus 7の違い
- Android スマートフォン OnePlus 7 をAndroid10にアップデートしてみた
- クレジットカードのバーチャルカードの比較のまとめ
- 活動量計 Xiaomi Mi Band 4を買ってみたのでレビュー
- Android スマートフォン OnePlus 7 のレビュー
- AliExpressでスマートフォンを買い物してみた
- パソコンのホコリ対策 レンジフードフィルターと養生テープ
- 80PLUS GOLDのPC電源ユニットAntec NeoEco 750 Goldのレビュー
- イギリスの付加価値税 VAT は払い戻しを受けられる
- イギリスのロンドンでスーツケースなど荷物を預けられる場所は
- イギリスのロンドンで地下鉄やバスに乗るならオイスターカードを使おう
- イギリスのヒースロー空港からロンドン市内への行き方
- 航空便でほかの航空会社に乗り継ぎがある場合のオンラインチェックイン
- SFC会員がANA便ではなくベトナム航空のコードシェアを試して解ったこと
- ベトナムの入国審査でeチケットの掲示が必要だった話
- シアトルの交通ICカードはオルカカード(Orca)です
人気のページ
- Windows7 IME 辞書ツールで単語の登録に失敗しました
- C言語 popen()でコマンドを実行して出力を読み込む
- Windows7で休止状態にする方法
- CentOS MySQLの起動、停止、再起動
- loggerコマンドでsyslogにエラーを出力する方法
- パソコンパーツの買取をしてくれる店のまとめ
- Java Mapの使い方 get(),put(),remove(),size(),clear()
- 楽天のRポイントカードを作ってみた
- iPhone 5 から iPhone 6 に乗り換えたのでレビュー
- netstatコマンドのステータスの意味
スポンサーリンク
過去ログ
2020 : 01 02 03 04 05 06 07 08 09 10 11 122019 : 01 02 03 04 05 06 07 08 09 10 11 12
2018 : 01 02 03 04 05 06 07 08 09 10 11 12
2017 : 01 02 03 04 05 06 07 08 09 10 11 12
2016 : 01 02 03 04 05 06 07 08 09 10 11 12
2015 : 01 02 03 04 05 06 07 08 09 10 11 12
2014 : 01 02 03 04 05 06 07 08 09 10 11 12
2013 : 01 02 03 04 05 06 07 08 09 10 11 12
2012 : 01 02 03 04 05 06 07 08 09 10 11 12
2011 : 01 02 03 04 05 06 07 08 09 10 11 12
2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12
2005 : 01 02 03 04 05 06 07 08 09 10 11 12
2004 : 01 02 03 04 05 06 07 08 09 10 11 12
2003 : 01 02 03 04 05 06 07 08 09 10 11 12