针对指针加减的一些知识和几则题目

一、指针加减运算规则

1.运算规则

我们平常说的指针是指针变量,是用来存放内存地址的变量,通俗讲就是说将一个变量或者函数的地址的地址取出放入指针变量中,每一个内存上的字节都对应一个地址。

指针变量中存放的是一串数字,而这串数字再进行运算的时候,跟普通的算术运算大不相同,当对同一个指针进行运算时,计算机会根据指针指向类型进行计算,跳过一个该类型的大小。例:当一个指针变量指向整型,给指针变量+1,其在该内存中存储的数字就会+4。

即p+1在内存中存储的数字不会变成0x00121213,而是会变成0x00121216,从应用方面理解就是,给指针变量+1,指针变量会自动跳过其所指向的这个类型的变量的所有地址,指向其后方。

2.其他说明

再对题目进行分析之前还需要对一些小知识点说明一下,以防混淆

(1).数组名一般表示首元素地址但 &数组名 sizeof(数组名),求出的是整个数组的大小;

(2).sizeof()计算的是类型的大小,其知道括号内是什么类型就直接输出结果,不会对括号内的表达式进行计算,且注意数组名和数组名+0意思不同,一个是计算整个数组大小,一个是指针变量;

(3).strlen(),这个函数返回值是size_t,函数参数接收形式为const char *,遇到 '\0' 会停止计算。

(4).sizeof是计算'\0'的,strlen是不计算'\0'的

(5)对数组指针进行解引用时,取出来的是整个数组。

二、题目

1.整型数组

int a[] = {1,2,3,4};

printf("%d\n",sizeof(a));  此处求出的是整个数组的大小——16字节

printf("%d\n",sizeof(a+0));  此处a不是自己单独出现的,a代表首元素地址——4/8字节

printf("%d\n",sizeof(*a));  此处a代表首元素地址,*a代表首元素,int类型——4字节

printf("%d\n",sizeof(a+1)); a+1即代表a数组第二个元素的地址4/8字节

printf("%d\n",sizeof(a[1]));a[1]等同于 *(a+1) ,int类型——4字节

printf("%d\n",sizeof(&a)); &a取出整个数组的地址即为数组指针 int(*)[4]类型——4字节

printf("%d\n",sizeof(*&a)); *与&抵消掉,即a代表数组名——16字节

printf("%d\n",sizeof(&a+1));取地址操作符优先级高于+,此处指向a数组后面的一个数组指针(这个加1跳过了16个字节)——4/8字节

printf("%d\n",sizeof(&a[0]));此处取出的是首元素的地址——4/8字节

printf("%d\n",sizeof(&a[0]+1))此处是第二个元素的地址——4/8字节

2.字符数组

char arr[] = {'a','b','c','d','e','f'};  这种字符串存储方式结尾没有'\0'

printf("%d\n", sizeof(arr));  sizeof(数组名)求的是整个数组的大小——6字节

printf("%d\n", sizeof(arr+0)); arr不是单独出现的,此处代表首元素地址——4/8字节

printf("%d\n", sizeof(*arr));*arr,代表首元素——1字节

printf("%d\n", sizeof(arr[1]));arr[1]=*(arr+1),此处代表第二个元素'b'——1字节

printf("%d\n", sizeof(&arr));此处取出的是整个字符串的地址——4字节

printf("%d\n", sizeof(&arr+1));此处取出地址后加以指向'f'后面的地址,(此处+1跳过6个字节)——4/8字节

printf("%d\n", sizeof(&arr[0]+1));此处为第二个元素的地址——4/8字节

printf("%d\n", strlen(arr)); 数组名代表首元素地址,字符串的存储最后没有'\0'——随机值

printf("%d\n", strlen(arr+0));  arr+0代表首元素地址,同上——随机值

printf("%d\n", strlen(*arr));*arr->'a',字符a的ASCII码值为97,strlen就会去找97地址处——ERR

printf("%d\n", strlen(arr[1]));意思同上——ERR

printf("%d\n", strlen(&arr));此处为数组指针,strlen需要的是字符指针,但是二者数值相同,strlen会使用这里的数组指针作为字符指针——随机值

