Ausführliche Erläuterung der Hinweise (von den Grundlagen bis zum Einstieg)

1. Was ist ein Zeiger?

In der Informatik ist ein Zeiger ein Objekt in einer Programmiersprache, das mithilfe einer Adresse direkt auf einen Wert zeigt, der an einer anderen Stelle im Speicher des Computers gespeichert ist. Da über die Adresse die benötigte Variableneinheit gefunden werden kann, kann man sagen, dass der Zeiger auf diese Variableneinheit zeigt. Daher wird die Adresse visuell als Zeiger bezeichnet. Das bedeutet, dass es die Speichereinheit anhand ihrer Adresse finden kann. Unter einem anderen Aspekt ist der -Zeiger eine Variable, die zum Speichern der Adresse (Kodierung) der Speichereinheit verwendet wird. Die Adresse identifiziert einen Speicherplatz eindeutig.

Dies kann durch den folgenden C-Code veranschaulicht werden:

#include<stdio.h>
int main()
{
    
    
    int a=10;//在内存中开辟一块空间
    int *p=&a;//取出a的地址,将a的地址存放在p变量中,p就是一个指针变量
    return 0}

ps: Die in Zeigern gespeicherten Werte werden als Adressen behandelt. Auf einer 32-Bit-Plattform belegt eine Zeigervariable 4 Bytes und auf einer 64-Bit-Plattform belegt eine Zeigervariable 8 Bytes.

2. Die Bedeutung von Zeigertypen

Warum gibt es verschiedene Zeigertypen, da die Größe von Zeigervariablen fest ist?

1. Der Zeigertyp bestimmt die Größe des Speicherplatzes, auf den zugegriffen werden kann, wenn der Zeiger für Referenzoperationen entfernt wird.
Das Folgende ist ein Beispiel:

Wenn der Zeigertyp ein Zeichentyp ist, gibt es den folgenden C-Code
Fügen Sie hier eine Bildbeschreibung ein
Wenn Sie die Adressänderung von a beobachten, können Sie erkennen, dass der Zeiger vom Typ char dereferenziert wird und Wenn der entsprechende Wert geändert wird, können zwei Bytes Inhalt geändert werden (es kann nur auf zwei Bytes Speicherplatz zugegriffen werden).

Wenn der Zeigertyp eine Ganzzahl ist, gibt es den folgenden C-Code
Fügen Sie hier eine Bildbeschreibung ein
Durch Beobachten der Änderung der Adresse von a im Speicher können Sie erkennen, dass der Zeiger vom Typ ist int wird dereferenziert und seine entsprechenden Werte können vier Bytes Inhalt geändert werden (es kann auf vier Bytes Speicherplatz zugegriffen werden).

Zusammenfassung: Der Typ eines Zeigers bestimmt, wie viel Autorität Sie bei der Dereferenzierung des Zeigers haben. Beispielsweise kann die Zeiger-Dereferenzierung von char * nur auf ein Byte zugreifen, während die Zeiger-Dereferenzierung von int * auf vier Bytes zugreifen kann und die Zeiger-Dereferenzierung von double * auf acht Bytes zugreifen kann.

2. Der Zeigertyp bestimmt die Schrittgröße der Zeigeraddition und -subtraktion von ganzen Zahlen.

Beobachten Sie den folgenden C-Code und seine Ausführungsergebnisse:
Fügen Sie hier eine Bildbeschreibung ein
Es ist nicht schwer herauszufinden, dass die Adresse nach der Ganzzahlzeigervariablen (pa) + 1 von C4 nach C8 springt. Springen um 4 Bytes (eine Ganzzahl) rückwärts; nachdem die Zeichenzeigervariable (pc) +1 ist, springt die Adresse von C4 nach C5 und springt 1 Byte (ein Zeichen) zurück; in ähnlicher Weise wird nach der Doppelzeigervariablen +1 die Die Adresse sollte 8 Bytes rückwärts springen.

