0

これはすでに尋ねられている非常に基本的な質問かもしれませんが、ここでの答えがchar ptrへのintポインターのキャスト、およびその逆が私の場合に当てはまるかどうかはよくわかりませんでした。だから本質的に私は次のようなものを持っています:

void* head = sbrk(1024);  //allocate 1024 bytes in heap   

*((int*)(head+size)) = value;   //value and size are int with valoues between 1 and 1023

サイズの任意の値に対して上記が機能しない場合、サイズの値の制限は何ですか?4で割り切れる必要がありますか?

4

3 に答える 3

2

まず第一に、voidポインタに対してポインタ演算を行うことはできません。そのコードはコンパイルすらすべきではありません。

説明のために、代わりにcharポインタがあると仮定します。そして正式には、そのようなキャストとそれに続くアクセスは未定義の動作です。ただし、現実の世界では、手動で位置合わせを確認できれば、コードは常に機能します。書き込むアドレスが整列されたメモリ位置にあることを確認する必要があります。そうでない場合、コードが機能するという保証はありません。


ISO 9899:2011標準からの関連する引用符を使用して編集します。voidポインターでのポインター演算が未定義の動作である理由:

6.3.2.2無効

void式(void型の式)の(存在しない)値は、いかなる方法でも使用してはならず、暗黙的または明示的な変換(voidを除く)はそのような式に適用されないものとします。

6.5.6加法演算子

/-/

さらに、両方のオペランドが算術型であるか、一方のオペランドが完全なオブジェクト型へのポインタであり、もう一方が整数型である必要があります。(インクリメントは1を加算するのと同じです。)

4適合性

制約またはruntimeconstraintの外側に表示される「shall」または「shallnot」要件に違反した場合、動作は未定義です。それ以外の場合、未定義の動作は、この国際標準では「未定義の動作」という言葉によって、または動作の明示的な定義の省略によって示されます。これら3つの間で強調に違いはありません。それらはすべて「未定義の振る舞い」を説明しています。

標準の規範的なテキストに違反するコードが「コンパイルする必要がある」かどうかは確かに議論できますが、議論がOPにとって有益であるとは思いません。未定義の動作に依存するコードを記述しないでください。

于 2013-03-25T07:20:46.567 に答える
1

使用memcpy()

memcpy((char*)head + size, &value, sizeof(value));
于 2013-03-25T07:32:34.297 に答える
0

多くのシステムでは、この状況ではsize、4の倍数である必要があります(システムのサイズが4バイトであることを含め、以下に詳述する追加の条件が適用さintれます)。これを必要としないシステムでは、通常、これが推奨されます。

まず、のタイプheadvoid *であり、C標準では、。を使用してポインタ演算を実行したときに何が起こるかを定義していませんvoid *

一部のコンパイラ、特にGCCとその継承者は、この算術演算を型がであるかのように扱いchar *ます。これに基づいて進めます。

第二に、私はsbrk特定の配置でアドレスを返す保証を知りません。

sbrkそれが適切に調整されたアドレスを返し、C実装が評価するための単純なことを行うと仮定します。これは、 (に変換された)の値をアドレス* (int *) (head + size) = valueに書き込むストア命令を発行することです。valueinthead + size

次に、あなたの質問は次のようになります。私のコンピューティングプラットフォームは、intこの住所の店舗で何をしますか?

プラットフォーム上でhead + size適切に調整されたアドレスである限り、ストアは期待どおりに実行されます。intほとんどのプラットフォームでは、4バイト整数は4バイトアライメントを優先し、8バイト整数は8バイトアライメントを優先します。headこのプリファレンスの倍数に調整され、このプリファレンスの倍数である限りsize、ストアは正常に実行されます。

それ以外の場合、何が起こるかはプラットフォームによって異なります。一部のプラットフォームでは、ハードウェアはストアを実行しますが、メモリへの2つの別々の書き込みに分割されるため、通常のストア命令よりも実行が遅くなる場合があります。(これは、同じメモリを共有する他のプロセスが、値の一部が保存されている間はメモリを読み取ることができるが、他の部分は保存されていない可能性があることも意味します。これも、コンピューティングプラットフォームの特性によって異なります。)

一部のプラットフォームでは、ハードウェアは、プログラムの実行を中断し、オペレーティングシステムに制御を移す例外を通知します。一部のオペレーティングシステムは、失敗した命令を分析し、目的のストアを実行する代替命令を実行することによって、ずれたストアを修正します(または、オペレーティングシステムは、この修正作業を行う、プログラム内の特別なコード(場合によっては自動的に含まれるライブラリ内)に例外を中継します) 。これらのプラットフォームでは、位置がずれているストアは非常に遅くなります。プログラムのパフォーマンスを大幅に低下させる可能性があります。

一部のプラットフォームでは、ハードウェアが例外を通知し、オペレーティングシステムが不整合なストアを修正しません。代わりに、オペレーティングシステムはプロセスを終了するか、問題に関するシグナルを送信します。これにより、多くの場合、プロセスが終了します。(他の可能性には、デバッガーのトリガーや、信号を処理するためにプログラムに含めた特別なコードの入力が含まれます。)

于 2013-03-25T11:49:23.427 に答える