C语言的灵魂:指针

指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。

(1) int *ptr;
(2) char *ptr;
(3) int **ptr;
(4) int (*ptr)[3];
(5) int *(*ptr)[4];

1.指针的类型

从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。

(1) int *ptr; //指针的类型是int*
(2) char *ptr; //指针的类型是char*
(3) int **ptr; //指针的类型是int**
(4) int (*ptr)[3]; //指针的类型是int(*)[3]
(5) int *(*ptr)[4]; //指针的类型是int*(*)[4]

2.指针所指向的类型

从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。

(1) int *ptr; //指针所指向的类型是int
(2) char *ptr; //指针所指向的类型是char
(3) int **ptr; //指针所指向的类型是int*
(4) int (*ptr)[3]; //指针所指向的类型是int()[3]
(5) int *(*ptr)[4]; //指针所指向的类型是int*()[4]

3.指针的值

指针所指向的内存区或地址

4.指针本身所占的内存大小

只要用函数sizeof(指针的类型)
int ptr;
sizeof(int
);

运算符

&是取地址运算符,*是间接运算符。
“ & ”和“ * ”都是右结合的。

假设有变量 x = 10
则*&x 的含义是:
先获取变量 x 的地址,再获取地址中的内容。
因为“&”和“*”互为逆运算,所以 x = *&x。

初始化初始化:

利用取地址获取 x 的地址,在指针变量 px 定义时,赋值给 px

int x;
int *px = &x;

定义指针变量,分别赋值“NULL”和“0”

int *p1= NULL, *p2 = 0;

此时的“0”含义并不是数字“0”,而是 NULL 的字符码值。
这种初始化的方式表示其目前还未指向任何对象。

    int a = 100, b;
    int *p = &a;
    int *p2 = NULL;
    p2 = &a;

    printf("%d\n", *p2);
    printf("%p\n", p);
    printf("%p\n", &a);
    printf("%d\n", *p);

C 指针的算术运算:

    int a[] = {
   1, 2, 100, 4, 5, 6, 7};
    int *p = a;
    printf("%d\n", *p);
    printf("%d\n", *p++);
    printf("%d\n", *p);

    printf("%d\n", *p);
    printf("%d\n", *++p);
    printf("%d\n", ++(*p++));
    printf("%d\n", *p);
    printf("%d\n", *(p + 3));
    printf("%d\n", *p + 1);

需要明确一个优先级顺序:()>[]>*

C 指针数组: int *p1[5];

数组存储指向 int 或 char 或其他数据类型的指针。
一个数组的元素均为指针类型数据,称为指针数组。

C 数组指针: int (*p2)[5]; => *(p2[5]);

如果一个指针指向了数组,我们就称它为 数组指针。

 	int  var[3] = {
   10, 100, 200};
    int i, *ptr[3];//指针数组
    int (*ptr2)[3];//数组指针
    ptr2 = &var;
    for (i = 0; i < 3; i++)
    {
   
        ptr[i] = &var[i]; /* 赋值为整数的地址 */
    }
    for ( i = 0; i < 3; i++){
   
      printf("Value of var[%d] = %d\n", i, *ptr[i] );
      printf("Value of var[%d] = %d\n", i, (*ptr2)[i] );
    }
    
    }
	char name[10][10]= {
   
                   "Zara Ali",
                   "Hina Ali",
                   "Nuha Ali",
                   "Sara Ali",
    };
    //char name[0];
    //char *p = name[0];
    const char *names[4] = {
   
        "Zara Ali",
        "Hina Ali",
        "Nuha Ali",
        "Sara Ali",
    };
    int i = 0;
    for ( i = 0; i < 4; i++){
   
      printf("Value of names[%d] = %s\n", i, names[i] );
      }

C 指针函数:*p(int, int)

它的本质是一个函数,不过它的返回值是一个指针。

C 函数指针:(*p)(int, int)

函数指针是指向函数的指针。
通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数。

int max(int a,int b){
   
    if(a>b)
        return a;
    else
        return b;
}
int *fun(int n){
   
    static int arr[100];//静态变量
    //C 不支持在调用函数时返回局部变量的地址,除非定义局部变量为 static 变量。
    //static 变量的值存放在内存中的静态数据区,不会随着函数执行的结束而被清除,故能返回其地址。
    int i;
    for (i = 0; i < n;i++){
   
        arr[i] = i;
    }
    return arr;//返回了指针
}```

```cpp
	int (*p)(int, int) = &max;//函数指针
    int a = 10, b = 5;
    printf("最大数为:%d\n", p(a, b));
    //等价于max(a,b);

    int n = 10;
    int *p1;
    p1 = fun(n);
    int i;
    for (i = 0; i < n;i++){
   
        printf("%d\n", *(p1 + i));
    }

编写一个函数实现:将字符串中的字符以逆序形式存放。

在main函数中输入这个字符串,调用函数逆序存放,输出变化后的字符串

(要求:形参是指针类型变量)。

交换函数

void swap1(int a,int b){
   
    int t;
    if(a<b){
   
        t = a;
        a = b;
        b = t;
    }
    printf("%d %d\n", a, b);
}

void swap(int *a,int *b){
   
    int t;
    if(*a<*b){
   
        t = *a;
        *a = *b;
        *b = t;
    }
}

int main(){
   
    int a = 100, b = 200;
    printf("%d %d\n", a, b);
    swap1(a, b);
    printf("%d %d\n", a, b);
    swap(&a, &b);
    printf("%d %d\n", a, b);
}

#include<string.h>
void func(char *a,int n){
   
    char temp;
    for (int i = 0; i < n / 2;i++){
   
        temp = *(a + i);
        *(a + i) = *(a + n - 1 - i );
        //0 ...n-1
        *(a + n - i - 1) = temp;
    }
    puts(a);
}
int strlen(char *a){
   
    int i = 0;
    while(a[i]!='\0'){
   
        i++;
    }
    return i;
}
int main(){
   
    char a[100];
    gets(a);
    int len = strlen(a);
    printf("%d\n", len);
    func(a, len);
    return 0;
}