【指针三:穿越编程边界的超能力】(上)

简介: 【指针三:穿越编程边界的超能力】

本章重点


       9.指针和数组面试题的解析

       10. 指针笔试题


九、指针和数组面试题的解析


1、一维数组的sizeof


#include<stdio.h>
int main()
{
  int a[] = { 1,2,3,4 };
  printf("%d\n", sizeof(a));
  printf("%d\n", sizeof(a + 0));
  printf("%d\n", sizeof(*a));
  printf("%d\n", sizeof(a + 1));
  printf("%d\n", sizeof(a[1]));
  printf("%d\n", sizeof(&a));
  printf("%d\n", sizeof(*&a));
  printf("%d\n", sizeof(&a + 1));
  printf("%d\n", sizeof(&a[0]));
  printf("%d\n", sizeof(&a[0] + 1));
  return 0;
}


数组名就是数组首元素的地址


   两个特殊情况:


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

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


printf("%d\n", sizeof(a));

特殊情况1,计算整个数组的大小,4 * 4 = 16


printf("%d\n", sizeof(a + 0));

数组名不是单独出现,a/(a + 0)表示数组首元素的地址,地址就是指针,4/8


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

数组名不是单独出现,*a表示数组首元素,首元素类型是整型,4


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

数组名不是单独出现,a表示数组首元素地址,a + 1第二个元素的地址,4/8


printf("%d\n", sizeof(a[1]));

a[1]表示数组的第二个元素,该元素的数据类型是整型,4


printf("%d\n", sizeof(&a));

特殊情况2,数组名表示整个数组,取出的是整个数组的地址,地址是指针,4/8


printf("%d\n", sizeof(*&a));

解法一:sizeof(*&a) <==> sizeof(a),16


解法二:&a -> int(*p)[4]数组指针 - 解引用*访问的就是数组,16


printf("%d\n", sizeof(&a + 1));

&a取出的是整个数组的地址,&a+1是跳过这个数组的地址,地址是指针,4/8


printf("%d\n", sizeof(&a[0]));

&a[0])获取的是数组首元素的地址,地址是指针,4/8


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

&a[0])获取的是数组首元素的地址,&a[0] + 1获取的是数组第二元素的地址,地址是指针,4/8    


代码图解



运行结果



2、字符数组的sizeof和strlen


#include<stdio.h>
#include<string.h>
int main()
{
  char arr[] = { 'a','b','c','d','e','f' };
  printf("%d\n", sizeof(arr));
  printf("%d\n", sizeof(arr + 0));
  printf("%d\n", sizeof(*arr));
  printf("%d\n", sizeof(arr[1]));
  printf("%d\n", sizeof(&arr));
  printf("%d\n", sizeof(&arr + 1));
  printf("%d\n", sizeof(&arr[0] + 1));
  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));
  return 0;
}


数组名就是数组首元素的地址


   两个特殊情况:


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

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


printf("%d\n", sizeof(arr));

数组名单独放在sizeof内部,arr表示整个数组,计算整个数组的大小,6 * sizeof(char) = 6


printf("%d\n", sizeof(arr + 0));

数组名不是单独出现,arr/(arr + 0)表示数组首元素的地址,地址就是指针,4/8


printf("%d\n", sizeof(*arr));

数组名不是单独出现,*arr表示数组首元素,首元素类型是字符型,1


printf("%d\n", sizeof(arr[1]));

arr[1]表示第二个字符,数据类型是字符型,1


printf("%d\n", sizeof(&arr));

数组名表示整个数组,&arr取出的是整个数组的地址,地址是指针,4/8


printf("%d\n", sizeof(&arr + 1));

&arr取出的是整个数组的地址,&arr+1是跳过这个数组的地址,地址是指针,4/8


printf("%d\n", sizeof(&arr[0] + 1));

&arr[0]是取出第一个字符的地址,&arr[0]+1是取出第二个字符的地址,地址就是指针,4/8


strlen统计的是在字符串中\0之前的字符的个数,如果没有\0,就会一直往后找

printf("%d\n", strlen(arr));

字符数组arr中没有\0,所以求字符串长度就会一直往后找,随机值


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

arr+0是首元素的地址,字符数组arr中没有\0,所以求字符串长度就会一直往后找,随机值


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

strlen(参数是地址),*arr是首元素-'a'-对应的ASCII码值为97,把97当作地址,非法访问,error


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

arr[1] - 'b' - 对应的ASCII码值为98,把98当作地址传参,非法访问,error


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

&arr取出的是整个数组的地址,&arr的类型数组指针char(*)[6]


strlen(const char *str)类型是字符指针,此时会发生数组指针转为字符指针的一个过程

传过去的值不会发生改变,只是类型发生改变


数组的地址和首元素的地址是一样滴,传递给strlen函数后,依然是从数组的第一个元素的位置寻找\0,所以大小仍然是随机值

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


&arr+1是跳过这个数组的地址,从数组的第七个元素的位置寻找\0,随机值,比strlen(&arr)小6

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


&arr[0]+1是取出第二个字符的地址,从数组的第二个元素的位置寻找\0,随机值,比strlen(&arr)小1


代码图解



运行结果:



