- ベストアンサー
C++の文字列バッファの幅は4の倍数になる?
- C++の文字列バッファは常に4の倍数の幅で取得され、余りの部分には0が確保されます。
- この仕様は正式なC++の仕様であり、メモリの内容もそれに従って確保されます。
- 具体的な条件や再現方法については、資料やサイトなどに明記されていないようです。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
皆様の言うとおり、コンパイラの仕様です。 ちなみに、VolatileつけてもVC++2010では変化なかったです。 リテラルにはどの修飾子が有効か、私は知りません。 一般的なOSのアーキテクチャでは、1バイトでもメモリを確保すると 1ページ(一般的に4096Byte)確保されます。 ですので、sa[3]を参照してもすぐさまメモリアクセスエラーに なることはありません。 ですが、C++でいうところの「確保されてないメモリ」ですので アクセスした際の動作は「不定」と定義されています。 Linux上のGccでテストしたところ、 sa -> a0ゴミゴミ・・・ でした。 この方がわかりやすいですよね。 たまたまVC++では4の倍数でゼロ埋めする、ただそれだけです。 C++では、確保していないメモリの値がどうなるかについての 仕様などありません(よってこの挙動は仕様上問題ない)。 プログラマとしては、確保されていないメモリ領域が何らかの値であることを 期待するコーディングはしてはいけません。 厳密にはsa[1]が0なのも環境依存で、'\0'が0を示す環境固有の挙動です。
その他の回答 (4)
- Tacosan
- ベストアンサー率23% (3656/15482)
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 です.
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
既に回答にあるとおり、きちんと定義されてない領域へのアクセスは、「正常にできると仮定してはならない」ので、そのコンパイラや、コンパイルオプションでどうなるかは不明というのが正解です。 さて、それを踏まえた上で。 まず、「各文字のバッファが必ず4の倍数で確保されている」というのは、(提示された例だけを見たとしても)実は誤解です。 ただしくは、(おそらく、変数のアライメントが4に揃えられているので)それぞれの変数の先頭領域が、4の倍数の位置に置かれているというのが実情です。 つまり、sa の「バッファ」が確保されているのではなく、sa も sb も、4の倍数の位置に配置されているので、sa と sb の間に、3バイトの「ごみ」ができてしまっているということです。 といいつつ、このあたりは、コンパイラの実装に依存するので、「おそらく、こういう実装になっているケースが多い」というレベルですが。
- kmee
- ベストアンサー率55% (1857/3366)
たぶん、Visual C++ではアドレスを4の倍数に合せるように作ってあるのでしょう。32bitCPUにとって扱いやすいので。 今手許に無いので試せないですが、サイズ優先の最適化とか、アライメントとかのオプションで変わるかも。
- Tacosan
- ベストアンサー率23% (3656/15482)
const char* sa = "a"; に対して sa[2] へのアクセスは未定義動作. つまり「C++ の仕様」としてはどうなるか全く決まっていない. ということで, 別のコンパイラを使えば違う動作になりえる.
お礼
#1~5の皆様ご回答いただきありがとうございます。 まとめると、仕様としては決まっていないが、4の倍数の位置から変数の領域が確保され残りの部分は0で埋められる、という条件のコンパイラが多いためこのような動作になる、という感じでしょうか。 >Linux上のGccでテストしたところ、 >sa -> a0ゴミゴミ・・・ >でした。 について、確認頂きありがとうございます。 私のほうでもgcc+Windowsで試してみましたが、windowsではやはり0が埋まっているようでしたが、環境によって反例があるというということは了解しました。