C语言指针进阶学完指针必看练习题详解-创新互联

该篇与上篇衔接

创新互联"三网合一"的企业建站思路。企业可建设拥有电脑版、微信版、手机版的企业网站。实现跨屏营销,产品发布一步更新,电脑网络+移动网络一网打尽,满足企业的营销需求!创新互联具备承接各种类型的成都网站设计、成都做网站项目的能力。经过10年的努力的开拓,为不同行业的企事业单位提供了优质的服务,并获得了客户的一致好评。二维数组
int main()
{int a[3][4] = {0 };
	printf("%d\n", sizeof(a));//48   3*4*sizeof(int)
	printf("%d\n", sizeof(a[0][0]));//4   第一行第一个元素  就是整形大小
	printf("%d\n", sizeof(a[0]));//16
	//a[0]就可以理解为 第一行数组名 
	//sizeof(a[0])数组名a【0】单独放在sizeof内部 a【0】表示整个第一行
	//sizeof(a[0])计算的就是第一行的大小

	printf("%d\n", sizeof(a[0]+1));//4/8  符合sizeof规则第三条 所以他叔第一行第一个元素的地址
	printf("%d\n", sizeof( * (a[0] + 1)));//4     第一行第二个解引用 , 的到元素
	printf("%d\n", sizeof(a+1));//4/8   对于二维数组来说 首元素就是第一行
	printf("%d\n", sizeof(*(a+1)));//16   *(a+1)->a[1]
	printf("%d\n", sizeof(&a[0]+1));//  4/8
	printf("%d\n", sizeof(*(&a[0] + 1)));// 16
	printf("%d\n", sizeof(*a));// 16    a是代表整个数组  *a 代表的是对第一行解应用 得到的是第一行的数组
	printf("%d\n", sizeof(a[3]));//16  既然a[3]存在它的类型就是int()[4] 假象他是一个第四行











	

	return 0;
}

int main()
{short s = 5;
	int a = 4;
	printf("%d", sizeof(s = a + 6));//2   最后的结果由short而定  short2个字节。sizeof内部表达式不参与运算

	printf("%d", s);//5



	return 0;
}

第三个解析
在这里插入图片描述

指针笔试题
int main()
{int a[5] = {1, 2, 3, 4, 5 };
    int *ptr = (int *)(&a + 1);
    printf( "%d,%d", *(a + 1), *(ptr - 1));
    return 0;   //第一个打印:a的地址没变 指向一 加一指向2的地址
}
//程序的结果是什么?
//2  5

解析
在这里插入图片描述


//由于我还没介绍过结构体,这里告知结构体的大小是20个字节
struct Test
{int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{	printf("%p\n", p + 0x1);//相当于p+1   加1跳过一个类型 结构体类型20个字节直接跳过所以是加20  0x100000+20=0x100014   4成16的0次方。。。
	printf("%p\n", (unsigned long)p + 0x1);//0x100001   正数加1就是1  不跟指针一样
	printf("%p\n", (unsigned int*)p + 0x1);//0x100004    +4  一个整形字节
	return 0;
}

int main()
{int a[4] = {1, 2, 3, 4 };
    int* ptr1 = (int*)(&a + 1);
    int* ptr2 = (int*)((int)a + 1);// a转化为整形  一个整形4个字节   加1是加一个字节

    printf("%x,%x", ptr1[-1], *ptr2);
    return 0;
}

在这里插入图片描述
在这里插入图片描述
%x打印打印16进制 只打印有效数组所以结果为4 2000000


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

解析

#includeint main()
{int a[3][2] = {(0, 1), (2, 3), (4, 5) };//用了小括号表示是逗号表达式  相当于就放了{1,3,5}第一行放了1  3  第二行5 0 第三行00
    int* p;
    p = a[0];//没有& 也没放在sizeof内部 所以他代表首元素地址  1 放到了整形指针
    printf("%d", p[0]);//结果1      *(p+0)
    return 0;
}//a[0]表示第一行,然后没有&,也没有sizeof,所以是首元素,加起来就是a[0]这一行的首元素

int main()
{int a[5][5];
    int(*p)[4];
    p = a;//int (*)[5]
    printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    //?

    return 0;
}
int main()
{int a[5][5];
    int(*p)[4];
    p = a;//int (*)[5]
    printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    //&p[4][2] 可以理解为 (*(p+4)+2)  解引用相当于从当前位置访问一个数组  刚好int四个 然后加2

    return 0;
}

**结果FFFFFFFC,4 **

C是12

//&p[4][2] 可以理解为 (*(p+4)+2) 解引用相当于从当前位置访问一个数组p[4] 刚好int四个 然后加2
在这里插入图片描述
指针-指针 得到指针见的元素个数
在这里插入图片描述
因为地址由低到高变化小地址减去大地址所以是-4

-4以%d打印就是-4 认为内存里放的有符号整数 以%p打印认为内存里是个地址 所以将地址补码直接拿出来 因为%p所以以16进制书写 4个1是一个f如下
- 4 写到内存就是
10000000000000000000000000000000100
111111111111111111111111111111111111011
111111111111111111111111111111111111100


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));
    printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
    return 0;
}
int main()
{int aa[2][5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int* ptr1 = (int*)(&aa + 1);//10   赋给ptr1的时候他就是个整形了  下面的-1是减去一个整形  所以打印10
    int* ptr2 = (int*)(*(aa + 1));//5  对第二行解引用拿到第二行  拿到第二行相当于拿到数组名。可以写成aa[1]  他就是6的地址 本身是个整形在解引用整形无意义
    printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
    return 0;
}

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

在这里插入图片描述

int main()
{char* a[] = {"work","at","alibaba" };//数组名表示首元素地址  首元素地址表示char*   
	char** pa = a;//相当于pa指向第一个的char*
	pa++;//指向“at”的char*   pa指向数组,+1指向下一个元素
	printf("%s\n", *pa);//解引用at  从这里向后打印字符串
	return 0;
}//at

int main()
{char* c[] = {"ENTER","NEW","POINT","FIRST" };
	char** cp[] = {c + 3,c + 2,c + 1,c };
	char*** cpp = cp;

	printf("%s\n", **++cpp);
	printf("%s\n", *-- * ++cpp + 3);
	printf("%s\n", *cpp[-2] + 3);
	printf("%s\n", cpp[-1][-1] + 1);
	return 0;
}

在这里插入图片描述

在这里插入图片描述

第一次解引用拿到c+2 第二次拿到了 char*内容 所以打印 POINT

在这里插入图片描述

printf("%s\n", *-- * ++cpp + 3);//++优先级高   --就是对c+1  减去1 后变成c 如果是c 指向位置也会发生改变 再解引用拿到 ENTER 加3 指向T。从E向后打印打印结果ER

*cpp[-2]可以写成 **(cpp-2) +3指向R打印ST
在这里插入图片描述

printf("%s\n", cpp[-1][-1] + 1);//cpp[-1][-1] 可以写成 (*(*(cpp-1)-1)+1   结果EW

在这里插入图片描述

总体打印结果POINT ER ST EW

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


文章名称:C语言指针进阶学完指针必看练习题详解-创新互联
网站链接:http://pwwzsj.com/article/ihijh.html