最終的な結論:CとC ++の両方でaの算術void*
は違法です。
GCCは、拡張機能として、それを可能にする、参照に算術演算をvoid
-と機能-ポインタ(このセクションでは、マニュアルの「C拡張機能」の章の一部であることに注意してください)。ClangとICC void*
は、GCCとの互換性を目的とした算術演算を可能にします。他のコンパイラ(MSVCなど)は、での演算をvoid*
許可しません。-pedantic-errors
フラグが指定されている場合、またはフラグが指定されている場合、GCCはそれを許可しません-Werror-pointer-arith
(このフラグは、コードベースもMSVCでコンパイルする必要がある場合に役立ちます)。
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)
かと同じ意味を持っているx
タイプを持っているchar*
かvoid*
、それはあなたが上の算術演算を行うことができることを意味するものではありませんvoid*
。
編集者注:この回答は、最終的な結論を反映するように編集されています。