203

特定の型 (たとえばintcharfloat、 ..) へのポインターがインクリメントされると、その値はそのデータ型のサイズだけ増加します。voidサイズのデータ​​を指すポインターがインクリメントされる場合x、どのようにしてxバイト先を指すようになりますか? xコンパイラーは、ポインターの値に追加することをどのように認識しますか?

4

9 に答える 9

326

最終的な結論: a の演算はvoid*、C と C++ の両方で違法です。

GCC では、拡張機能としてこれを使用できます。 - および関数ポインターの算術演算をvoid参照してください(このセクションは、マニュアルの「C 拡張機能」の章の一部であることに注意してください)。Clang と ICCvoid*では、GCC との互換性のために算術演算が許可されている可能性があります。他のコンパイラ (MSVC など) は での算術演算を許可しません。GCCは、フラグが指定されている場合、またはフラグが指定されvoid*ている場合は許可しません(このフラグは、コード ベースも MSVC でコンパイルする必要がある場合に役立ちます)。-pedantic-errors-Werror-pointer-arith

C標準は語る

引用は n1256 ドラフトから取得されます。

加算操作の標準の説明には、次のように記載されています。

6.5.6-2: 加算の場合、両方のオペランドが算術型であるか、一方のオペランドがオブジェクト型へのポインタで、もう一方が整数型である必要があります。

したがって、ここでの問題void*は、 が「オブジェクト型」へのポインタであるかどうか、または同等に「オブジェクト型」であるかどうかvoidです。「オブジェクト タイプ」の定義は次のとおりです。

6.2.5.1: 型は、オブジェクト型(オブジェクトを完全に記述する型)、関数型(関数を記述する型)、および不完全型(オブジェクトを記述するが、サイズを決定するために必要な情報が不足している型) に分割されます。

また、標準では次のように定義voidされています。

6.2.5-19:void型は値の空のセットで構成されています。完成できない不完全型です。

は不完全型なのでvoid、オブジェクト型ではありません。したがって、これは加算演算の有効なオペランドではありません。

したがって、ポインターに対してポインター演算を実行することはできませんvoid

ノート

当初void*は、C 標準の次のセクションにより、算術演算が許可されていると考えられていました。

6.2.5-27: voidへのポインターは、文字型へのポインターと同じ表現およびアラインメント 要件を持たなければなりません。

でも、

同じ表現とアラインメントの 要件は、関数への引数、関数からの戻り値、および共用体のメンバーとしての互換性を暗示するものです。

したがって、これはが型またはをprintf("%s", x)持っていても同じ意味を持つことを意味しますが、 で算術演算を実行できるという意味ではありません。xchar*void*void*

于 2010-08-19T17:05:39.960 に答える
66

ポインタ演算はポインタでは許可されていませんvoid*

于 2010-08-19T15:06:47.150 に答える
27

それを char ポインターにキャストし、ポインターを x バイト先にインクリメントします。

于 2010-08-19T15:08:25.233 に答える
14

void *まさにこの理由で、型に対してポインター演算を行うことはできません!

于 2010-08-19T15:08:20.037 に答える
8

void ポインタは、任意のメモリ チャンクを指すことができます。したがって、コンパイラは、void ポインターでポインター演算を試行するときに、インクリメント/デクリメントするバイト数を知りません。したがって、void ポインターは、ポインター演算に関与する前に、まず既知の型に型キャストする必要があります。

void *p = malloc(sizeof(char)*10);
p++; //compiler does how many where to pint the pointer after this increment operation

char * c = (char *)p;
c++;  // compiler will increment the c by 1, since size of char is 1 byte.
于 2013-01-22T05:42:17.903 に答える
8

ポインター演算を行う前に、別の型のポインターにキャストする必要があります。

于 2010-08-19T15:08:36.497 に答える
-3

コンパイラは型キャストで認識します。与えられたvoid *x:

  • x+1に 1 バイトを加算しx、ポインタはバイトに移動しますx+1
  • (int*)x+1バイトを追加しsizeof(int)、ポインターはバイトに移動しますx + sizeof(int)
  • (float*)x+1アドレスsizeof(float)バイトなど

最初の項目は移植性がなく、C/C++ の Galateo に反していますが、それでも C 言語に正確です。つまり、ほとんどのコンパイラで何かにコンパイルされ、適切なフラグ (-Wpointer-arith など) が必要になる可能性があります。

于 2015-03-13T09:40:19.560 に答える