36.C语言进阶 — 练习 && 解释

int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));           //48   ps:3*4*sizeof(int)
	printf("%d\n", sizeof(a[0][0]));     //4    ps:a[0][0] - 第一行第一个元素
	printf("%d\n", sizeof(a[0]));	     //16   ps:a[0]可以理解为第一行的数组名
	printf("%d\n", sizeof(a[0] + 1));    //4    ps:a[0]作为数组名不是单独放在sizeof内部,是表示首元素的地址
										 //        a[0] + 1表示第一行第二列的地址,因为是地址所以长度为4
	printf("%d\n", sizeof(*(a[0]+ 1)));  //4    ps:*(a[0]+ 1)是第一行第二个元素
	printf("%d\n", sizeof(a + 1));       //4    ps:a表示的是首元素的地址,即第一行的地址,+1就是第二行的地址,因为是地址所以是4
	printf("%d\n", sizeof(*(a + 1)));    //16   ps:解引用后就是第二行
	printf("%d\n", sizeof(&a[0] + 1));   //4    ps:&a[0]是取第一行的地址,+1就是第二行的地址。所以为4
	printf("%d\n", sizeof(*(&a[0] + 1)));//16   ps:解引用...
	printf("%d\n", sizeof(*a));		     //16   ps:a是第一行的地址,解引用就是第一行
	printf("%d\n", sizeof(a[3]));		 //16   ps:见下面
	//表达式有两个属性    3+5     a[3]
	//1.值属性			  8  
	//2.类型属性		  int     int [4]   so sizoef(a[3]) = 16
	//sizeof()		      内部的表达式不计算的!

	return 0;
}

为了更好理解最后一个代码,可以再看一段代码

int main()
{
	short s = 5;
	int a = 4;
	printf("%d\n", sizeof(s = a + 6));  //2
	printf("%d\n", s);				    //5
	return 0;
}

因为sizeof不计算表达式,只看类型属性,所以sizeof(s = a + 6)可以等价为sizeof(s).


好了,现在我们来做一些笔试题吧~

int main()
{
	int a[5] = { 1,2,3,4,5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));//2  5
	return 0;
}

解释:    result  -  2  5

* (a + 1)  :a是首元素的地址,+1是第二个元素的地址,那它们解引用后就是 2
        * (ptr - 1):&a是数组的地址,+1就是指向数组后面一个地址,再强制类型转换下,所以ptr就是地址后面一个元素并且是int*的类型,那么它 -1 (注意是整形指针噢~)就是5的地址了

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

	return 0;
}

解释:     result  -  0x100014   0x100001   0x100004

第一行:p是指结构体指针地址,那么它 + 1就是加20,即0x100000(十六进制) + 20(十进制) = 0x100014
第二行:unsigned long是整数,那么+1 就是加1,所以为 0x100001
第三行:unsigned int*是个指针,那么+1 是加一个整形,所以+4 为0x100004

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);
	return 0;
}

解释:     result  -  2000000,4

ptr1:&a是指a的地址,+1就是a后面一个地址,强制类型转换成int*,那么ptr[-1]是a倒数第三个地址
ptr2:a是首元素地址,那么它+1是第二个地址,再强制类型转换成int,*ptr2就是解引用第二个开始的4个地址
   01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00   (小端)
        |                                                       |
      ptr1                                                 ptr2
  0x 02 00 00 00                          0x 00 00 00 04
 result:       2000000                              4    

int main()
{
	int a[3][2] = { (0,1),(2,3),(3,5) };
	int* p;
	p = a[0];
	printf("%d", p[0]);
	return 0;
}

解释:    result  -  1

{ (0,1),(2,3),(3,5) }  ()里的是逗号表达式,所以可以理解为{1,3,5}
那p = a[0]可以理解为指向a第一个元素的地址,p[0]也是一样的意思,所以输出为1

int main()
{
	const char* a[] = { "work","at","alibaba" };
	const char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

解释:    result  -  at

pa指向的是a的第一个元素的地址(work),那么pa++指向的就是(at)
那么*pa就是at啦

int main()
{
	const char* c[] = { "ENTER","NEW","POINT","FIRST" };
	const char** cp[] = { c + 3,c + 2,c + 1,c };
	const 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;
}

解释:        result  -  point  er  st  ew

int main()
{
	const char* c[] = { "ENTER","NEW","POINT","FIRST" };
	const char** cp[] = { c + 3,c + 2,c + 1,c };
	const 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;
}

解释:        result  -  POINT  ER  ST  EW

第一行:*++cpp ->cp[c + 2] -> c[point],  那么把它解引用就是point了
第二行:++cpp是指 c + 1(前面加过了),解引用后 -- 变成c
           再解引用是指向ENTER中的第四个E的地址,所以结果为ER
第三行:*cpp[-2] + 3可以理解为**(cpp-2)+3 cpp现在指向的是c+1
            那么它-2就是指向c+3,再解引用就是FIRST,它再+3就是S的地址,所以结果为ST
第四行:cpp[-1][-1]+1可以理解为*(*(cpp-1)-1)+1,cpp现在是指向c+3,那么它-1指向的是c+2
            那么把它解引用后就是POINT的地址,那么它-1就是NEW的地址,再解引用就是NEW                    首元素的地址再把它+1就是E的地址,所以输出的结果为EW       

如果喜欢我的文章可以点赞收藏下,后面将会有更多优质的文章,希望大家喜欢~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值