先来简单的了解指针

image

可以说地址即是指针
通过指针(地址)能找到以它为地址的内存单元
存放于指针中的值都被当成地址处理

一个简单的指针
int a=10;
int* p=&a;
    int a = 1;
    int *pa = &a;
    char *pc = &a;
    //取出地址一样
    printf("%p\n", pa);
    printf("%p\n", pc);

那既然输出的地址一样 那还区分char和int类型干嘛

#include<stdio.h>

int main() {
    int a = 0;
    int *pa = &a;
    char *pc = &a;
    printf("%p\n", pa);
    printf("%p\n", pa + 1);
    printf("%p\n", pc);
    printf("%p\n", pc + 1);
}

image

这样我们就很清楚的看到类型的作用:
即指针类型决定指针解引用能够访问空间的大小
不妨测试下:

指针变量的大小都一样 主要是访问空间的大小不同
    //64位机器上 一个指针变量大小为8个字节
    //32位机器上 一个指针变量大小为4个字节
    printf("%d\n", sizeof(char *));
    printf("%d\n", sizeof(int *));
    printf("%d\n", sizeof(float *));

常用的:

  1. int 4个字节
  2. char 1个字节
  3. double 8个字节
  4. float 8个字节

再看具体例子:

 int arr[10] = {0};
    //数组名为数组首元素的地址
    int *p = arr;
    //若改成char 只修改了总共10个字节
//    char *p=arr;
    int i = 0;
    for (i = 0; i < 10; ++i) {
        *(p + i) = 1;
    }
    for (int i = 0; i < 10; ++i) {
        printf("%p\n", arr[i]);
    }

image

image

可以看到改为char*后只能 向后修改10个字节 因为char类型的作用


野指针

简单来说就是指针指向位置是不可知的 就是瞎**乱指
三种情况:

#include<stdio.h>

int *fun();
static int b;
int a;
float c;

int main() {
    //指针不初始化 就是一个随机值 野指针
    int *p;
    printf("%d\n", a);
    printf("%d\n", b);
    printf("%f\n", c);
    printf("%p\n", p);

    //指针越界访问 野指针
    int arr[10] = {0};
    int *pp = arr;
    int i = 0;
    for (i = 0; i < 12; ++i) {
        *pp + 1;
    }

    //指针指向了已经释放的内存空间 野指针
    int *ppp = fun();
    *ppp=20;
}

int *fun() {
    int a = 10;
    return &a;
}

如果要避免就对应上述三种情况避免 就是规范写法


指针的运算:

  • 指针+-整数
  • 指针-指针
  • 指针的关系运算(比较大小)

这里穿插个知识 随着下标增大 对应地址也变大

    //打印数组
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int n = sizeof(arr) / sizeof(arr[0]);
    int *p = arr;
    for (int i = 0; i < n; ++i) {
        printf("%d ", *p);
	//指针p+1
        *p += 1;
    }
#include<stdio.h>

#define value 5

int main() {
    //将数组values元素全赋值为0
    float values[value];
    float *vp;
    for (vp = &values[0]; vp < &values[value];) {
        //分号";"后没有vp++ ====》先算赋值运算   然后vp++
        *vp++ = 0;
    }
    printf("\n%d\n", *vp);
}
#include<stdio.h>

int main() {
    int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    //得到的是中间元素个数
    printf("%d", &a[9] - &a[0]);
}
规定比较只可与最后一个元素之后进行比较

指针和数组

还是要说到关于数组名首元素地址的问题:

    //关于元素首地址
    int arr[10] = {0};
    printf("%p\n", arr);
    //加了4
    printf("%p\n", arr + 1);

    printf("%p\n", &arr[0]);
    //加了4
    printf("%p\n", &arr[0] + 1);

    //&arr整个数组的地址
    printf("%p\n", &arr);
    //加了40 跨过了一个数组
    printf("%p\n", &arr + 1);
就两个例外: 1. &arr 取出整个数组地址 2.sizeof(arr) 表示整个数组大小
    //指针数组 存放指针的数组
    int x = 10, y = 20, c = 30;
    int* ok[3]={&x,&y,&c};
    for (int i = 0; i < 3; ++i) {
        printf("%d ",*(ok[i]));

二级指针
int* pa :	*pa告诉是个指针  int 告诉指向对象类型为int
    int a = 10;
    int *p = &a;
    int **p2 = &p;
    printf("%d\n", **p2);
    **p2 = 50;
    printf("%d\n", a);
posted on 2024-05-24 20:19  蒸饺  阅读(15)  评论(0)    收藏  举报