C语言指针经典面试题——第一弹

简介: 笔记
#include<stdio.h>
int main()
{
  int a[] = { 1,2,3,4 };
  printf("%d\n", sizeof(a));
  //结果是16,这里算的是整个数组
  printf("%d\n", sizeof(a + 0));
  //结果是4或8,这里算的是第一个地址的大小
  printf("%d\n", sizeof(*a));
  //结果是4,这里算的是首元素大小
  printf("%d\n", sizeof(a + 1));
  //结果是4或8,这里算的是第二个地址的大小
  printf("%d\n", sizeof(a[1]));
  //结果是4,这里算的是第二个元素的大小
  printf("%d\n", sizeof(&a));
  //结果是4或8,这里算的是整个数组的地址大小
  printf("%d\n", sizeof(*&a));
  //结果是16,这里先是取出整个数组地址,然后对整个数组解引用,也就是算出的是整个数组的大小
  printf("%d\n", sizeof(&a + 1));
  //结果是4或8,这里跳过了整个数组,计算数组后面的地址大小,所以是4或8,&a的类型是int(*)[4]
  printf("%d\n", sizeof(&a[0]));
  //结果是4或8,这里算的是第一个元素的地址大小
  printf("%d\n", sizeof(&a[0] + 1));
  //结果是4或8,这里算的是第二个元素的地址大小
  return 0;
}

注意:这里&a的类型是int(*)[4],数组指针,1.png

&a+1是跳过整个数组

sizeof()和char型一维数组


  char arr[] = { 'a','b','c','d','e','f' };
  printf("%d\n", sizeof(arr));
  //6,这里计算的是整个数组
  printf("%d\n", sizeof(arr + 0));
  //4或8,这里计算的是第一个元素的地址
  printf("%d\n", sizeof(*arr));
  //1,这里计算的是第一个元素的大小
  printf("%d\n", sizeof(arr[1]));
  //1,哲理计算的是第二个元素的大小
  printf("%d\n", sizeof(&arr));
  //4或8,这里计算的是整个数组的地址大小
  printf("%d\n", sizeof(&arr + 1));
  //还是4或8,这里计算的是跳过整个数组之后,整个地址的大小
  printf("%d\n", sizeof(&arr[0] + 1));
  //还是4或8,这里计算的是第二个元素的地址大小

strlen和char型一维数组


  char arr[] = { 'a','b','c','d','e','f' };
  printf("%d\n", strlen(arr));
  //随机值,这里计算的是整个数组,即从第一个元素开始往后计算直到找到\0位置,随机值是因为这个数组里面没有\0
  printf("%d\n", strlen(arr + 0));
  //随机值,这里strlen是从第一个元素开始往后数,随机值的值跟上面的值一样
  printf("%d\n", strlen(*arr));
  //报错,这里传的是第一个元素,第一个元素是一个值,strlen()括号里面的必须是char *类型的指针变量,而这里面的元素是char类型不是char *类型,若把'a'传过去,则相当于把97当作指针穿了过去
  printf("%d\n", strlen(arr[1]));
  //报错,传的是第二个元素,跟上面的值一样
  printf("%d\n", strlen(&arr));
  //随机值,跟前面一样,传的是整个地址,整个地址是从第一个元素的地址开始的,随意会产生随机值,由于是从第一个元素开始,所以产生的结果会跟第一个一样
  printf("%d\n", strlen(&arr + 1));
  //随机值,这里是跳过了整个数组,然后开始计算,遇到\0便停止,跟第一个随机值相差6
  printf("%d\n", strlen(&arr[0] + 1));
  //随机值,从第二个元素的地址开始计算,遇到\0停止,跟第一个随机值相差1

sizeof()和字符串数组


  char arr[] = "abcdef";
  printf("%d\n", sizeof(arr));
  //7,有\0
  printf("%d\n", sizeof(arr + 0));
  //4或8,计算的是地址大小,从第一个元素的地址开始计算
  printf("%d\n", sizeof(*arr));
  //1,计算的是是第一个元素的大小
  printf("%d\n", sizeof(arr[1]));
  //1,计算的是第二个元素的大小
  printf("%d\n", sizeof(&arr));
  //4或8,计算的是整个地址
  printf("%d\n", sizeof(&arr + 1));
  //4或8,跳过这个数组后,计算后面的地址大小
  printf("%d\n", sizeof(&arr[0] + 1));
  //4或8,跳过第一个元素后,计算后面的地址大小,而不是数组里面的内容大小