Zusammenfassung: Der Zeigertyp bestimmt, wie weit (Entfernung) sich der Zeiger einen Schritt vorwärts oder rückwärts bewegt.

Anhand der folgenden Beispiele können wir unser Verständnis vertiefen

Beispiel: Bei gegebenem Array int arr[10]={0} verwenden Sie Zeiger, um alle Array-Elemente auf 1 zu setzen

#include<stdio.h>
int main()
    {
    
    
    int arr[10]={
    
    0};
    int* p=arr;//数组名表示首元素地址
    int i=0;
    for(i=0;i<10;i++)//将各数组元素全部置为1
    {
    
    
        *(p+i)=1;//p为int类型的指针,每加一向后跳跃一个整形(4个字节)
    }
    for(i=0;i<10;i++)//打印输出
    {
    
    
        printf("%d ",arr[i]);
    }
    return 0;
    }

Wenn p ein Zeiger vom Typ char ist, kann er auch durch den folgenden Code implementiert werden

#include<stdio.h>
int main()
    {
    
    
    int arr[10]={
    
    0};
    char* p=arr;//数组名表示首元素地址
    int i=0;
    for(i=0;i<10;i++)//将各数组元素全部置为1
    {
    
    
        *(p+4*i)=1;//p为char类型的指针,每加一向后跳跃一个字符(1个字节),题设数组元素为整形(4个字节),应该加上4*i
    }
    for(i=0;i<10;i++)//打印输出
    {
    
    
        printf("%d ",arr[i]);
    }
    return 0;
    }

3. Wilder Zeiger

**

(1) Konzept

**

Ein Wild-Zeiger bedeutet, dass die Position, auf die der Zeiger zeigt, unbekannt ist (zufällig, falsch und ohne klare Grenze).

**

(2) Ursachen für wilde Zeiger

**

1. Der Zeiger wird initialisiert

Wie zum Beispiel der folgende C-Code

#include<stdio.h>
int main()
{
    
    
    int* p;//局部指针变量未初始化,默认为随机值
    *p=10;
    return 0;
}

2. Zeigerzugriff außerhalb der Grenzen

Wie zum Beispiel der folgende C-Code

#include<stdio.h>
int main()
{
    
    
   int arr[10]={
    
     0 };
   int* p=arr;//数组名代表首元素地址
   int i=0;
   for(i=0;i<12;i++)
   {
    
    
       *(p++)=i;
       //数组元素个数为10,当i>9时,指针指向的范围超过了数组arr的范围,此时p就是野指针
   }
   return 0;
}

3. Der Zeiger zeigt auf den freigegebenen Platz

Wie zum Beispiel der folgende C-Code

#include<stdio.h>
int* test()
{
    
    
    int a = 10;
    //a为局部变量,函数开始时创建,函数结束时销毁
    return &a;
}
int main()
{
    
    
    int* p = test();
    *p = 20;
    //此时p指向的空间已销毁(被释放),不属于当前程序,此时指针p就为野指针
    return 0;
}

(3) So vermeiden Sie das Auftreten wilder Zeiger

1. Zeigerinitialisierung
2. Achten Sie darauf, ob der Zeiger außerhalb der Grenzen liegt
3. Wenn der Zeiger auf den freigegebenen Bereich zeigt, er wird auf NULL (Nullzeiger) gesetzt
4. Die Gültigkeit von Zeigern sollte vor der Verwendung überprüft werden

4. Zeiger und Arrays

(1) Zeiger und Arrays

Der Array-Name stellt die Adresse des ersten Elements dar

