【C语言】经典指针笔试题(深度解剖)(下)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【C语言】经典指针笔试题(深度解剖)(下)


    char arr[] = "abcdef";
  printf("%d\n", strlen(arr));
  printf("%d\n", strlen(arr + 0));
  printf("%d\n", strlen(*arr));
  printf("%d\n", strlen(arr[1]));
  printf("%d\n", strlen(&arr));
  printf("%d\n", strlen(&arr + 1));
  printf("%d\n", strlen(&arr[0] + 1));


解析:char arr[] = “abcdef”;

注意!现在arr是一个字符串,后面默认放着一个\0的相当于是[ abcdef\0 ]


printf(“%d\n”, strlen(arr));

strlen计算 \0之前出现的字符个数,答案是->6


printf(“%d\n”, strlen(arr + 0));

arr+0 还是首元素地址,首元素地址往后面找\0,答案是->6


printf(“%d\n”, strlen(*arr));

strlen函数的参数只能计算指针或者地址,如果解引用 * arr相当于把字符’a’ASCll当成地址了,这个时候程序会崩溃的,代码会报错的 答案是->(代码错误error)


printf(“%d\n”, strlen(arr[1]));

同上题道理一样, * arr【1】把字符’b’ASCll当成地址了,程序会崩溃的,代码会报错的 答案是->(代码错误error)


printf(“%d\n”, strlen(&arr));

&arr指向第一个元素地址先,向后找\0 答案->6

(&arr = char (*)[7] 数组指针)


printf(“%d\n”, strlen(&arr + 1));

&arr一开始指向第一个元素地址,&arr+1跳过arr整个数组大小,等于指向了/0后面的位置

指向了\0后,因为不知道\0的位置,所以是随机值 答案->随机值

a6fd7c6eb390457eaa0e2d474f2505c6.png


printf(“%d\n”, strlen(&arr[0] + 1));

&arr[0] +1 是第二个元素地址,从第二个元素地址后开始找\0,答案是->5

092e8abfb8fa4fb4893ca5d6e5ab1b52.png


    char* p = "abcdef";
  printf("%d\n", sizeof(p));
  printf("%d\n", sizeof(p + 1));
  printf("%d\n", sizeof(*p));
  printf("%d\n", sizeof(p[0]));
  printf("%d\n", sizeof(&p));
  printf("%d\n", sizeof(&p + 1));
  printf("%d\n", sizeof(&p[0] + 1));


解析: char* p = “abcdef”;

内存部图大概是这样的

6aafbf5733df4a9ca115851e9b623f85.png


printf(“%d\n”, sizeof ( p ));

p是一个指针变量,sizeof(p)计算的是指针变量的大小,该指针变量存的是地址,地址大小4/8个字节,答案是->4/8个字节.


printf(“%d\n”, sizeof(p + 1));

p存放的是首元素a的地址,a的地址+1,char*指针+1跳过一个字符,其实是b的地址,地址是4/8个字节,答案是->4/8个字节.


printf(“%d\n”, sizeof(*p));

p存放的是首元素地址,解引用拿到的就是首元素a,答案是->1


printf(“%d\n”, sizeof(p[0]));

同样拿到的也是首元素a,答案是->1


printf(“%d\n”, sizeof(&p));

&p拿到的是p空间的地址,跟abcdef那一块地址没有关系!地址4/8个字节,答案是4 / 8

(p–char*) (&p --char**)

(写成代码是这样的char* p; , char**pp = &p)

(&p其实是一个二级指针指向了那一块p空间,因为那一块是char*一级的)

729ee8947c8d456e80eff8bae6db34d2.png


printf(“%d\n”, sizeof(&p + 1));

&p+1跳过p的地址,终究还是个地址,地址4/8个字节,答案是->4/8

b544d83244ca46cfae503565247bc27c.png


printf(“%d\n”, sizeof(&p[0] + 1));

&p[0]取出第一个元素地址+1,跳过一个字符,等于b的地址,地址4/8个字节,答案是->4 / 8


    char* p = "abcdef";
  printf("%d\n", strlen(p));
  printf("%d\n", strlen(p + 1));
  printf("%d\n", strlen(*p));
  printf("%d\n", strlen(p[0]));
  printf("%d\n", strlen(&p));
  printf("%d\n", strlen(&p + 1));
  printf("%d\n", strlen(&p[0] + 1));


解析: char* p = “abcdef”;


printf(“%d\n”, strlen( p));

p代表首元素a的地址,strlen遇到 \0 才会停止,答案是-> 6


printf(“%d\n”, strlen(p + 1));

p+1是’b’的地址 ,strlen从b的位置向后找 ’ \0 ’ 答案是->5


printf(“%d\n”, strlen(*p));

strlen函数的参数只能计算指针或者地址,如果解引用 * p相当于把字符’a’ASCll当成地址了,造成非法访问,这个时候程序会崩溃的,代码会报错的 答案是->(代码错误error)


printf(“%d\n”, strlen(p[0]))

