3

Visual Studio C++ バージョン 9 (およびおそらく他のバージョンも) では、次のコード:

int a = sizeof(void);
void const *b = static_cast<void const *>("hello world");
b += 6;

次の エラーが生成されます。

error C2070: 'void': illegal sizeof operand
error C2036: 'const void *' : unknown size

このコードは GCC で動作しsizeof(void)1 .

char *ポインター演算の目的で明示的にキャストすると混乱が生じるため、この制限を回避する方法はありますか(void *生メモリへの型なしポインターとしてよく認識され、使用されます)。

Update0

  • 注意してください、私は標準の存在をよく知っています。
  • 生のポインタ演算を行いたい
  • それが問題の原因でsizeof(void)はないという事実を十分に認識していることを示します。1
  • コード例は、エラーを生成するために何が必要かを示すためのものです。
  • これが を使用する「通常の」方法ではないことはわかっていますvoidが、これは C であり、これらのことが起こります。
  • はい、人々はこれを低レベルで行う必要があります。私は理由を求めているのではなく、方法を求めています。理由を知りたい場合は、カーネル ソースまたは使いやすい glibc を参照してください。

アップデート1

この質問は多くの混乱を引き起こしたようです。問題は、なぜ持つことが標準的でないのかということsizeof(void) == 1ではなく、標準的でない場合にどうするかということです。

1 バイトのポインター演算が行われる場合、 にキャストすることchar *が正しい答えであることがわかります。*(void *)これは、 サイズがないからではなく、標準が実際に*(char *)は常にであると保証しているため1です。したがって、 の使用は常に正しく、生のポインター演算の目的で GCC 拡張char *と一致します。void *

ポイントをさらに強化するために、型のvoid *ないメモリへのポインターの正しい選択であり、生のポインター演算のchar *キャスト先の正しい型です。

4

8 に答える 8

18

ポインタをインクリメントすると、技術的には、ポインタが指しているもののサイズに応じてポインタがインクリメントされることになっています。ボイドは何も指さないので、サイズは不明です。

一部のコンパイラでは、voidポインタをインクリメントできるので便利です。

キャストは面倒です。別のポインタにキャストしてから元に戻すか、次のような厄介なことを行う必要があるためです。(*(char *)&voidptr) += 6

個人的にはchar *、算術の目的でそれを宣言します

于 2009-12-08T03:24:51.753 に答える
10

C言語でsizeofは、不完全な型には適用できません。voidは不完全な型であるため、のオペランドとして使用することはできませんsizeof

ポインタのポインタ演算void *もCではサポートされていません。ポインタ演算で使用するには、ポインタがオブジェクトタイプを指している必要がありますが、そうでvoidはありません。

GCCは、奇妙な言語拡張として両方を許可します。

于 2009-12-08T03:27:43.670 に答える
6

void *「未知へのポインタ」を意味することを意味します

したがって、voidポインターに6を追加することは定義されていません。これは、コンパイラーに「6つの未知のオブジェクトのサイズ」だけポインターを進めるように要求しているためです。

あなたはそれをするべきではありません。

于 2009-12-08T03:32:11.413 に答える
3

ここには 2 つの異なる質問があります。1 つ目は 用void、2 つ目は 用void*です。それらは異なるタイプであり、名前以外の共通点はほとんどありません。

void主に関数の宣言/定義に使用されます (戻り値の型として、または「引数を取らない」という意味で)。type のオブジェクトを持つことはできませんvoid。これまで。そのため、存在しないオブジェクトのサイズを調べる必要があるとは考えにくいです。 GCC の動作は非標準であり、意図的な拡張です。sizeof(void) == 1ただし、 C++ 標準では、すべてのオブジェクトが少なくとも 1 バイトのスペースを必要とするため、彼らが選択したと思います。

void*「実際のデータへのポインターですが、関連する型情報はありません」を意味します。持つことは完全に可能void*です; そして、あなたはそれらにたくさん出くわします。ただし、型情報が無視されるため、ポインターをあまり操作できません。これは仕様によるものです。なぜなら、何を持っているかを知らなければ、それで何ができるか本当にわからないからです。

ただし、メモリをバイトのコレクションとして扱いたい場合は、それをchar*行います。Acharはどこでも 1 バイトです。バイト文字列はchar*. これがおかしいと思ったら、 (のようなものとしてbyte*定義する場所) を使用してください。byteunsigned char

于 2009-12-08T09:09:20.527 に答える
2

少なくとも最初の行にエラーが表示されます-sizeof(void) があり、sizeof(void*) である必要がありますか?

于 2009-12-08T03:22:10.620 に答える
1

純粋に生データを指し、データのチャンクが占めるバイト数だけそのポインターをインクリメントするために、私は常にchar *. 次に、ポインターを特定のものとして扱う必要がある場合は、ポインターを関連するデータ構造ポインターに再キャストします。a のインクリメントは、void *コンパイラ間で移植性がありません。

于 2009-12-08T04:29:10.027 に答える
1

void * はよく認識され、生メモリへの型のないポインタとして使用されます。

正しい。タイプがないということは、サイズがないということでもあります。

于 2009-12-09T08:47:02.390 に答える
-3

正解char *は、ポインタ演算に使用することであるように思われます。これsizeof(char)は、常に1として定義されており、どのプラットフォームでもアドレス可能な粒度が最も優れているためです。

つまり、制限を回避する方法はなくchar *、実際にはそれを行うための適切な方法です。

マティアス・ワンデル正しい答えを持っていましたが、正当性は異なりました。

于 2009-12-08T07:05:44.547 に答える