目录
- [1. sizeof 和 strlen 的对比](#1. sizeof 和 strlen 的对比)
-
- [1.1 sizeof](#1.1 sizeof)
- [1.2 strlen](#1.2 strlen)
- [1.3 sizeof 和 strlen 的对比](#1.3 sizeof 和 strlen 的对比)
- 2.数组和指针笔试题解析
-
- [2.1 一维数组](#2.1 一维数组)
- [2.2 字符数组](#2.2 字符数组)
- [2.3 二维数组](#2.3 二维数组)
- [3. 指针运算笔试题解析](#3. 指针运算笔试题解析)
-
- [3.1 **题目1**:](#3.1 题目1:)
- [3.2 **题目2**:](#3.2 题目2:)
- [3.3 题目3](#3.3 题目3)
- [3.4 **题目4**:](#3.4 题目4:)
- [3.5 **题目5**:](#3.5 题目5:)
- [3.6 题目6:](#3.6 题目6:)
- [3.7 题目7:](#3.7 题目7:)
1. sizeof 和 strlen 的对比
1.1 sizeof
在学习C语言数据类型和变量时,我们学习了sizeof操作符,sizeof 是用来计算变量或数据类型所占内存大小的操作符,单位是字节。sizeof的返回值是size_t类型的,它只关心占用空间,不关心内存中存放的具体数据。
比如:
c
int main()
{
int n = 40;
int a = 0;
printf("%zu\n", sizeof(n)); //4
printf("%zu\n", sizeof(40)); //4
printf("%zu\n", sizeof n); //4
printf("%zu\n", sizeof(a = n + 10)); //sizeof中表达式不计算,计算结果为4
printf("%d\n", a); //0
return 0;
}
1.2 strlen
strlen 是C语⾔库函数 ,功能是求字符串⻓度。函数原型如下:
c
size_t strlen ( const char * str );
str:要统计的字符串地址。
strlen:从 str 指向的位置开始统计字符个数。
遇到 \0 停止:不统计 \0 本身。
返回值 size_t:表示字符串中有效字符的个数。
注意:strlen 是库函数,不是操作符,所以,使用strlen库函数要包含头文件<string.h>

c
#include <string.h> //使用strlen库函数时要包含头文件
#include <stdio.h>
int main()
{
char arr1[3] = { 'a', 'b', 'c' };
char arr2[] = "abc";
printf("%d\n", strlen(arr1)); // arr1 中没有 '\0',strlen 会继续向后查找,可能越界访问,结果未定义
printf("%d\n", strlen(arr2)); //3
printf("%d\n", sizeof(arr1)); //3
//arr1是字符数组,存储了'a' , 'b' , 'c' 三个字符
printf("%d\n", sizeof(arr2));//4
// arr2 存储 'a','b','c','\0',占 4 个字节
return 0;
}
1.3 sizeof 和 strlen 的对比
| 对比项 | sizeof | strlen |
|---|---|---|
| 本质 | 操作符 | 库函数 |
| 头文件 | 不需要额外头文件 | 需要包含头文件 <string.h> |
| 作用 | 计算变量或类型占用的内存大小 | 计算字符串的长度 |
| 统计内容 | 统计所占内存的字节数 | 统计 \0 之前字符的个数 |
| 单位 | 字节 | 字符个数 |
| 是否关注内容 | 不关心内存中存放什么数据 | 需要查找字符串结束标志 \0 |
| 注意事项 | 结果由变量或类型本身决定 | 如果没有 \0,可能会越界查找 |
2.数组和指针笔试题解析
讲解之前我们需要知道数组名的意义 ,数组名的意义在C语言指针深入浅出3中讲解到了,我把最核心的知识挪到这里:
- sizeof(数组名),这⾥的数组名表⽰整个数组 ,计算的是整个数组的⼤⼩。
- &数组名,这⾥的数组名表⽰整个数组 ,取出的是整个数组的地址。
- 除此之外所有的数组名都表⽰⾸元素的地址。
2.1 一维数组
c
#include <stdio.h>
int main()
{
int a[] = { 1, 2, 3, 4 };
printf("%zu\n", sizeof(a));
printf("%zu\n", sizeof(a + 0));
printf("%zu\n", sizeof(*a));
printf("%zu\n", sizeof(a + 1));
printf("%zu\n", sizeof(a[1]));
printf("%zu\n", sizeof(&a));
printf("%zu\n", sizeof(*&a));
printf("%zu\n", sizeof(&a + 1));
printf("%zu\n", sizeof(&a[0]));
printf("%zu\n", sizeof(&a[0] + 1));
return 0;
}


2.2 字符数组
代码1:
c
#include <stdio.h>
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%zu\n", sizeof(arr));
printf("%zu\n", sizeof(arr + 0));
printf("%zu\n", sizeof(*arr));
printf("%zu\n", sizeof(arr[1]));
printf("%zu\n", sizeof(&arr));
printf("%zu\n", sizeof(&arr + 1));
printf("%zu\n", sizeof(&arr[0] + 1));
return 0;
}


代码2:
c
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
printf("%zu\n", strlen(arr));
printf("%zu\n", strlen(arr + 0));
printf("%zu\n", strlen(*arr));
printf("%zu\n", strlen(arr[1]));
printf("%zu\n", strlen(&arr));
printf("%zu\n", strlen(&arr + 1));
printf("%zu\n", strlen(&arr[0] + 1));
return 0;
}


代码3:
c
#include <stdio.h>
int main()
{
char arr[] = "abcdef";
printf("%zu\n", sizeof(arr));
printf("%zu\n", sizeof(arr + 0));
printf("%zu\n", sizeof(*arr));
printf("%zu\n", sizeof(arr[1]));
printf("%zu\n", sizeof(&arr));
printf("%zu\n", sizeof(&arr + 1));
printf("%zu\n", sizeof(&arr[0] + 1));
return 0;
}


代码4:
c
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "abcdef";
printf("%zu\n", strlen(arr));
printf("%zu\n", strlen(arr + 0));
printf("%zu\n", strlen(*arr));
printf("%zu\n", strlen(arr[1]));
printf("%zu\n", strlen(&arr));
printf("%zu\n", strlen(&arr + 1));
printf("%zu\n", strlen(&arr[0] + 1));
return 0;
}


代码5:
c
#include <stdio.h>
int main()
{
char* p = "abcdef";
printf("%zu\n", sizeof(p));
printf("%zu\n", sizeof(p + 1));
printf("%zu\n", sizeof(*p));
printf("%zu\n", sizeof(p[0]));
printf("%zu\n", sizeof(&p));
printf("%zu\n", sizeof(&p + 1));
printf("%zu\n", sizeof(&p[0] + 1));
return 0;
}


代码6:
c
#include <stdio.h>
#include <string.h>
int main()
{
const char* p = "abcdef";
printf("%zu\n", strlen(p));
printf("%zu\n", strlen(p + 1));
printf("%zu\n", strlen(*p));
printf("%zu\n", strlen(p[0]));
printf("%zu\n", strlen(&p));
printf("%zu\n", strlen(&p + 1));
printf("%zu\n", strlen(&p[0] + 1));
return 0;
}


2.3 二维数组
c
#include <stdio.h>
int main()
{
int a[3][4] = {0};
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[3]));
return 0;
}


3. 指针运算笔试题解析
3.1 题目1:
c
#include <stdio.h>
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int* ptr = (int*)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));
return 0;
}


3.2 题目2:
这个题目的是指针的+ -运算,相关知识点:C语言指针深入浅出1。
注意:注意:%p 用于打印指针地址,通常以十六进制形式显示;在 VS 的 x86 环境下,一般显示为 8 位十六进制,不足位会补 0。
c
#include <stdio.h>
//在X86环境下 1
//假设结构体的⼤⼩是20个字节
//程序输出的结果是啥?
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}* p = (struct Test*)0x100000;
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}


3.3 题目3
这道题用到了逗号表达式 ,相关知识点:C语言操作符详解。
c
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int* p;
p = a[0];
printf("%d", p[0]);
return 0;
}


3.4 题目4:
c
#include <stdio.h>
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}


我再来讲解一下FFFFFFFC怎么来的:
相关知识点:C语言操作符详解。
在 VS 的 x86 环境下,-4 用 32 位补码表示:
c
-4 的二进制:
10000000 00000000 00000000 00000100
取反(符号位不变,其他位按位取反):
11111111 11111111 11111111 11111011
加 1:
11111111 11111111 11111111 11111100
把最后一行按 4 位一组转成十六进制:
c
1111 1111 1111 1111 1111 1111 1111 1100
F F F F F F F C
-4 的 32 位补码 = 0xFFFFFFFC。
3.5 题目5:
c
#include <stdio.h>
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;
}


3.6 题目6:
c
#include <stdio.h>
int main()
{
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}


3.7 题目7:
c
#include <stdio.h>
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;
}

完