跟上面题一样 p[0]等于把第一个元素解引用,把ASCll当成地址了,造成非法访问,程序会崩溃的,代码会报错 答案是->(代码错误error)


printf(“%d\n”, strlen(&p));

&p是拿到了p那一块空间的地址,并不是abcdef那一块空间,p那一块空间 不知道\0的位置,所以也是随机值 答案->随机值

caa1aac1e7aa41a2a057e7b254414bb2.png


printf(“%d\n”, strlen(&p + 1));

&p + 1把整个p空间那块数组跳过去了,跳过p一块空间,更不能预测\0的位置,所以也是随机值 答案->随机值

(&p 和 &p+1 没有任何关系,因为:可能p那块空间里面有\0,&p+1跳过p那一块数组,可能半天都找不到\0)

d970c1eeb63041ce9de80ff51e16f4ca.png


printf(“%d\n”, strlen(&p[0] + 1));

&p[0]+1是’b’的地址 从b的地址往后找\0 答案是->5


int a[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
  printf("%d\n", sizeof(a));
  printf("%d\n", sizeof(a[0][0]));
  printf("%d\n", sizeof(a[0]));
  printf("%d\n", sizeof(a[0] + 1));
  printf("%d\n", sizeof(*(a[0] + 1)));
  printf("%d\n", sizeof(a + 1));
  printf("%d\n", sizeof(*(a + 1)));
  printf("%d\n", sizeof(&a[0] + 1));
  printf("%d\n", sizeof(*(&a[0] + 1)));
  printf("%d\n", sizeof(*a));
  printf("%d\n", sizeof(*a+1));
  printf("%d\n", sizeof(a[3]));


解析:int a[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };


printf(“%d\n”, sizeof(a));

数组名单独发放在sizeof内部,计算的是整个数组的大小。答案是->48


printf(“%d\n”, sizeof(a[0][0]));

a[0][0]是第一行第一个元素,答案是->4


printf(“%d\n”, sizeof(a[0]));

第一行的数组名,这时数组名单独放在sizeof内部了,计算的是数组的大小,单位是字节,答案是->16


printf(“%d\n”, sizeof(a[0] + 1));

a[0]作为数组并没有单独放在sizeof内部,也没取地址,所以此时的a[0]就是第一行第一个元素的地址 - &a[0][0] , a[0] + 1 是第一行第2个元素的地址 &a[0][1] . 地址大小是4/8个字节 , 答案是->4 / 8


printf(“%d\n”, sizeof(*(a[0] + 1)));

此题跟上题一样,只是解引用了 *(&a[0][1]),第一行第二个元素,大小是4个字节 , 答案-> 4


printf(“%d\n”, sizeof(a + 1));

a作为二维数组的数组名并非单独放在sizeof内部,所以表示的是首元素地址,二维数组首元素地址即是第一行的地址->( int (*)[4])-> &(a[0]),a+1是跳过第一行,指向了第二行地址->(&a[1]) , 地址大小是 4/8,单位是字节, 答案是->4/8


printf(“%d\n”,sizeof(*(a+1)));

此题跟上题类似,只是把第二行地址解引用了 (a[1]) ,计算第二行的大小,单位是字节,答案是->16


printf(“%d\n”, sizeof(&a[0] + 1));

&a[0]是第一行的地址 , &a[0]+1跳过第一行,既是第二行的地址。地址大小是 4/8,单位是字节, 答案是->4/8


printf(“%d\n”, sizeof(*(&a[0] + 1)));

a[0]+1,既是第二行数组 a[1],计算第二行的大小,单位是字节,答案是->16


printf(“%d\n”, sizeof(*a));

a是首元素地址-第一行的地址,*a就是第一行,sizeof(*a)就是计算第一行的大小,答案是->16


printf(“%d\n”, sizeof(*a+1));

a没有单独放在sizeof()内部,既表示的是首元素的地址,二维数组首元素地址即是第一行的地址->&a[0], 解引用即是第一行a[0], 但第一行a[0]加1了,他又不是单独放在sizeof()内部了,这时a[0]又变成首元素地址了->&a[0][0]的地址,在+1变成第一行第二个元素地址->&a[0][1],地址是4/8个字节,答案->4/8


printf(“%d\n”, sizeof(a[3]));

可能大多数人跟我一样,哎刚开始看见a[3]不是造成越界访问了吗? 但答案并非如此!!

sizeof里面的表达式不参与真正的运算,只是根据他的类型属性计算他的大小,他不会真正访问a[3]这行 ,a[3]为第四行所有元素,大小为16,所以答案是->16

(sizeof只会根据他的类型来计算)

5afa86967fe7402ba1a462ddf8bdaa44.png


3:总结



如果不是单独放在sizeof()内部,一般的操作都会使指针降一阶

目录
相关文章
|
1月前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
92 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
1月前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
59 9
|
1月前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
46 7
|
2月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
169 13
|
2月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
2月前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
145 3
|
2月前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
2月前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
45 1
|
2月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
2月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。