タンハオチャンC言語第3版
関数パラメーターとしての構造ポインター変数
ANSI C規格では、構造変数は全体的な送信の関数パラメーターとして許可されています。しかし、この種の送信では、すべてのメンバーを1つずつ送信する必要があります。特に、メンバーがアレイの場合、送信に多くの時間とスペースがかかり、プログラムの効率が大幅に低下します。したがって、最良の方法は、ポインターを使用することです。つまり、送信用の関数パラメーターとしてポインター変数を使用します。このとき、実際のパラメータから正式なパラメータにアドレスのみが渡されるため、時間とスペースのオーバーヘッドが削減されます。
アレイとは異なります
関数パラメーターとしての配列
配列は、データ送信の関数パラメーターとして使用できます。アレイは、関数のパラメータとして使用されている二つの形式。一方、実際のパラメータとして使用する配列要素(添字変数)であり、他方は、関数パラメータと実際のパラメータとして配列名を使用することです。
関数パラメーターとしての配列名
関数パラメーターとして配列名を使用することと、実際のパラメーターとして配列要素を使用することには、いくつかの違いがあります。
配列要素を実際のパラメーターとして使用する場合、配列タイプが関数の仮パラメーター変数のタイプと一致している限り、添え字変数として使用される配列要素のタイプも関数の仮パラメーター変数のタイプと一致します。したがって、関数の正式なパラメータも添え字変数である必要はありません。つまり、配列要素の処理は通常の変数として扱われます。配列名を関数パラメーターとして使用する場合、正式なパラメーターと対応する実際のパラメーターは同じタイプの配列である必要があり、明確な配列の説明が必要です。正式なパラメータと実際のパラメータに一貫性がない場合、エラーが発生します。
通常の変数または添え字変数が関数パラメーターとして使用される場合、正式なパラメーター変数と実際のパラメーター変数は、コンパイラシステムによって割り当てられる2つの異なるメモリユニットです。関数が呼び出されたときに発生する値の転送は、実際のパラメーター変数の値を正式なパラメーター変数に割り当てることです。配列名が関数パラメーターとして使用される場合、それは値の転送ではありません。つまり、実パラメーターグループの各要素の値は、形状パラメーターグループの各要素に割り当てられません。ので、それは実際のパラメータ配列を存在しない場合、コンパイラシステムは、メモリサイズパラメータを割り当てるように設定されていません。では、データ送信はどのように実現されますか?紹介したように、アレイ名はアレイの最初のアドレスです。したがって、配列名を関数パラメータとして使用する場合、送信はアドレス送信のみになります。つまり、実際のパラメータグループの最初のアドレスが形状パラメータグループ名に割り当てられます。形状パラメータグループ名が最初のアドレスを取得した後は、実際の配列を持つことと同じです。実際、形状パラメータグループと実パラメータグループは同じ配列であり、メモリ空間を共有します。
上の図は、この状況を示しています。この図では、aを実際のパラメーターグループとし、タイプは整数です。2000から始まるメモリ領域を占有します。bは形状パラメータグループの名前です。関数呼び出しが発生すると、アドレス送信が実行され、実パラメータグループaの最初のアドレスがシェイプパラメータグループ名bに送信されるため、bもアドレス2000を取得します。したがって、2つのアレイaとbは、最初のアドレスが2000の連続メモリユニットを共同で占有します。この図から、aとbの同じ添え字を持つ要素が、実際には同じ2つのメモリユニットを占有していることもわかります(整数配列の各要素は2バイトを占有します)。たとえば、a [0]とb [0]はどちらも2000ユニットと2001ユニットを占有しますが、もちろんa [0]はb [0]と同じです。類推により、a [i]はb [i]に等しい。
1.構造を使用して操作を実行する場合、たとえば、関数パラメーターとして、構造全体をコピーする必要があります(構造に含まれるバイト数、コピーする必要のあるバイト数)。
ポインタを使用するとはるかに便利で、コピーする必要があるのは4バイト(ポインタの長さ)だけです。パフォーマンスを節約
https://zhidao.baidu.com/question/2118370445891739467.html
2.(1)構造baiポインターが関数パラメーターとして使用される場合、呼び出し中に渡されるduは、構造変数(つまり、構造変数のアドレス)へのポインターです。構造変数が関数パラメーターとして使用される場合、呼び出し中に渡される構造変数自体。
(2)次のコードは呼び出し時の違いを示しています
#include <stdio.h>
/ *構造タイプポイントを定義します* /
typedef struct {
int x;
int y;
}ポイント;
void fun1(ポイントポイント){
point.x + = 10;
point.y + = 10;
}
void fun2(Point pPoint){
pPoint-> x + = 10;
pPoint-> y + = 10;
}
void main()
{{
ポイントp;
px = 100;
py = 200;
/ * fun1を呼び出す* /
fun1(p);
printf( "x =%d、y =%d \"、px、py);
/ * fun2を呼び出します:pのアドレスをパラメーターとして取ります* /
fun2(&p);
printf( "x =%d、y =%d \"、px、py);
}
プログラムの出力は次のとおりです。
x = 100、y = 200
x = 110、y = 210
(3)上記のプログラムを実行した結果を見ると、fun1関数を実行した後、pは変化していませんが、fun2を呼び出した後、pは変化しています。これは、fun1が呼び出されると、渡されたパラメーターpが呼び出しスタックにコピーされ、fun1の操作が元の変数(メインのp)ではなくスタック内の変数であるためです。一方、fun2が呼び出されると、 pの着信アドレスfun2は、アドレスを介してmainの変数pを変更します。これは、構造ポインタと関数パラメータとして使用される構造変数の最大の違いです。
構造Aは、そのポインタがパラメータとして関数funcに渡されると、構造の値をfuncでポインタを介して変更できます。関数が戻った後、構造の値が変更されますが、構造変数がパラメータとして渡されると、関数がfuncの場合、func関数で変更されたとしても、関数が戻ったとき、変更は彼のコピーにすぎないため、構造自体は変更されません。