Xiaofanはvoid *を理解しています

@ TOC

紹介する

Linuxオペレーティングシステムを学んだ友達はすべて、スレッドの作成に関連する知識を知っています。最近、この知識を学んだときに、Xiaofanはポインターに関する問題に遭遇しました。一緒にプロセスを見ていきましょう。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
//Thread1执行函数
void *thread_1(void *arg)
{
	int rec = 0;

	sleep(1);
	rec = (int)(arg);
	printf("new thread1 arg = %d\n", rec);
	return NULL;
}
//Thread2执行函数
void *thread_2(void *arg)
{
	int rec = 0;

	sleep(1);
	rec = *((int *)(arg));
	printf("new thread2 arg = %d\n", rec);
	return NULL;
}

int main(int argc, char *argv[])
{
	pthread_t tid1, tid2;//定义tid1,tid2
	int test = 100;//定义一个整形变量,赋值为100

	/*创建两个线程*/
	pthread_create(&tid1, NULL, thread_1, (void *)test);
	pthread_create(&tid1, NULL, thread_2, (void *)(&test));
	while(1);
	return 0;
}

コース作成のアイデア

最初のステップ

メイン関数フレームワークをセットアップし、while(1)を追加して実行するメインプロセスを制御します。メインプロセス(つまりメイン関数)でpthread_create()関数を呼び出して2つのスレッドを作成した後、最初のパラメーターをスレッド識別子アドレスに渡す必要があります。 、これは2番目のステップにつながります。

int main(int argc, char *argv[])
{
	/*创建两个线程*/
	pthread_create();
	pthread_create();
	while(1);
	return 0;
}

第二段階

2つのpthread_t変数tid1とtid2を宣言します。Xiaofanはここで問題を抱えています。ここでのtid1は、プロセスが作成されたときのpidとは異なります。これは、fork()関数の戻り値を受け取って割り当て、使用する必要があります。代わりに、引数として直接使用され、宣言後にpthread_create()関数に渡されます。教師によると学習したこと:C言語では、変数を宣言した後、変数に初期値が割り当てられていない場合、システムはそれに乱数、つまり乱数が一意であるアドレスを割り当てるため、スレッド作成関数がこれを渡し、これを配置します一意性を実現するために、一意のアドレス値がスレッド識別子アドレスとして使用されます。このような使い方をすることで、5体のXiaofanを小さな白として鑑賞することができます。

pthread_t tid1, tid2;//定义tid1,tid2
pthread_create(&tid1);
pthread_create(&tid1);

第三段階

パラメーター2は属性設定です。当面は検討しません。NULLに設定します。パラメーター3は、スレッド実行関数のエントリアドレスに渡されます。このとき、各スレッドの実行関数を定義します。つまり、thread1とthread2です。定義された形式voidに注意してください。 *タイプ。入力パラメーターもvoid *タイプです。

	pthread_create(&tid1, NULL, thread_1);
	pthread_create(&tid1, NULL, thread_2);
void *thread1(void *arg)
{
	
	return NULL;
}
void *thread2(void *arg)
{
	
	return NULL;
}

第四段階

ポイントが来ています!新しいスレッド実行関数のパラメーターに渡されるパラメーター4、および(void *)タイプ。
1.整変数を定義する

int test = 100;//定义一个整形变量,赋值为100

2.変数を強制した後、パラメーター4の位置に配置します。

pthread_create(&tid1, NULL, thread_1, (void *)test);
pthread_create(&tid1, NULL, thread_2, (void *)(&test));

void *は、任意のデータ型を指すことができる型指定されていないポインタです。
最初にテストを分析し
ます。testは、値が100の整数変数です;
(void *)テストは、整数変数をtestに格納されているポインタ変数に強制します値100は整数データ100ではなく、アドレス100です。メモリアドレスは16進数を使用しているため、画面への出力は100桁の16進数(0X64)であり、スクリーンショットは次のようになります。
ここに画像の説明を挿入
スレッド1の実行関数にtestが渡されたら、それを印刷したいのですが、ここでは整数データ100を印刷しています。このとき、強制型変換が行われます。コード補完は次のようになります。

