An integer may be converted to any pointer type. The result is implementation-defined, might not be properly aligned, and might not point to an entity of the referenced type.
だから、「変換するまで」は OK 。 変換した後のポインタをいじくるとどうなるかわからないし、 何が入っているかもわからない、 と理解していました。 may だからコンパイルエラーにしても良いということですか?
The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly freed or reallocated).
ウイルス感染環境作んなボケェ! (スコア:-1, 荒らし)
メモリ破壊コード (スコア:1, 興味深い)
Re: (スコア:2, 参考になる)
別に何を再現する必要も無いのでは?
不定というのは、結果がどうなっても構わないという意味です。
暴走、例外はおろか、鼻から悪魔が飛び出しても言語規約上許されますし、
そんな分かりやすいリアクションではなく、一見正しく動作しているフリをしても構いません。
数多くのプログラマを苦しめてきた、Cの暗黒面の筆頭といって良い仕様です。
Re: (スコア:1, おもしろおかしい)
指定された壊れたメモリ領域を律儀に読み込んでとんでもない動作を実行し続けるだけで。
壊れていようがなんだろうがお構い無しに実行するのがCという言語の仕様。
まあコードからだけでは動作を予測し切る事は一般にできないもんだけど。
Re: (スコア:2, 参考になる)
なんかprintfをつけたら症状が出なくなったからデバッグ完了、と同じ類のvoodoo臭がぷんぷん漂ってきますよ。
Cの規格では確保したバッファの範囲外を読んだり書いたりアドレスを生成するだけで不定になります。
確保したバッファ+1のアドレス生成だけは認められていますが。
Re: (スコア:1, 興味深い)
アドレスを生成した時点で不定だったっけ?
void* pv = (void*)(0xDEADBEEF);
このコードが存在するだけで不定って意味になるけど、pvを使ってアクセスしなければ不定にはならないと思うよ。
Re: (スコア:2, 興味深い)
はポインタの指す先を読み書きしなければ大丈夫です。
整数はどんなポインタにも変換可能と規格で決まっています。
undefined なのは
char buf[1]; や char *buf = malloc ( 1 );
があったときに、(buf-2) や (buf+2) を含む式を評価した場合です。
例えば オーバーフローがあると例外を発生させるような種類の CPU で、
buf がメモリ空間の端っこ付近に割り当てられていたりすると
ひどい目にあうかもしれません。
一方 (buf-1) や (buf+1) は評価できることになってます。
一個までなら配列の範囲外を指すポインタを生成しても
オーバーフローしないと規格で決められています。
先の例で言うと、 buf はメモリ空間の端っこに配置されません。
必ず一要素分以上隙間があります。
嘘を書くな嘘を(Re:メモリ破壊コード) (スコア:2)
ポインタが指し示す先のオブジェクトの中には
alignment が問題となるものがある(たとえば、奇数ア
ドレスを持ち得ないなど)ので、整数→ポインタの結果
については実装依存です。
逆もしかり(実装依存)で、特にポインタ→整数で保持
しきれない環境では undefined-behavior です。
余計にアドレスを生成して良いのは配列へのポインタの
場合のみで(対象が malloc では駄目)、配列の最後の
要素を一つだけ越えて生成する場合に限られます(一つ
前は駄目)。
Re:嘘を書くな嘘を(Re:メモリ破壊コード) (スコア:2, 興味深い)
だから、「変換するまで」は OK 。
変換した後のポインタをいじくるとどうなるかわからないし、
何が入っているかもわからない、
と理解していました。
may だからコンパイルエラーにしても良いということですか?
> 余計にアドレスを生成して良いのは配列へのポインタの
> 場合のみで(対象が malloc では駄目)
これは本当ですか?
と、malloc の返すポインタは an array を指せるようになっているのですが、
binary + の項目には malloc で作られた object を指すポインタと
そうでない object を指すポインタを区別する記述は見つかりませんでした。
どこにその記述があるか教えて頂けると助かります。
>(一つ前は駄目)。
ごめんなさい。そうでした。
Re:嘘を書くな嘘を(Re:メモリ破壊コード) (スコア:1)
int i;
t_hoge a[10], *p=a;
for( i=0; i<10; i++ ){
*(p++) = hoge();
}
みたいなコードを許容するためだ、と書いてあった記憶があります。
この例では計10回 p++ が走りますが、10回目の p++ がエラーになってはいけない、ただそれだけだと。
なので、配列の後ろにアドレス空間上の余白を空けるかどうかとは別問題です。
そもそもポインタが実アドレスや論理アドレス、あるいはそれに準じる値を保持する約束も無いのです。
(もちろん実装するにあたり、常に後方にアドレス空間を空けておくという解決策もありでしょう。)
記事では10回 ++ した p を他の t_hoge* と比較できるかどうかも考察していたと思いますが、
そっちは忘れてしまいました(汗
Re:嘘を書くな嘘を(Re:メモリ破壊コード) (スコア:2)
これはその通りで、実装がどう動くかを理解して書く分
には構わない(実装依存でないのは 0 をポインタに変
換したときだけ、というのを勘違いしてた)。
これも私の嘘でした(何を勘違いしてたんだか…)。
Re:嘘を書くな嘘を(Re:メモリ破壊コード) (スコア:1)
そっちもオッケーだったはず。
t_hoge array[10], *ptr;
for (ptr = array; ptr < array+10; ptr++) {
…
}
みたいなコードでも正しく動くようにってことで、
「array+10」は「ポインタ」としては正しく存在し演算可能。
ただし、大丈夫なのはポインタを扱うところまでで、*(array+10)をやったらアウト。