关于指针的一些细节内容

文章讲述了sizeof函数的作用,以及如何在C语言中使用它计算结构体指针和数组的大小。通过实例展示了指针加法和不同类型转换对内存地址的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们将请出我们今天重要的嘉宾来为我们的指针的讲解出一份力:

**sizeof()**函数:

sizeof函数是一个用于计算数组大小的函数,它能够计算一个函数有多少字节。

我们今天就利用sizeof函数来帮助我们进行解析指针。

接下来直接上题:

第一题:

struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
} * p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
//0x开头的数字是16进制的数字
int main()
{
	p = (struct Test*)0x100000;
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);

	return 0;
}

题解:

在vs上和x86环境下,我们的地址大小为4。

对于第一个:我们可以简单看出,是将 一个结构体指针——p + 0x1,其中加上0x1,我们可以直接看作+1;那么对一个指针直接加一,是什么结果呢?

答:再整个同类型的指针,对此题,也就是在加上一个struct Test类型的大小,也就是,加上20字节 ,因此答案就是:00100014,前面的00是为了补足32位。

对于第二个:我们可以简单看出,强制将p转换为了无符号长整型,而对无符号整型加一,就是在其值上加1,所以答案就是:00100001

对于第三个:我们可以简单看出,强制将p转换为了无符号整型指针,而对无符号整型指针加一,就是在其值上加4,所以答案就是:00100004

第二题:

int main()
{
	int aa[2][5] = { 10,9,8,7,6,5,4,3,2,1 };
	int* ptr1 = (int*)(&aa + 1);//第二行1后面的地址,&aa+1相当于跳过了整个数组
	int* ptr2 = (int*)(*(aa + 1));//第二行起始地址,即5
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//ptr1-1,即从1后面的地址变为1,ptr2-1,即从5减到上一行的6
	return 0;
}

题解:

对于二维数组来说,我们可以将它划分为两个部分,列如上面的数组:

int aa[2][5] = { 10,9,8,7,6,5,4,3,2,1 };---->aa[0][]={10,9,8,7,6}和aa[1][]={5,4,3,2,1}

这只是我们抽象出来的,在内存中储存依旧是连续的。

对于ptr1来说:&aa是整个数组的地址,加一就跳过了整个数组,因为本身地址就是int *类型,因此强制转换为int *没有影响。

对于ptr2来说:aa是第一行的地址,第一行的地址加一,就是第二行起始位置。

然后在printf中:ptr1-1,就指向了数组最后一个,结果为1,prt2-1,就到了第一行的最后一个,结果就是:5。

第三题:

#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };//work\0   at\0   alibaba\0
	char** pa = a;//pa的类型是char**,是一个二级指针
	pa++;
	printf("%s\n", *pa);
	return 0;
}

题解:

有第一行和第二行我们可以得知:a是一个字符串数组,pa是一个二级指针。

对于一个二级指针++一次,就是跳过一个char *类型的大小,故pa

由指向a的第一个字符串,指向了第二个字符串地址,所以,解引用pa就是第二行元素,答案就是:at

第四题:

int main()
{
	int a[4] = { 1, 2, 3, 4 };
	int* ptr1 = (int*)(&a + 1);//跳过整个数组,在4后面
	int* ptr2 = (int*)((int)a + 1);
	printf("%x,%x", ptr1[-1], *ptr2);//ptr1[-1]相当于*(ptr1-1),为4
	return 0;
}

题解:

对于ptr1来说:&a就是取整个数组的地址,ptr1+1就到了指向了4后面。而ptr1[-1]就是访问ptr1当前位置的后一个数据类型,也就是:4

对于ptr2来说:将a(这里a是数组第一个的地址)强制转化为int类型,也就是01000000,+1后就是01000001(int型),然后在转换为整型指针,也就是:01000001(int*型),也就是移动了一个字节;而对地址来说,有四个字节,因此ptr2此时指向的内存地址不再是10(下面表格内容),而是跳过了01,指向01后面的00,而在对ptr2解引用,需要四个字节的地址,就读取到00 00 00 02,然后高地址放在高位,低地址放在地位,就是:02 00 00 00 因此打印出来就是:2000000。

扩充:由于我所使用的是小端机器,和32位环境下:

对于数组的内存储存可以得知:

01000000 (1)02000000(2)03000000 (3)04000000(4)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值