こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

C++の文字列バッファの幅は4の倍数になる?

VisualC++でテストを行ってみたのですが、たとえば、

const char* sa = "a";

cout << (int)sa[1] << " ";
cout << (int)sa[2] << " ";
cout << (int)sa[3] << " ";

というような処理を書くと、表示される結果は必ず "0 0 0" となります。

また、

const char* sa = "a";
const char* sb = "bb";
const char* sc = "ccc";
const char* sd = "dddd";
const char* se = "eeeee";
....

のように文字列を定義しメモリの中身を見ると、各文字列が必ず4の倍数の幅で取得され、余りの部分には0が確保されているらしく、上記の場合ですと、メモリの内容が

sa -> a000
sb -> bb00
sc -> ccc0
sd -> dddd0000
se -> eeeee000

という風に確保されているようなのですが、これは正式なC++の仕様なのでしょうか?

もし正しい仕様であれば、それが明記されているサイト、資料等を教えていただければありがたいです。

もしくはそうでない場合、上記のようにならない(たとえば sa[3] != 0 となる)具体的な条件、再現方法を教えて頂きたいです。


宜しくお願いします。

投稿日時 - 2011-09-22 00:32:30

QNo.7026512

困ってます

質問者が選んだベストアンサー

皆様の言うとおり、コンパイラの仕様です。
ちなみに、VolatileつけてもVC++2010では変化なかったです。
リテラルにはどの修飾子が有効か、私は知りません。

一般的なOSのアーキテクチャでは、1バイトでもメモリを確保すると
1ページ(一般的に4096Byte)確保されます。
ですので、sa[3]を参照してもすぐさまメモリアクセスエラーに
なることはありません。
ですが、C++でいうところの「確保されてないメモリ」ですので
アクセスした際の動作は「不定」と定義されています。

Linux上のGccでテストしたところ、
sa -> a0ゴミゴミ・・・
でした。
この方がわかりやすいですよね。

たまたまVC++では4の倍数でゼロ埋めする、ただそれだけです。
C++では、確保していないメモリの値がどうなるかについての
仕様などありません(よってこの挙動は仕様上問題ない)。

プログラマとしては、確保されていないメモリ領域が何らかの値であることを
期待するコーディングはしてはいけません。

厳密にはsa[1]が0なのも環境依存で、'\0'が0を示す環境固有の挙動です。

投稿日時 - 2011-09-22 10:21:11

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.5

VC++2010 では,
const char* sa = "a";
const char* sb = "bb";
の部分はまずリテラル "a", "bb" に対して
'a', 0, (2バイトのあき) 'b', 'b', 0, (1バイトのあき)
と確保します. で sa, sb に対してはそれぞれの先頭を指すように初期化します. つまり
VC++ では 4バイト境界にアラインしているのでここで挙げられたようにふるまう
ということでしょう.

ちなみに「'\0'が0を示す環境固有の挙動」ってどういうことでしょうか>#4. '\0' を int に直せば必ず 0 です.

投稿日時 - 2011-09-22 12:27:13

お礼

#1~5の皆様ご回答いただきありがとうございます。

まとめると、仕様としては決まっていないが、4の倍数の位置から変数の領域が確保され残りの部分は0で埋められる、という条件のコンパイラが多いためこのような動作になる、という感じでしょうか。

>Linux上のGccでテストしたところ、
>sa -> a0ゴミゴミ・・・
>でした。

について、確認頂きありがとうございます。
私のほうでもgcc+Windowsで試してみましたが、windowsではやはり0が埋まっているようでしたが、環境によって反例があるというということは了解しました。

投稿日時 - 2011-09-23 00:08:55

ANo.3

既に回答にあるとおり、きちんと定義されてない領域へのアクセスは、「正常にできると仮定してはならない」ので、そのコンパイラや、コンパイルオプションでどうなるかは不明というのが正解です。

さて、それを踏まえた上で。
まず、「各文字のバッファが必ず4の倍数で確保されている」というのは、(提示された例だけを見たとしても)実は誤解です。
ただしくは、(おそらく、変数のアライメントが4に揃えられているので)それぞれの変数の先頭領域が、4の倍数の位置に置かれているというのが実情です。

つまり、sa の「バッファ」が確保されているのではなく、sa も sb も、4の倍数の位置に配置されているので、sa と sb の間に、3バイトの「ごみ」ができてしまっているということです。

といいつつ、このあたりは、コンパイラの実装に依存するので、「おそらく、こういう実装になっているケースが多い」というレベルですが。

投稿日時 - 2011-09-22 09:01:16

ANo.2

たぶん、Visual C++ではアドレスを4の倍数に合せるように作ってあるのでしょう。32bitCPUにとって扱いやすいので。
今手許に無いので試せないですが、サイズ優先の最適化とか、アライメントとかのオプションで変わるかも。

投稿日時 - 2011-09-22 03:19:48

ANo.1

const char* sa = "a";
に対して
sa[2]
へのアクセスは未定義動作. つまり「C++ の仕様」としてはどうなるか全く決まっていない.

ということで, 別のコンパイラを使えば違う動作になりえる.

投稿日時 - 2011-09-22 01:20:24

あなたにオススメの質問