ホームページ >php教程 >PHP开发 >voidとvoidポインタの意味を深く理解する

voidとvoidポインタの意味を深く理解する

高洛峰
高洛峰オリジナル
2016-12-13 13:15:531526ブラウズ

voidの意味
voidは「型なし」、void *は「型なしポインタ」で、任意のデータ型を指すことができます。

Voidポインタの使用仕様
①voidポインタは任意の型のデータを指すことができます。つまり、任意のデータ型のポインタを使用してvoidポインタに値を代入できます。例:
int *pint;
void *pvoid; /* ただし、pint = pvoid; */
pvoid を次のようにキャストする必要があります。 = (int * )pvoid;

②ANSI C 標準では、pvoid++ や pvoid+=1 などの算術演算は void ポインターでは許可されませんが、GNU では許可されています。これは、GNU がデフォルトで void * と char * を考慮するためです。同じ。 sizeof( *pvoid )== sizeof( char ).

voidの役割

① 関数の戻り値の制限。
②関数パラメータの制限。
関数が値を返す必要がない場合は、void 修飾を使用する必要があります。例: void func(int, int);
関数がパラメーターを受け入れることができない場合は、void 修飾を使用する必要があります。例: int func(void)。

void ポインターは任意のタイプのデータを指すことができるため、つまり、任意のデータ型のポインターを使用して void ポインターに値を割り当てることができるため、void ポインターは関数のパラメーターとしても使用できます。関数は任意のデータ型のポインターをパラメーターとして受け入れることができます。例:
void * memcpy( void *dest, const void *src, size_t len );
void * memset( void *buffer, int c, size_t num ); 多くの初心者は void と void に精通しています。ポインター型はよく理解されていないため、使用時にいくつかのエラーが発生しました。この記事では、void キーワードの深い意味を説明します。void および void ポインター型の使用方法とテクニックについて詳しく説明します。

1. ルール: void ポインター型は注意して使用してください

ANSI (American National Standards Institute) 規格によれば、void ポインターに対して算術演算を実行することはできません。つまり、次の演算は不正です:

void*pvoid;

pvoid++;//ANSI: Error
pvoid+ =1;//ANSI: Error
//ANSI 標準がこれを識別する理由は、アルゴリズム演算に使用されるポインタが、それが指すデータ型のサイズを知っている必要があると主張しているためです。 。
//例:
int*pint;
pint++;//ANSI: 正解
pint++の結果はsizeof(int)を増加させます。
しかし、有名な GNU (GNU'sNotUnix の略) はそう考えていません。 void* のアルゴリズム演算は char* のアルゴリズム演算と一致すると規定しています。
したがって、次のステートメントは GNU コンパイラでは正しいです:
pvoid++; //GNU: 正しい
pvoid+=1; //GNU: 正しい
pvoid++ の実行結果は 1 増加します。
実際のプログラミングでは、ANSI 規格に準拠し、プログラムの移植性を向上させるために、次のように同じ機能を実現するコードを書くことができます。
(char*)pvoid++; //ANSI: 正しい; GNU : 正しい
(char*)pvoid+=1;//ANSI: 間違っています; GNU: 正しい
一般的に、GNU は ANSI よりも「オープン」であり、より多くの構文をサポートしています。しかし、実際に設計するときは、可能な限り ANSI 規格に準拠する必要があります。

2. ルール 2: 関数のパラメータが任意の型のポインタである場合、そのパラメータは void* として宣言する必要があります。 メモリ操作関数 memcpy や memset などの典型的な関数プロトタイプは次のとおりです。
void*memcpy(void) *dest,constvoid *src,size_tlen);
void*memset(void*buffer,intc,size_tnum);

このようにして、任意のタイプのポインタを memcpy と memset に渡すことができ、これもメモリの意味を正確に反映します。演算関数は、メモリの種類に関係なく、演算の対象となるのはメモリの一部にすぎません。 memcpy と memset のパラメータの型が void* ではなく char* だったら本当に奇妙です。このような memcpy と memset は明らかに「純粋で、低レベルの楽しみが含まれていない」関数ではありません。

次のコードは正しく実行されます:
//例: memset は任意のタイプのポインターを受け入れます
int intarray[100];
memset(intarray,0,100*sizeof(int));//intarray を 0 にクリアします
//例: memcpy は任意のタイプのポインターを受け入れます
int intarray1[100], intarray2[100];
memcpy(intarray1,intarray2,100*sizeof(int));//intarray2 を intarray1 にコピーします
興味深いのは、memcpy 関数と memset 関数もreturn void * type、標準ライブラリ関数の作成者はなんと知識が豊富なのでしょうか。

3. ルール 3: void は実数変数を表すことはできません
次のコードはすべて void に実数変数を表そうとしているため、すべて間違ったコードです:
voida;//Error
function(voida);//Error

void これは抽象化を具体化したものです。たとえば、人は男性か女性 (そしてニューハーフ?) のいずれかです。

voidの出現は抽象的なニーズのためだけです オブジェクト指向における「抽象基底クラス」の概念を正しく理解していれば、voidデータ型を理解するのは簡単です。抽象基本クラスのインスタンスを定義できないのと同様に、void (類推により void を「抽象データ型」と呼びます) 変数も定義できません。



声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。