sizeof和字符串数组


  char arr[] = "abcdef";
  printf("%d\n", sizeof(arr));
  //7,有\0
  printf("%d\n", sizeof(arr + 0));
  //4或8,计算的是地址大小,从第一个元素的地址开始计算
  printf("%d\n", sizeof(*arr));
  //1,计算的是是第一个元素的大小
  printf("%d\n", sizeof(arr[1]));
  //1,计算的是第二个元素的大小
  printf("%d\n", sizeof(&arr));
  //4或8,计算的是整个地址
  printf("%d\n", sizeof(&arr + 1));
  //4或8,跳过这个数组后,计算后面的地址大小
  printf("%d\n", sizeof(&arr[0] + 1));
  //4或8,跳过第一个元素后,计算后面的地址大小,而不是数组里面的内容大小

strlen和字符串


  char arr[] = "abcdef";
  printf("%d\n", strlen(arr));
  //6,遇到\0停止打印
  printf("%d\n", strlen(arr + 0));
  //6,遇到\0停止打印
  printf("%d\n", strlen(*arr));
  //报错,传的不是char *类型
  printf("%d\n", strlen(arr[1]));
  //报错,穿的不是char*类型
  printf("%d\n", strlen(&arr));
  //6,传的是整个数组地址,从第一个元素的地址开始
  printf("%d\n", strlen(&arr + 1));
  //随机值,跨过整个数组之后,开始计算遇到\0停止
  printf("%d\n", strlen(&arr[0] + 1));
  //5,从第二个元素开始计算,遇到\0停止

字符指针和sizeof()


  char* p = "abcdef";
  printf("%d\n", sizeof(p));
  //4或8,这里的p是指针,p里面村的是第一个元素的地址,
  printf("%d\n", sizeof(p + 1));
  //4或8,指向第二个元素的地址
  printf("%d\n", sizeof(*p));
  //1,第一个元素的大小
  printf("%d\n", sizeof(p[0]));
  //1,第一个元素的大小
  printf("%d\n", sizeof(&p));
  //4或8,&p是二级指针
  printf("%d\n", sizeof(&p + 1));
  //4或8,跨过了整个数组
  printf("%d\n", sizeof(&p[0] + 1));
  //4或8,从第二个元素开始计算地址的大小

字符指针和strlen()


  char* p = "abcdef";
  printf("%d\n", strlen(p));
  //6,p是首元素地址
  printf("%d\n", strlen(p + 1));
  //5,从第二个元素开始计算
  printf("%d\n", strlen(*p));
  //报错,因为穿的是一个值,不是char *类型的
  printf("%d\n", strlen(p[0]));
  //报错,传的是一个值,不是char *类型的
  printf("%d\n", strlen(&p));
  //随机值,p是一个一级指针,&p就是一个二级指针,也就是说这里的strlen是从p的地址开始向后数的遇到\0停止
  printf("%d\n", strlen(&p + 1));
  //随机值,跨过了整个数组,然后开始计算遇到\0位置
  printf("%d\n", strlen(&p[0] + 1));
  //随机值,从第一个元素开始计算遇到\0为止,这个和上面的相差的数字也是随机值,不是一个确定的数,因为他们遇到\0的情况不相同
  //倒数第二个和倒数第一个相差的值,是一个随机值,因为&p是从p的地址开始数,当没到&p[0]+1时,可能会出现\0也有可能不会出现\0,而&p[0]+1,时从第二个元素的地址开始数,什么时候遇到\0则说不准

4.png3.png

&p+1和&p[0]+1结果相差为随机值的原因,有可能在p[0]+1往右移动且没到达&p+1的时候遇到\0,也有可能会和&p+1遇到同一个\0,由于这里的\0具有不确定性,所以他们俩者相差的就是一个随机值。

二维数组和sizeof()


int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
//48,这里计算的是整个数组的大小
printf("%d\n", sizeof(a[0][0]));
//4,这里计算第一个元素的大小
printf("%d\n", sizeof(a[0]));
//16,a[0]第一行元素的大小
printf("%d\n", sizeof(a[0] + 1));
//4/8,这里的a[0]不再单独放在()内部,有+1的操作,所以这里的a[0]表示首元素的地址,+1就表示第二个元素地址的大小,所以这里的是地址
printf("%d\n", sizeof(*(a[0] + 1)));
//4,这个是第一行,第二个元素的大小
printf("%d\n", sizeof(a + 1));
//4/8,a有+1的操作,所以a表示首元素地址,即第一行,a+1就是第二行的地址,由于算的是地址所以是4/8
printf("%d\n", sizeof(*(a + 1)));
//16,第二行元素的大小
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就是解引用,所以是16
printf("%d\n", sizeof(a[3]));
//16,这里并没有越界,因为他没有去访问第四行

总结


数组名的意义:


1. sizeof( 数组名 ) ,这里的数组名表示整个数组,计算的是整个数组的大小。

2. & 数组名,这里的数组名表示整个数组,取出的是整个数组的地址。

3. 除此之外所有的数组名都表示首元素的地址。


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