Fügen Sie hier eine Bildbeschreibung ein
Hinweis: Die folgenden beiden Situationen sind Ausnahmen
1. &Array-Name (z. B. &arr)
Der Array-Name ist nicht der Adresse des ersten Elements. Der Name (arr) stellt das gesamte Array dar, &Array-Name (&arr) stellt die Adresse dar, an der das gesamte Array entnommen wird
Fügen Sie hier eine Bildbeschreibung ein
arr –>arr+1 , springt 4 Bytes zurück a>
&arr–>&arr+1, springt 40 Bytes zurück (Hexadezimal A20 minus 9F8 ist 28, in Dezimal umgewandelt ist 40 )

2. sizeof (Array-Name), z. B. sizeof(arr)
Der Array-Name (arr) repräsentiert das gesamte Array und sizeof (arr) berechnet die Größe des gesamten Arrays Array

(2) Zeiger-Array

Zeiger-Arrays sind im Wesentlichen Arrays. In Analogie zu Ganzzahl-Arrays (die Ganzzahlen speichern) und Zeichen-Arrays (die Zeichentypen speichern) können wir sehen, dass Zeiger-Arrays zum Speichern von Zeigern verwendet werden.
Fügen Sie hier eine Bildbeschreibung ein

(3) Array-Zeiger

Eine ausführliche Erklärung finden Sie im folgenden Code

Fügen Sie hier eine Bildbeschreibung ein

Die Verwendung von Array-Zeigern ist wie folgt

#include<stdio.h>
void print2(int (*p)[5], int x, int y)
//第一个形参int (*p)[5]为数组指针,存放的是第一行元素构成的一维数组的地址
{
    
    
    int i = 0;
    int j = 0;
    for (i = 0; i < x; i++)
    {
    
    
        for (j = 0; j < y; j++)
        {
    
    
            printf("%d ", *(*(p + i)+j));
            /* 
            p的类型为数组指针,指向为一个一维数组的地址,p+1表示向后跳过一个数组大小,p + i表示向
            后跳过i行,假设二维数组每一行分别代表一个一维数组,则 *(p + i)表示对应的一维数组的数
            组名,而数组名代表该一维数组首元素的地址。该数组为整形数组,+j表示向后跳跃j个整形的大
            小,得到该一维数组各个元素的地址,即*(p + i)+j)表示二维数组中各个元素的地址,再通过解
            引用操作得到各个元素的值,即*(*(p + i)+j)表示二维数组每个元素的值
            */
            
        }
        printf("\n");
    }
}
int main()
{
    
    
    int arr[3][5] = {
    
     {
    
    0,1,2,3,4},{
    
    1,2,3,4,5},{
    
    2,3,4,5,6} };
    print2(arr, 3, 5);
    //在二维数组中,数组名表示第一行数组的地址(可看成一个一维数组的地址)
    return 0;
}

Durch das Studium von Zeiger-Arrays und Array-Zeigern sollten wir die Bedeutung des folgenden Codes verstehen
int arr[5]
(a five -element Integer array)
int *arr[5]
(Zeigerarray, das Array enthält fünf Elemente, jeder Elementtyp ist int *) < a i=5> int ( * arr)[5] (Array-Zeiger, zeigt auf ein Array mit fünf Elementen) int( * arr[10] )[5] (ist ein Array. Das Array hat zehn Elemente. Jedes Element ist ein Array-Zeiger. Das Array, auf das der Array-Zeiger zeigt, hat fünf Elemente. Jedes Element ist vom Typ int. )



5. Funktionszeiger

Wie der Name schon sagt, ist ein Funktionszeiger ein Zeiger auf eine Funktion, der zum Speichern der Funktionsadresse verwendet wird.

Die Darstellungsmethode des Funktionszeigers
Fügen Sie hier eine Bildbeschreibung ein
kann durch den folgenden Code verstanden werden

#include<stdio.h>
int Add(int x, int y)
{
    
    
    return x + y;
}
int main()
{
    
    
    int a = 0;
    int b = 0;
    int (*p)(int, int) = Add;//定义一个函数指针
    printf("%d\n", (*p)(10, 20));//通过函数指针调用函数
    //输出结果为30
    return 0;
}
#include<stdio.h>
void Print(char* str)
{
    
    
    printf("%s\n", str);
}
int main()
{
    
    
    void (*p)(char*) = Print;//定义一个函数指针
    (*p)("Hello World");//通过函数指针调用函数
    return 0;
}

