この質問で言う C とは C99 のこと、 C++ は C++11 のことという前提を置きます。
以下のような配列をポインタで辿るプログラムがあったとして、 &foo[3]
の部分は C++ として未規定ではないと考えてよいですか?
cpp
1#include <stdio.h> 2 3int main(void) { 4 int foo[3] = {1, 2, 3}; 5 for(int* p=foo; p<&foo[3]; ++p) { 6 printf("%d", *p); 7 } 8}
私の思考過程をたどる形で質問をもう少し詳細にします。
C では
E1[E2]
は(*((E1)+(E2)))
と等価である- ポインタと整数の加算の結果は配列の要素か配列の最後の要素をひとつ超えたところを指さなければならない (そうでなければ未定義)
- ポインタと整数の加算の結果が配列の最後の要素をひとつ超えたところを指す場合、評価される単項
*
演算子のオペランドとしてはならない - 単項
&
のオペランドが単項*
の結果である場合は&
も*
も評価しない (両者を取り除いた場合と同じ結果)
という規則によって &foo[3]
は foo+3
と同じ結果となり、配列の最後の要素をひとつ越えた場所を指すポインタが生成されるけれどもそこにアクセスはしないので未定義を踏んでいないと考えられます。
しかし C++ では &
と *
を相殺する規則が存在しません。 そのかわりに
という規則があり、単項 &
のオペランドが単項 *
の結果であった場合には結果的にこの変換が起こらないのでオブジェクトが初期化されているかどうかが問題にされるパスを通らず未定義にはあたらないと思います。
この理解で正しいでしょうか? というのが質問の意図です。
C++11 より後の規格でも事情が大きく変わっているところはないと思いますが、もしも特に知る必要がある改定があるならば補足いただけるとありがたいです。
回答2件
あなたの回答
tips
プレビュー