8. C言語はポインタを使用して、仮パラメータの逆転送の問題を実現します

8.ポインタを使用して仮パラメータの逆転送の問題を実現する

逆転送にポインター型仮パラメーターを使用するには、次の点が必要です
。1.外部実パラメーターは、内部と外部に渡されるデータを格納するためにエンティティのスペースを使用する必要があるため、外部実パラメーターはポインターではなくエンティティとして定義する必要があります。(ポインターを外部で使用する必要がある場合は、9を参照してください。2次元ポインターを使用して、仮パラメーターの逆の値の転送を実現します)
2.内部仮パラメーターが外部スペースのアドレスを取得するため、仮パラメーターの内部アドレスが内部で失われることはありません。 、パラメーターは常に外部空間のアドレスを格納する必要があります。
3.値が反転すると、転送されたデータは外部実パラメータのスペースに配置されます。外部実パラメータのスペースを取得するには、仮パラメータをアドレス指定してから値を渡す必要があります。
たとえば、次のとおりです。

/*
fun执行时,e自身有个地址————&e。
因为e是指针所以e存储的是一个另外空间的地址,由于函数调用时外部使用了a作为实参,所以e存储的是外部a的地址,*e则是外部a的存储空间
*/
void fun(int* e)
{
    int num = 7;
    

    /*
    如果下面反向传值的赋值语句写为:
        e = #
    则是将num的地址赋值给e,而e原本存储的外部a的地址就被覆盖了,所以达不到反向传值的效果。
    所以
    正确反向传值赋值语句写法为:
        *e = num;
    这样,e存储的一直是a的地址,*e是a的空间,这句赋值语句就将num中的7拷贝到了外部a的空间中
    */
    *e = num;
}

int main()
{
    //外部定义为实体,不能定义为指针int* a;定义为实体则a的空间可以用于接收外传的数据
    int a = 3;
    /*
    调用过程中,形参获取到实参传递的值
    因为fun函数形参e是指针类型,于是这里实参a向形参e传递的是a的地址————&a,而非a的值————3
    */
    fun(a);
    
    return 0;
}

9. 2次元ポインターを使用して、仮パラメーターの逆伝送を実現します。

まず、8を確認しましょう。仮パラメーターの逆の値を実現するためのポインターの使用。
具体的なアイデアは次のとおりです
。1.外部がエンティティとして定義され、エンティティアドレスが渡されます。
2.内部で定義された仮パラメーターは1次元のポインターであるため、仮パラメーターは外部エンティティーを指します。
3.外部エンティティスペースを取得するために仮パラメーターに対処し、外部エンティティスペースに返される値を割り当てて、外部値の転送を実現します。

ここでは、すべての部分が「より1次元のポインタ」であり、2次元のポインタを使用して値の演算を逆にします。
具体的なアイデアは次のとおりです
。1. 1次元のポインターを外部で定義し、ポインターのアドレスを渡します。
2.内部仮パラメーターは、外部1次元ポインターを指す2次元ポインターとして定義されます。
3.外部ポインターを取得するために仮パラメーターをアドレス指定し、次に外部ポインターが指すスペースを取得するためにさらにアドレス指定します。代入文により、外部ポインタの指す空間への値転送演算を実現します。

たとえば、次のとおりです。

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
/*************************************定义部分*************************************/
typedef struct Node {
    int number;
}Elem;

void fun(Elem** e)
{
    //进入函数,形参通过拷贝手段获取到实参的值,于是e存储a的地址&a,实现二维指针e指向一维指针a,一维指针a目前指向空
    //于是对e寻址就获取了a空间,所以对*e进行赋值,就相当于对a赋值

    //maloc函数申请空间,并将空间地址返回出来,假设malloc返回的地址是0x00000001
    //因为对*e进行赋值,就相当于对a赋值,于是将0x00000001赋值给了a
    *e = (Elem*)malloc(sizeof(Elem));

    //完成赋值语句后,二维指针e指向一维指针a,一维指针a指向空间0x00000001

    //对二维指针e寻址(即:*e)获取一维指针a,对一维指针a寻址(即:(*(*e)))获取空间0x00000001,
    //于是赋值语句实现将7放入0x00000001内
    (*(*e)).number = 7;
}
/*************************************使用部分*************************************/
int main()
{
    SetConsoleOutputCP(65001);
    
    //定义一个指针a,作为实参传入fun函数,用于接收fun函数形参(e)反向传出的实际空间的地址0x00000001
    Elem* a = NULL;//定义指针变量,并进行初始化

    //至此我们获取了一个指针a,她没有指向(或者说指针a指向空)
    
    //将a的地址传入
    fun(&a);
    //函数执行完成后,栈内存释放,函数fun内的形参e被释放。但是a已经存储到malloc空间的地址0x00000001,
    //于是a指向0x00000001,通过指向符号“->”就可以获取被指向空间0x00000001内所存的值7
    printf("%d\n",a->number);//显然输出的是:7
    //当然,不通过指向符号“->”的话,也可以通过对a寻址(即:*a)获取空间0x00000001,进而通过“点操作”获取该空间内部存储的值7
    printf("%d\n",(*a).number);//显然输出的依然是:7
    

    free(a);

    system("pause");
    return 0;
}

この時点で、LinkListのコードを最適化し、GetElem関数パラメーターに2次元ポインターを使用させることができるため、外部呼び出しが特定のスペースパフォーマンスを節約できる場合、実際のパラメーターをエンティティーの代わりにポインターとして定義できます。同時に、内側のループ本体カーソルのポインターはパフォーマンスを節約します。

質問8と質問9のコードを観察すると、共通のポイントは、関数が呼び出されたときに、渡されるパラメーターは外部変数によって格納された値ではなく、外部変数のアドレスであり、内部パラメーターが定義されていることです外部変数は高次元のポインタです。この共通のポイントは、バック値の転送に仮パラメーターを使用するという中心的な考え方を反映しています。関数内の仮パラメーターを外部空間に向けてください!仮パラメーターをアドレス指定して、値を外部スペースに渡します。

この中心的な考え方に基づいて、3次元(またはより高次元)のポインターを使用して、仮パラメーターの逆の値渡し操作を実現できます。

この考え方は、他の高水準言語での「参照」の転送に似ています(値は値ではなく参照です)。

元の23件の記事を公開 いいね1 20,000以上の訪問

おすすめ

転載: blog.csdn.net/shenjie_xsj/article/details/102823812