Beispiel:
Erklären Sie den folgenden Code

//解释以下代码
void(*fun(int, void(*)(int)))(int);
        //fun是一个函数声明
        //fun函数的参数有两个,第一个为int类型,第二个为函数指针类型,该函数指针指向的函数参数类型为int,返回类型为void
        //fun函数的返回类型也是一个指针函数,该指针函数指向的函数的参数为int,返回类型为void(空)
//上述代码可通过typedef关键字进行简化,简化代码如下:
    typedef void(*fun_t)(int);//将该函数指针类型创建别名fun_t
    fun_t(fun(int, fun_t));

6. Array von Funktionszeigern

Das Funktionszeiger-Array ist im Wesentlichen ein Array, und jedes Element des Arrays ist die Adresse einer Funktion.

#include<stdio.h>
int Add(int x, int y)
{
    
    
    return x + y;
}
int Sub(int x, int y)
{
    
    
    return x - y;
}
int Mul(int x, int y)
{
    
    
    return x * y;
}
int Div(int x, int y)
{
    
    
    return x / y;
}
int main()
{
    
    
    int(*p[4])(int, int) = {
    
     Add,Sub,Mul,Div };//定义一个函数指针数组
    int i = 0;
    for (i = 0; i < 4; i++)
    {
    
    
        printf("%d\n", p[i](10, 5));//循环逐个调用函数
    }
    return 0;
}

Fügen Sie hier eine Bildbeschreibung ein

Zweck des Funktionszeiger-Arrays:Übertragungstabelle
Beispiel: Implementierung eines Taschenrechners

#include<stdio.h>
void menu()
{
    
    
    printf("**********************\n");
    printf("******   1.Add  ******\n");
    printf("******   2.Sub  ******\n");
    printf("******   3.Mul  ******\n");
    printf("******   4.Div  ******\n");
    printf("******   0.exit ******\n");
    printf("**********************\n");
}
int Add(int x, int y)
{
    
    
    return x + y;
}
int Sub(int x, int y)
{
    
    
    return x - y;
}
int Mul(int x, int y)
{
    
    
    return x * y;
}
int Div(int x, int y)
{
    
    
    return x / y;
}
int main()
{
    
    
    int input = 0;
    int x = 0;
    int y = 0;
    int (*pfarr[])(int, int) = {
    
    0, Add,Sub,Mul,Div };
    //pfarr为一个函数指针数组—转移表,通过函数指针数组下标转到对应的函数
    do
    {
    
    
        printf("请输入你的选择:\n");
        scanf_s("%d", &input);
        if (input >= 1 && input <= 4)
        {
    
    
            printf("请输入两个数:\n");
            scanf_s("%d %d", &x,&y);
            printf("%d\n", pfarr[input](x, y));
        }
        else if (input == 0)
        {
    
    
            printf("退出!\n");
        }
        else
        {
    
    
            printf("输入错误,请重新输入\n");
        }
    } while (input);
    return 0;
}

7. Funktionszeiger-Array-Zeiger

[Funktionszeiger-Array] Zeiger, Zeiger, zeigt auf ein Array von Funktionszeigern

    int (*pf)(int, int);//函数指针
    int(*pfarr[5])(int, int);//函数指针数组
    int(*(*pparr)[5])(int, int)=&pfarr;//函数指针数组指针,指向【函数指针数组】的指针
    //所指向的函数指针数组有5个元素,每个元素为一个函数指针,类型为int(*)(int,int)

Supongo que te gusta

Origin blog.csdn.net/weixin_75094128/article/details/129249462
Recomendado
Clasificación