深挖C语言:深入理解指针(6)

📅 2026/8/19 22:22:15
深挖C语言:深入理解指针(6)
目录1.sizeof 和 strlen 的对比2.函数和指针笔试题目解析3.指针运算笔试题解析正文1.sizeof 和 strlen 的对比sizeof 计算变量所占内存空间的大小单位字节如果操作数是类型计算的是类型创建的变量所占内存空间的大小。sizeof 只关注占用内存空间的大小并不会真实的去运算操作数不在乎内存中放了什么数据。例如#includestdio.h int main() { int a 0; printf(%zu\n,sizeof(a)); // 4 printf(%zu\n,sizeof a );// 4 printf(%zu\n,sizeof(int));// 4 return 0; }strlen 是C语言库函数用来计算字符串或字符数组的长度。#includestring.h size_t strlen(const char* str);运算原理是从 str 中这个地址往后\0 之前字符串的个数strlen 函数会一直i选哪个后找直到找到 \0 为止所以存在越界查找。sizeof 和 strlen 的对比图sizeofstrlen1.sizeof是操作符1.strlen是库函数使用需要包含头文件string.h2.sizeof计算操作数所占内存的大小单位是字节2.strlen是求字符串长度的统计的是\0之前字符的个数3.不关注内存中存放什么数据3.会关注是否有\0如果没有就持续向后找可能会越界2.函数和指针笔试题目解析知识点补充数组名的意义1.sizeof(数组名)这里数组名表示整个数组计算的是整个数组的大小。2.数组名这里的数组名表示整个数组取出的是整个数组的地址。3.除此之外所有的数组名都表示首元素的地址。一维数组不带有 \0 sizeof:#includestdio.h int main() { int a[] {1,2,3,4}; printf(%zu\n,sizeof(a));// 16 计算整个数组的内存大小 printf(%zu\n,sizeof(a0));// 4/8 计算首元素地址的大小 printf(%zu\n,sizeof(*a));// 4 计算首元素内存的大小 printf(%zu\n,sizeof(a1));// 4/8 计算第二个元素地址的大小 printf(%zu\n,sizeof(a));// 4/8 计算整个数组地址的大小 printf(%zu\n,sizeof(*a));// 16 计算整个数组的内存大小 printf(%zu\n,sizeof(a1));// 4/8 计算的依旧是地址的内存大小 printf(%zu\n,sizeof(a[0]));// 4/8 计算的是首元素地址的大小 printf(%zu\n,sizeof(a[0]1));// 4/8 计算的是第二个元素地址的大小 return 0; }字符数组sizeof:#includestdio.h int main() { char arr[] {a,b,c,d,e,f}; printf(%zu\n,sizeof(arr));// 6 计算的是整个数组的内存大小 printf(%zu\n,sizeof(arr0));// 4/8 计算的是数组首元素地址的大小 printf(%zu\n,sizeof(*arr));// 1 计算的是首元素的内存大小 printf(%zu\n,sizeof(arr[1]));// 1 计算的是第二个元素的内存大小 printf(%zu\n,sizeof(arr));// 4/8 计算的是整个数组地址的大小 printf(%zu\n,sizeof(arr1));// 4/8 计算的是地址的大小 printf(%zu\n,sizeof(arr[0]1));// 4/8 计算的是第二个元素地址的大小 return 0; }strlen:#includestdio.h #includestring.h int main() { char arr[] {a,b,c,d,e,f}; printf(%zu\n,strlen(arr));// 未知数 没有 \0 printf(%zu\n,strlen(arr0));// 未知数 printf(%zu\n,strlen(*arr));// 程序崩溃 所传参数不是地址 printf(%zu\n,strlen(arr[1]));// 程序崩溃 printf(%zu\n,strlen(arr));// 未知数 printf(%zu\n,strlen(arr1));// 未知数-6 printf(%zu\n,strlen(arr[0]1));// 未知数-1 return 0; }带有 \0 sizeof#includestdio.h int main() { char arr[] abcdef; printf(%zu\n,sizeof(arr));// 7 计算的是整个数组内存的大小 printf(%zu\n,sizeof(arr0));// 4/8 计算的是首元素地址的大小 printf(%zu\n,sizeof(*arr));// 1 计算的是首元素的内存大小 printf(%zu\n,sizeof(arr[1]));// 1 计算的是第二个元素的内存大小 printf(%zu\n,sizeof(arr));// 4/8 计算的是整个数组地址的大小 printf(%zu\n,sizeof(arr1));// 4/8 计算的是地址的大小 printf(%zu\n,sizeof(arr[0]1));// 4/8 计算的是地址的大小 return 0; }strlen:#includestdio.h #includestring.h int main() { char arr[] abcdef; printf(%zu\n,strlen(arr));// 6 计算字符数组的长度 printf(%zu\n,strlen(arr0));// 6 计算字符数组的长度 printf(%zu\n,strlen(*arr));// 程序崩溃 所传参数不是地址 printf(%zu\n,strlen(arr[1]));// 程序崩溃 printf(%zu\n,strlen(arr));// 6 计算的是字符数组的长度 printf(%zu\n,strlen(arr1));// 未知数 跳过了整个数组越界访问 printf(%zu\n,strlen(arr[0]1));// 5 从第二个数组开始计数 return 0; }字符指针sizeof#includestdio.h int main() { char* p abcdef; printf(zu\n,sizeof(p));// 4/8 第一个元素地址的大小 printf(zu\n,sizeof(p1));// 4/8 第二个元素地址的大小 printf(zu\n,sizeof(*p));// 1 第一个元素的内存大小 printf(zu\n,sizeof(p[0]));// 1 第一个元素的内存大小 printf(zu\n,sizeof(p));// 4/8 指针变量p的地址大小 printf(zu\n,sizeof(p1));// 4/8 地址大小 printf(zu\n,sizeof(p[0]1));// 4/8 第二个元素地址的大小 return 0; }strlen#includestdio.h #includestring.h int main() { char* p abcdef; printf(%zu\n,strlen(p));// 6 字符串的长度 printf(%zu\n,strlen(p1));// 5 第二位开始计数字符串长度 printf(%zu\n,strlen(*p));// 程序崩溃 所传内容不是地址 printf(%zu\n,strlen(p[0]));// 程序崩溃 所传内容不是地址 printf(%zu\n,strlen(p));// 未知数 用的是指针p的地址不是字符串的地址 printf(%zu\n,strlen(p1));// 未知数 - 1 printf(%zu\n,strlen(p[0]1));// 5 第二位开始计数字符串长度 return 0; }二维数组sizeof#includestdio.h int main() { int a[3][4] {0}; printf(%zu\n,sizeof(a));// 48 计算整个数组的内存大小 printf(%zu\n,sizeof(a[0][0]));// 4 首元素内存大小 printf(%zu\n,sizeof(a[0]));// 16 a[0]可以看作数组名代表整个第一行数组 printf(%zu\n,sizeof(a[0]1));// 4/8 a[0]是首元素地址a[0]1 a[0][1] printf(%zu\n,sizeof(*(a[0]1)));// 4 计算第二个元素的内存大小 printf(%zu\n,sizeof(a1));// 4/8 整个第二行数组元素的地址 printf(%zu\n,sizeof(*(a1)));// 16 整个第二行数组元素的内存大小 printf(%zu\n,sizeof(a[0]1));// 4/8 第二行数组元素的地址 printf(%zu\n,sizeof(*(a[0]1)));// 16 整个第二行元素的内存大小 printf(%zu\n,sizeof(*a));// 4 第一行数组所存元素的内存大小 printf(%zu\n,sizeof(a[3]));// 16 通过类型去推导有16个字节不会真正的去访问不会越界 return 0; }3.指针运算笔试题解析题目1#includestdio.h int main() { int arr[5] { 1, 2, 3, 4 ,5}; int* parr (int*)(arr 1); printf(%d,%d,*(arr 1),*(parr - 1)); return 0; }结果25题目2//在x86环境下 //假设结构体的大小是20个字节 #includestdio.h 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);//跳过一个结构体的大小20字节 printf(%p\n,(unsigned long)p 0x1); printf(%p\n,(unsigned int*)p 0x1);//跳过一个整型变量大小 return 0; }输出001000140010000100100004题目3#includestdio.h int main() { int arr[3][2] { (0,1) , (2,3) , (4,5) };//逗号表达式表达式的结果是右侧结果 int* p arr[0]; printf(%d,p[0]); return 0; }输出1题目4//假设在x86环境下运行程序 #includestdio.h int main() { int arr[5][5]; int(*p)[4]; p arr; printf(%p, %d\n,p[4][2] - arr[4][2],p[4][2] - arr[4][2]);//涉及补码知识 return 0; }输出FFFFFFFC- 4题目5#includestdio.h int main() { int arr[2][5] {1,2,3,4,5,6,7,8,9,10}; int* ptr1 (int*)(arr 1); int* ptr2 (int*)(*(arr 1)); printf(%d,%d,*(ptr1 - 1),*(ptr2 - 1)); return 0; }输出105题目6#includestdio.h int main() { char* a[] {work,at,alibaba}; char** pa a; pa; printf(%s\n,*pa); return 0; }输出at题目7#includestdio.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; }输出POINTERSTEW最后感谢阅读欢迎大家的交流与指正。