//Thread1执行函数
void *thread_1(void *arg)
{
	int rec = 0;

	sleep(1);
	rec = (int)(arg);
	printf("new thread1 arg = %d\n", rec);
	return NULL;
}

int型の変数recを定義し、割り当てられた値を0として表示します。1秒の遅延後、強制型変換後に出力されます。
この時点で、テストはargに割り当てられています。Argはポインター変数を表します。これを整数変数に戻す場合は、(int)を使用して強制的に変換します。変換後、argは整数変数になり、その格納内容も次のように変更されます。アドレスはプラスチックデータに変換されます。この時点で、アドレスを割り当てて印刷することができます。効果図は次のとおりです:
ここに画像の説明を挿入
次の分析とテスト:
&テスト。最初の理解は、テストのアドレス、つまり、プラスチックデータが保存されているアドレス100を取得することです;
詳細な理解これは、整数データの100アドレスを指すint型のポインターと同等です;
(void *)(&test)は、int型のポインターから型なしのポインターに強制的に&テストします。void *型のポインターは任意のデータ型を指すことができるため、用途が広く、渡されるパラメーターの型が不明確なことがよくあります。そのため、それはvoid *型に変換され、渡されてから使用されます。
このとき、また、それを印刷するために、ここでの印刷は、整形されたデータ100も印刷することです。

//Thread2执行函数
void *thread_2(void *arg)
{
	int rec = 0;

	sleep(1);
	rec = *((int *)(arg));
	printf("new thread2 arg = %d\n", rec);
	return NULL;
}

変換されたコードを直接見る

rec = *((int *)(arg));

argは、テストで渡されます。つまり、ポインタまたは型なしポインタです。
以前はint 型のポインタでした。そのため、その値を取得してint型の変数に支払うには、最初にargをunsignedから配置する必要があります。型ポインタをint型のポインタに変換し、整数データ100を格納しているメモリユニットに「* p」でアクセスして取り出します。アイデアの分析は次のとおりです
。1.(int *)(arg)
2. *((int *)(
Arg ))3. rec = *((int *)(arg))
このとき、recの値を出力すると、シェーピングデータ100になります。効果は次のとおりです。
ここに画像の説明を挿入

まとめ

変数を強制的にポインタに変換すると、変数に格納された内容がポインタ型のデータ、つまりアドレスになります。
「&変数」自体はアドレスであり、強制転送後もアドレスのままです。アドレスの下に格納されているデータには影響しません。例として、int型のポインターを考えてみます
。int* a = 100;
aは、整数データ100が格納されているアドレスです。これは0X1234です。
* aは、0X1234に格納されているデータを取り出し、int型のデータストレージの方法に従ってその値を解析するようコンパイラーに指示します。
&testもプロセス内のアドレスであり、そこに格納されているデータ100も整形され、次に=&&test 、&​​testはint型のポインタであり、int型のデータを指し、その値を取得する方法であると理解できる* a = (&test)= 100;
&testは以前にvoid *型のポインタに変換されたため、値の前元の型に強制する必要があります、これはint *型なので、
((int *)(&test));
void *型なしポインターは任意の型のデータを指すことができるため、int型のポインターはプロセスで強制的にvoidにされますタイプポインタも可能で、アドレスに格納されているデータのタイプは変更されず、必要に応じて変換され、汎用性が高くなります。

終わり

Xiaofanもポインターの点で少し白いので、初心者の視点からしか理解できず、ここでのメモの収集に使用されるため、内容は参照のみです。

元の記事を3件公開 Likes0 Visits 22

おすすめ

転載: blog.csdn.net/qq_43711326/article/details/105399233