#include<stdio.h>
#include<string.h>
int main()
{
  char arr[] = "abcdef";
  printf("%d\n", sizeof(arr));
  printf("%d\n", sizeof(arr + 0));
  printf("%d\n", sizeof(*arr));
  printf("%d\n", sizeof(arr[1]));
  printf("%d\n", sizeof(&arr));
  printf("%d\n", sizeof(&arr + 1));
  printf("%d\n", sizeof(&arr[0] + 1));
  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));
  return 0;
}


数组名就是数组首元素的地址


   两个特殊情况:


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

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


char arr[] = "abcdef";//这种写法数组的内容是[a b c d e f \0]

printf("%d\n", sizeof(arr));

数组名单独放在sizeof内部,arr表示整个数组,计算整个数组的大小,7 * sizeof(char) = 7


printf("%d\n", sizeof(arr + 0));

数组名不是单独出现,arr/(arr + 0)表示数组首元素的地址,地址就是指针,4/8


printf("%d\n", sizeof(*arr));

数组名不是单独出现,*arr表示数组首元素,首元素类型是字符型,1


printf("%d\n", sizeof(arr[1]));

arr[1]表示第二个字符,数据类型是字符型,1


printf("%d\n", sizeof(&arr));

数组名表示整个数组,&arr取出的是整个数组的地址,地址是指针,4/8


printf("%d\n", sizeof(&arr + 1));

&arr取出的是整个数组的地址,&arr+1是跳过这个数组的地址,地址是指针,4/8


printf("%d\n", sizeof(&arr[0] + 1));

&arr[0]是取出第一个字符的地址,&arr[0]+1是取出第二个字符的地址,地址就是指针,4/8


strlen统计的是在字符串中\0之前的字符的个数,如果没有\0,就会一直往后找

printf("%d\n", strlen(arr));

字符数组arr中有\0,字符串长度是\0之前的字符,不包括\0,6


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

arr+0是首元素的地址,字符数组arr中有\0,字符串长度是\0之前的字符,不包括\0,6


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

strlen(参数是地址),*arr是首元素-'a'-对应的ASCII码值为97,把97当作地址,非法访问,error


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

arr[1] - 'b' - 对应的ASCII码值为98,把98当作地址传参,非法访问,error


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

&arr取出的是整个数组的地址,&arr的类型数组指针char(*)[6]


strlen(const char *str)类型是字符指针,此时会发生数组指针转为字符指针的一个过程

传过去的值不会发生改变,只是类型发生改变


数组的地址和首元素的地址是一样滴,传递给strlen函数后,依然是从数组的第一个元素的位置寻找\0,字符数组arr中有\0,字符串长度是\0之前的字符,不包括\0,6


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

&arr+1是跳过这个数组的地址,从数组的第八个元素的位置寻找\0,随机值


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

&arr[0]+1是取出第二个字符的地址,从数组的第二个元素的位置寻找\0,5


代码图解:



运行结果:


#include<stdio.h>
int main()
{
  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));
  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));
  return 0;
}


【指针三:穿越编程边界的超能力】(下):https://developer.aliyun.com/article/1424758

相关文章
|
6月前
|
C++
【编码狂想】指针航行,链表魔法,解锁结构体和类的编程幻境
【编码狂想】指针航行,链表魔法,解锁结构体和类的编程幻境
83 1
|
6月前
|
算法 Linux C语言
【Linux系统编程】深入理解Linux目录操作:文件夹位置指针操作函数(telldir,seekdir,rewinddir)
【Linux系统编程】深入理解Linux目录操作:文件夹位置指针操作函数(telldir,seekdir,rewinddir)
78 0
|
5月前
|
存储 安全 编译器
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
66 5
|
6月前
|
C语言
文件类型指针及其在编程中的应用
文件类型指针及其在编程中的应用
99 0
|
6月前
|
存储 编译器 C语言
数组指针,高效编程之道
数组指针,高效编程之道
|
6月前
【错题集-编程题】dd爱框框(同向双指针 / 滑动窗口)
【错题集-编程题】dd爱框框(同向双指针 / 滑动窗口)
|
6月前
|
C语言
C语言进阶⑬(字符串函数)+(指针编程题)strlen+strcpy+strcat+strstr+strtok+strerror(下)
C语言进阶⑬(字符串函数)+(指针编程题)strlen+strcpy+strcat+strstr+strtok+strerror
27 0
|
6月前
|
安全 C语言
C语言进阶⑬(字符串函数)+(指针编程题)strlen+strcpy+strcat+strstr+strtok+strerror(中)
C语言进阶⑬(字符串函数)+(指针编程题)strlen+strcpy+strcat+strstr+strtok+strerror
42 0
|
6月前
|
C语言
C语言进阶⑬(字符串函数)+(指针编程题)strlen+strcpy+strcat+strstr+strtok+strerror(上)
C语言进阶⑬(字符串函数)+(指针编程题)strlen+strcpy+strcat+strstr+strtok+strerror
31 0
|
6月前
|
存储 编译器 程序员
【C/C++ this指针 20240105更新】探索C++编程之旅:深入理解this指针的魅力与应用
【C/C++ this指针 20240105更新】探索C++编程之旅:深入理解this指针的魅力与应用
80 0
下一篇
无影云桌面