4

以下では:

struct adt { void * A; };

int new_adt(const void * const A)
{
    struct adt * r = malloc(sizeof(struct adt));
    r->A = A;
}

私は得る:

警告:割り当てにより、ポインタターゲットタイプから修飾子が破棄されます


私は私が使うことができることを知っています

memcpy(&(r->A), &A, sizeof(void *));

それを回避するために、しかし私は尋ねなければなりません:他に何かありますか?

を使用const void * constすることにより、入力に変更が加えられないと言うふりをします。また、考えてみると、const void *それで十分でしょう?(呼び出し元に影響を与えるようにポインターを変更できないため)

読んでいただきありがとうございます。

4

3 に答える 3

7

const void * constを使用することにより、入力に変更が加えられないと言うふりをします。

入力に変更が加えられないと言うふりをしていません。入力に変更が加えられないことを 保証していることをコンパイラーに明示的に伝えました。

自分がしていることをしてはいけません。

于 2011-02-10T23:43:24.977 に答える
6

Aからのポインタを介して変更したくない場合は、そのポインタもconstにadtする必要があります。

struct adt {
    const void * A;
};

これでエラーがなくなります。

を介して変更する場合、非定数ポインタを使用する必要があります。Aadtnew_adt


編集:より一般的なメモ。これは役立つ場合があります。

const一般に、キーワードはそのすぐ左のタイプに適用されます。ただし、左側にタイプがない場合は、右側のタイプに適用されます。つまり、: は(ポインタではなく、に適用されます)const int * Aと同じですが、では、constはintではなくポインタに適用されます。int const * Aconstintint * const A

ウィキペディアには、より包括的な説明があります:const-correctness。そのページの「ポインターと参照」セクションには、ポインターに適用できるconstとnon-constのさまざまな組み合わせをカバーする例が含まれています。

于 2011-02-10T23:43:03.733 に答える
2

constをキャストすることができます:

r->A = (void *) A;

ただし、問題は警告を回避する方法ではなく、何をしようとしているのかということです。「A」は書き込み可能ではないことをコンパイラに通知しているが、書き込み可能として定義されている場所に格納しようとしているため、コンパイラは警告を発します。それは一般的に意味的にはOKではありません。

「A」がバイナリデータセクション内の場所を指していると想像してください。constをキャストした後、それに書き込もうとすると、おそらくセグメンテーション違反が発生します。

したがって、実際には、コンパイラの警告を回避する前に、何をしようとしているのかをよく考えてください。それらは正当な理由で警告です。

于 2011-02-10T23:43:20.203 に答える