c语言指针-权限与数组

目录

指针类型的意义:

野指针以及如何避免野指针:

         数组指针

指针的运算:

指针操作数组


指针类型的意义:

1.指针解引用的权限有多大

void main(){

       int a=0x11223344;

       char *p=&a;

       *p=0;

       //运行的结果是0x11223300,仅仅把44改变了

}

为什么是改变的44而不是11,这就涉及到计算机存储的两种模式:

大端存储与小端存储,暂时不涉及。

2.指针走的步长

void main(){

       int arr[]={1,3};//首元素地址为0x11

       int *p=arr;

       char *cp=arr;

       p+1;//地址变为0x15,一个int走四个字节

       cp+1;//地址变为0x12,而char就走一个字节,利用这个特性,进行强转,很强大

}

野指针以及如何避免野指针:

1.第一种是没有定义的指针,比如

int *p;
*p=20;

这里的指针p的地址是个随机值,你使用的时候并没有申请该地址,如果直接使用该指针,像上面那样赋值,编译器并不会报错,但是会使用未申请的地址,形成错误。//正确的应该让指针初始化,如果不知道该初始化为什么,可以用int *p=NULL;

2.被释放掉了

int* text(){
       int a=10;
       return &a;
}
void main(){
       int *p=text();//由于a是个局部变量,所以离开text函数,a就被销毁了,同样是相当于没有申请a的空间
}

3.小心指针越界:在访问数组

数组指针

指针的运算:

指针-指针

void main(){

       int arr[10]={1,2,3,4,5,6,7,8,9,10};

       int *p1=arr[0];//1

       int *p2=arr[9];//10

       int c=p2-p1;

      

      

       //c=9,指针-指针,得到的结果为俩指针中间的元素个数

}

使用指针遍历,给数组赋值

int *vp=NULL;

for(vp=&arr[10];vp>&arr[0];){//先让指针指向数组的第11个地址,尽管没有定义

       *--vp=0;//先让指针—指向第十个地址,在修改值    

}

指针操作数组

为了方便理解,采用图片形式

这里有一数组为char arr[5]={1,2,3,4,5};

假设数组首元素地址为0x01.

1. char arr[5]={1,2,3,4,5};

2. char(*parr)[5]=&arr;

第二行代码意思是:

parr首先与*结合(因为有括号,按照优先度进行),成为一个指针,再与[5]结合,意味指针指向数组为5个个数的元素。此时parr指向了arr数组

此时parr的数组状态为:(同样假设arr的地址为0x01)

(*parr)- Parr中存放的是整个数组的地址,如果要访问数组元素,应该先把整个数组的地址转换为数组首元素地址即(*parr)

((*parr)+1)-在(*parr)的基础上加1,取到的地址也加1,即取到的为0x02

*((*parr)+1) -对取到的地址0x02进行取值得到值为2

把1换位i,对i遍历便可得到整个数组的内容

其实把char(*parr)[5]=&arr;中的&arr换成arr,效果还是一样的,以parr的视角去看arr这个地址,会把这个地址看作为整个数组的指针,写&arr只是为了方便理解。

此时parr等效于&arr。

&arr是整个数组的地址,arr是数组首元素地址,两者地址相同,

但取一个数组名的地址所产生的是一个指向数组的指针,而不是一个指向某个指针常量值的指针,&arr与arr尽管这两个地址内容相同,但也是有区别的,区别在于类型不同:

&arr类型是地址 arr数组名的类型是指针变量。

如果直接打印printf(“%d”,*(&arr));则打印出来的是printf(“%d”,arr)

我们定义一个指针变量

Char *p=&arr;

这时p赋值的内容为整个数组的地址,但由于将数组的地址赋给了指针变量,指针变量会把它看作数组首元素地址,故可将p看作arr数组名首地址,类型为指针变量。

验证  &arr是地址 ,arr是指针,地址!=指针\n对地址取值就是指针

环境: windows环境 VS2022  64位

void main() {
	int arr[10] = {0};
	int(*parr)[10] = &arr;
	printf("&arr:    %x\n",&arr);
	printf("&arr+1:  %x\n",&arr+1);
	printf("parr:    %x\n",parr);
	printf("parr+1:  %x\n",parr+1);

	printf("&arr是地址 ,arr是指针,地址!=指针\n对地址取值就是指针\n");

	printf("arr:       %x\n",arr);
	printf("arr+1:     %x\n",arr+1);
	printf("(*parr):   %x\n", (*parr));
	printf("(*parr)+1: %x\n", (*parr) + 1);
}

下面是结果:

&arr:    53f774
&arr+1:  53f79c
parr:    53f774
parr+1:  53f79c
&arr是地址 ,arr是指针,地址!=指针
对地址取值就是指针
arr:       53f774
arr+1:     53f778
(*parr):   53f774
(*parr)+1: 53f778

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蠢 愚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值