printf("%d\n", strlen(&arr+1)); 此处跳过arr字符串,指向'f'后——比上面的随机值小6

printf("%d\n", strlen(&arr[0]+1));第二个字符的地址——比前面的随机值小1

char arr[] = "abcdef"; 这种命名方式使得字符串最后有'\0'

printf("%d\n", sizeof(arr));arr为数组名,此处计算整个数组的大小——7字节

printf("%d\n", sizeof(arr+0));arr不是单独出现,此处代表首元素地址——4/8字节

printf("%d\n", sizeof(*arr));此处代表第一个字符——1字节

printf("%d\n", sizeof(arr[1]));此处代表第二个字符——1字节

printf("%d\n", sizeof(&arr));此处代表数组指针——4/8字节

printf("%d\n", sizeof(&arr+1));此处跳过整个字符串,包括'\0',但还是指针变量——4/8字节

printf("%d\n", sizeof(&arr[0]+1));第二个字符的地址——4/8字节

printf("%d\n", strlen(arr));此处为首元素地址,且有'\0'——6字节

printf("%d\n", strlen(arr+0));此处也为首元素地址——6字节

printf("%d\n", strlen(*arr));此处为第一个元素——ERR

printf("%d\n", strlen(arr[1]));此处为第二个元素——ERR

printf("%d\n", strlen(&arr));strlen需要的是字符指针,但是二者数值相同,strlen会使用这里的数组指针作为字符指针——6字节

printf("%d\n", strlen(&arr+1));跳过整个字符串——随机值

printf("%d\n", strlen(&arr[0]+1));第二个元素开始算——5字节

char *p = "abcdef"; 将首元素的地址存入p,p就是一个字符指针

printf("%d\n", sizeof(p)); p就是一个字符指针——4/8字节

printf("%d\n", sizeof(p+1));指向第二个字符——4/8字节

printf("%d\n", sizeof(*p));第一个字符,char——1字节

printf("%d\n", sizeof(p[0]));p[0]=*(p+0),第一个字符——1字节

printf("%d\n", sizeof(&p));二级指针,指向p的指针 char**类型——4/8字节

printf("%d\n", sizeof(&p+1));跳过一个char*的对象,指向p的后面——4/8字节

printf("%d\n", sizeof(&p[0]+1));此处指向b,为字符指针——4/8字节

printf("%d\n", strlen(p));p为首元素地址——6字节

printf("%d\n", strlen(p+1));p+1从第二个字节开始算——5字节

printf("%d\n", strlen(*p));第一个字符——ERR

printf("%d\n", strlen(p[0]));p[0]=*(p+0)——ERR

printf("%d\n", strlen(&p));二级指针指向p——随机值

printf("%d\n", strlen(&p+1));二级指针指向p后——随机值

printf("%d\n", strlen(&p[0]+1));第二个元素地址开始算——5字节

3.二维数组

int a[3][4] = {0};

printf("%d\n",sizeof(a));sizeof(a)是整个数组的大小,共3*4——48字节

printf("%d\n",sizeof(a[0][0]));  a[0][0]=*(*(a+0)+0),第一个元素——4字节

printf("%d\n",sizeof(a[0]));a[0]代表第一行的数组名,sizeof(数组名)代表整个数组的大小,这里也就是4*4——16字节

printf("%d\n",sizeof(a[0]+1));a[0]不是单独出现,这里代表第a[0][1]处的地址,int*类型——4/8字节

printf("%d\n",sizeof(*(a[0]+1)));上面的地址解引用了——4字节

printf("%d\n",sizeof(a+1));数组名不是单独出现a+1代表第二行地址(int*[4]类型)——4/8字节

☆printf("%d\n",sizeof(*(a+1)));a+1代表第二行地址,对第二行地址进行解引用,即对int*[4]进行解引用,取出了一个数组——16字节

printf("%d\n",sizeof(&a[0]+1));第二行的地址——4/8字节

printf("%d\n",sizeof(*(&a[0]+1))); 对第二行的地址进行解引用——16字节

printf("%d\n",sizeof(*a));对第一行元素进行解引用——16字节

printf("%d\n",sizeof(a[3]));第四行数组名,sizeof不会管内存中到底有没有这个a[3]只要知道类型就会计算——16字节

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值