指针数组与数组指针的区别以及指针需要注意的问题

  1. 指针数组
int a = 11;
int b = 22;
int c = 33;
int* brray[3];  //指针数组的定义,*号在数组名前,有三个指针,分别如下:
                    //将3个毫无联系的变量给结合到了一块
brray[0] = &a;
brray[1] = &b;
brray[2] = &c;

for(i = 0; i < 3; i++){
    printf("%d ", *(brray[i]));
}

	/*int *p;
    p = array;

    for(i = 0; i < 3; i++){
        printf("%d ", *p++);
    }*/  //*p不叫做指针数组,它是整形变量指针,刚好指向了数组首地址

运行结果:11 22 33

  1. 数组指针
int array[3] = {1, 2, 3};
int (*p)[3];   //数组指针的定义, 强调的是类型,数组的个数
p = array;
int *p2;
p2 = array;

printf("array的地址:%p\n", array);
printf("array的地址:%p\n", &array[0]);
printf("p的地址:%p\n", p);
printf("p2的地址:%p\n", p2);    //四个地址全部为000000000061FDF0

printf("***********注意区别来了************\n");
printf("++p的地址:%p\n", ++p);   //p移动后的内存地址为:000000000061FDFC
printf("++p2的地址:%p\n", ++p2); //p2移动后的内存地址为:000000000061FDF4

//ps:数组指针偏移的是整个数组的大小,对于p而言就是3*4=12个字节
//整型变量指针偏移的是一个整型指针大小即4个字节

  1. 指针需要注意的小细节
    (1)指针定义
int *p;   //定义指定变量,存放的是变量地址
p = &a;   //给指针变量赋值
//*p = &a;  //这种定义是错误的

int *p = &a;  //*号只有在定义指针的时候,才是指针的标识符,其余时候都是运算符,此时跟+-*/运算符功能相似,表示将变量内存地址中存储的数据值给取出来

(2)指针偏移

int array[3] = {1, 2, 3};
int *p1 = array;  //int *p1 = &array[0]   数组首地址:1.数组名;2.数组第一个元素地址
printf("第一个元素地址:%p\n", p1++);  //int类型指针偏移4个字节
printf("第二个元素地址:%p\n", p1++);
printf("第三个元素地址:%p\n", p1);

char brray[3] = {'a', 'b', 'c'};
char *p2 = &brray[0];
printf("第一个元素地址:%p\n", p2++);  //char型指针偏移占1个字节
printf("第二个元素地址:%p\n", p2++);
printf("第三个元素地址:%p\n", p2);


int *k = (int *)0x0061FDEE;
*k = 24;
printf("k的内存地址为:%p, 存放值为:%d\n", k, *k);

/*
volatile int *k = (volatile int *)0x0061FDEE;
volatile: 类型修饰符:主要作用是,当处于多线程时,A线程可能会对寄存器中的指针变量k的值进行更改
B线程此时可能就不会知道指针k的值已经发生变化了,所以操作系统会使用volatile直接在内存地址中对指针k的值进行读取,从而使得相应计算结果准确无误*/

(3)内存泄漏

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
	int n;
    int i;
    printf("请输入学生成绩个数:\n");
    scanf("%d", &n);

    int array[n];   //用数组也可以输入数据并且遍历数据
    for(i = 0; i < n; i++){
        printf("%d学生成绩:\n", i+1);
        scanf("%d", &array[i]);
    }

    for(i = 0; i < n; i++){
        printf("%d ", array[i]);
    }
    putchar('\n');

    int *prray = (int *)malloc(n * sizeof(int));  //malloc开辟内存空间
    int *p1 = prray;
    printf("prray首地址为:%p\n", prray);
    for(i = 0; i < n; i++){
        printf("请输入第%d个学生成绩:\n", (i+1));
        //scanf("%d", &prray[i]);  //这样以数组的形式输入可以避免指针偏移对后续结果打印产生影响

		//也可以用指针来输入,但需要注意指针偏移对后面结果打印产生的影响
        printf("prray[%d]的地址:%p\n", (i), &prray[i]);
        scanf("%d", prray);
        prray++;
    }
    putchar('\n');

    // prray = &prray[0];这两个偏移前后本来就是相等的,这样是无法使指针指向偏移前的首地址----容易混淆的重点:指针偏移后的首地址与偏移前的首地址是不同的,属于两个不同的地址量
    printf("prray偏移后首地址:%p\n", prray);
    printf("prray[0]首地址为:%p\n", &prray[0]);
    prray = p1; //用中间指针变量将prray重新指向原偏移前的首地址

    printf("prray首地址为:%p\n", prray);
    for(i = 0; i < n; i++){
        printf("第%d个学生成绩为:%d\n", (i+1), *prray++);
    }

    free(prray);
	/*
    malloc之内存泄漏:
    1.程序跑起来很好,过了几个小时或几周后,程序崩了
    2.malloc申请的空间,程序不会主动释放,Linux中的话,程序结束后,系统会回收这个空间
    如何避免?
    1.注意在循环语句中是否重复申请
    2.记得及时合理地释放,即free(p); p = NULL;释放后避免指针p成为野指针,赋值NULL
    */

    return 0;
}

运行结果如下:
请输入学生成绩个数:
3
学生1成绩:
89
学生2成绩:
88
学生3成绩:
79
89 88 79
prray首地址为:0000000000B66AE0
请输入第1个学生成绩:
89
prray[0]的地址:0000000000B66AE0
请输入第2个学生成绩:
88
prray[1]的地址:0000000000B66AE8
请输入第3个学生成绩:
79
prray[2]的地址:0000000000B66AF0

prray偏移后首地址:0000000000B66AEC
prray[0]首地址为:0000000000B66AEC
prray首地址为:0000000000B66AE0
第1个学生成绩为:89
第2个学生成绩为:88
第3个学生成绩为:79
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值