2021-06-01


问题一

int main()
{
	int a[3][4] = { 0 };
	short s = 5;
	int a = 4;
	printf("%d\n", sizeof(s = a + 6));//2,s的类型是short,sizeof算出来的依然是short的大小
	printf("%d\n", s);//5,sizeof内部表达式不计算
	printf("%d\n", sizeof(a));//48,数组名表示整个数组,计算整个数组大小,3*4*sizeof(int)
	printf("%d\n", sizeof(a[0][0]));//4,第一行第一个元素所占空间大小是4
	printf("%d\n", sizeof(a[0]));//16,三行四列,每一行都是一个元素计算的是第一行那个数组的大小
	printf("%d\n", sizeof(a[0] + 1));//4,第一行第一个元素是个整形,跳过第一个整形,指向第二个整形,a[0]作为数组名没有单独放在sizeof内部,也没有取地址,所以a[0]就是第一行第一个元素的地址
	printf("%d\n", sizeof(*(a[0] + 1)));//4,第一行第二个元素
	printf("%d\n", sizeof(a + 1));//4,a+1是第二行的地址
	printf("%d\n", sizeof(*(a + 1)));//16,第二行的大小,a[1]就是第二行数组名,计算的就是第二行的大小
	printf("%d\n", sizeof(&a[0] + 1));//4,取出第一行地址+1就是第二行地址,大小是4个字节
	printf("%d\n", sizeof(*(&a[0] + 1)));//16,第二行地址解引用拿到第二行数组,第二行的大小是16
	printf("%d\n", sizeof(*a));//16,a作为二维数组的数组名,没有取地址,没有单独放在sizeof内部,a就是首元素的地址,即第一行的地址,所以*a就是第一行第一行地址解引用得到的是第一行,此处也可以写成*(a+0)=a[0]
	printf("%d\n", sizeof(a[3]));//16,虽然数组中只有a[0],a[1],a[2],a[3]理论上是第四行的数组名,但这里假装存在a[3],他的类型属性就是int[4],所以sizeof(a[3])就是16,sizeof()括号的内部的表达式是不会计算的,sizeof()括号内部的数组越界也没有关系,所以程序不会报错;表达式3+5的值属性是8,类型属性是int,sizeof(3+5)=4,因为他的类型属性是int
	printf("%d\n", sizeof(a[-1]));//16,与上题同理
	//总结: 数组名的意义:1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。3. 除此之外所有的数组名都表示首元素的地址。

问题二

//第二题,由于还没学习结构体,这里告知结构体的大小是20个字节
	struct Test
	{
		int Num;
		char *pcName;
		short sDate;
		char cha[2];
		short sBa[4];
	}*p;//*+结构体类型就是结构体指针
	//假设p 的值为0x100000。 如下表达式的值分别为多少?指针类型决定指针的运算,什么样的指针类型+1就跳过对应的大小
	int main()
	{
		printf("%p\n", p + 0x1);//0x100014,16进制的1和10进制的1是一样的,指针+1就是向后跳过20个字节
		printf("%p\n", (unsigned long)p + 0x1);//0x100001,被强制类型转换成整形了,整形+1就是直接+1
		printf("%p\n", (unsigned int*)p + 0x1);//0x100004,整形指针往后跳1个就是+4
		return 0;
	}

问题三

	int main()
	{
		int a[4] = { 1, 2, 3, 4 };
		int *ptr1 = (int *)(&a + 1);
		int *ptr2 = (int *)((int)a + 1);
		printf("%x,%x", ptr1[-1], *ptr2);//4,2000000   ptr[-1]= *(ptr1-1),要想有前缀要加#
		return 0;
	}
}

在这里插入图片描述

问题四

#include <stdio.h>
int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };//这是个逗号表达式,实际上数组是{1,3,5}
	int *p;
	p = a[0];//数组首元素1的地址
	printf("%d", p[0]);//1,p[0]= *(p+0),结果为1
	return 0;
}

问题五

int main()
{
	int a[5][5];
	int(*p)[4];
	p = a;//a的类型是int(*)[5],
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//这2个元素之间相差4个元素(分析过程见图),小地址-大地址得到-4,-4的原码:10000000 00000000 00000000 00000000,补码11111111 11111111 11111111 11111100,这个地址以16进制形式打印每4个1是1个F,答案是FF FF FF FC
	return 0;
}

在这里插入图片描述

问题六

int main()
{
	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int *ptr1 = (int *)(&aa + 1);
	int *ptr2 = (int *)(*(aa + 1));//第2行地址解引用,拿到了第二行,相当于aa[1],本来就是个整形,这个强制转换是多余的
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10,5
	return 0;
}

问题七

#include <stdio.h>
int main()
{
	char *a[] = { "work", "at", "alibaba" };
	char**pa = a;
	pa++;
	printf("%s\n", *pa);//答案at,分析过程见图
	return 0;
}

在这里插入图片描述

问题八

int main()
{
	char *c[] = { "ENTER", "NEW", "POINT", "FIRST" };
	char**cp[] = { c + 3, c + 2, c + 1, c };
	char***cpp = cp;
	printf("%s\n", **++cpp);//POINT
	printf("%s\n", *--*++cpp + 3);//ER
	printf("%s\n", *cpp[-2] + 3);//ST
	printf("%s\n", cpp[-1][-1] + 1);//EW
	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值