GCCは私に次の警告を出します:
note: expected 'const void **' but argument is of type 'const struct auth **
問題が発生する可能性のあるケースはありますか?
より大きなスニペットは
struct auth *current;
gl_list_iterator_next(&it, ¤t, NULL);
関数はポインタに格納current
するだけです。void *
エラーメッセージは十分に明確です:あなたはaが受け入れられたstruct auth **
場所を通過しています。は他のポインタタイプと同じサイズと配置を持たない可能性があるためvoid **
、これらのタイプ間に暗黙の変換はありません。void*
解決策は、中間体を使用することvoid*
です。
void *current_void;
struct auth *current;
gl_list_iterator_next(&it, ¤t_void, NULL);
current = current_void;
編集:以下のコメントに対処するために、これが必要な理由の例を次に示します。sizeof(struct auth*) == sizeof(short) == 2
、while sizeof(void*) == sizeof(long) == 4
;のプラットフォームを使用しているとします。これはC標準で許可されており、さまざまなポインタサイズのプラットフォームが実際に存在します。その場合、OPのコードは次のようになります
short current;
long *p = (long *)(¤t); // cast added, similar to casting to void**
// now call a function that does writes to *p, as in
*p = 0xDEADBEEF; // undefined behavior!
ただし、このプログラムも中間体を導入することで機能させることができます(ただし、結果は、の値がに格納できるほど小さいlong
場合にのみ意味があります)。long
short
const void *
うーん...のような構成はあまり意味がないと思います。
ユーザーがデータにアクセスしたい場合はvoid *
、voidからキャストする必要があり、このアクションはコンパイラーの型チェックをバイパスし、その結果、定数をバイパスするためです。
この例を考えてみましょう。
#include <stdio.h>
#include <stdlib.h>
int main () {
int i = 6;
int * pi = &i;
const void * pcv = pi;
const int * pci = pi;
// casting avoids type checker, so constantness is irrelevant here
*(int *)pcv = 7;
// here we don't need casting, and thus compiler is able to guard read-only data
*pci = 7;
return 0;
}
したがって、結論として、データの一定性を確保するには、voidポインタまたはデータのいずれかが必要ですが、両方は必要ありません。