当前位置: 首页 > news >正文

11 C 语言 sizeof 与指针实战指南:一维 / 二维数组计算注意事项 + 笔试真题解析 + sizeof strlen 对比

深入理解指针

sizeof 和strlen的对⽐

sizeofstrlen

1. sizeof是操作符

2. sizeof计算操作数所占内存的⼤⼩, 单位是字节

3. 不关注内存中存放什么数据

1. strlen是库函数,使⽤需要包含头⽂件 string.h

2. srtlen是求字符串⻓度的,统计的是 \0 之前字符的隔个数

3. 关注内存中是否有 \0 ,如果没有 \0 ,就会持续往后找,可 能会越界

#include <stdio.h>
int main()
{char arr1[3] = {'a', 'b', 'c'};char arr2[] = "abc";//把字符串的字符挨个放入数组arr2,包括反斜杠0printf("%d\n", strlen(arr1));;//没有\0可能会查找越界printf("%d\n", strlen(arr2));printf("%d\n", sizeof(arr1));//sizeof 数组名--计算是数组的大小printf("%d\n", sizeof(arr2));return 0;
}

数组和指针笔试题解析

⼀维数组
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));//sizeof 数组名--单独只有数组名就是计算整个数组的大小--16字节
printf("%d\n",sizeof(a+0));//数组名加偏移量就是首元素地址---指针类型--4或者8字节
printf("%d\n",sizeof(*a));//数组名解引用得到首元素--int类型--4字节
printf("%d\n",sizeof(a+1));//数组名加偏移量就是首元素地址---指针类型--4或者8字节
printf("%d\n",sizeof(a[1]));//数组名加偏移量然后解引用得到首元素--int类型--4字节
printf("%d\n",sizeof(&a));//对数组名取地址得到数组指针--指针类型--大小固定4/8
printf("%d\n",sizeof(*&a));//对数组名取地址得到数组指针然后解引用得到数组名,sizeof 数组名--计算整个数组大小--16
printf("%d\n",sizeof(&a+1));//对数组名取地址得到数组指针然后加偏移量还是数组指针--4/8
printf("%d\n",sizeof(&a[0]));//对数组首元素取地址--4/8
printf("%d\n",sizeof(&a[0]+1));//对数组首元素取地址加偏移量--4/8
字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));sizeof //数组名--sizeof单独只有数组名就是计算整个数组的大小--6字节
printf("%d\n", sizeof(arr+0));//数组名加偏移量退化成数组首元素地址加偏移量--指针类型--4/8
printf("%d\n", sizeof(*arr));//数组名解引用得到首元素--char类型--1
printf("%d\n", sizeof(arr[1]));//首元素-char--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	

代码2:

char arr[] = {'a','b','c','d','e','f'};
///随机值,数组中没有字符'\0'.使用在内存中遇见'\0'也就是0的时候结束函数,返回随机长度
// strlen(const char* c)参数为字符串的首元素地址或者字符数组的首元素地址
//以'/0'为标志结束该函数,返回字符串长度
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));

代码3:

char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//数组名--计算数组大小包括隐藏的\0---7
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));

代码4:

char arr[] = "abcdef";
printf("%d\n", strlen(arr));//数组名首元素地址-从首元素开始计算长度直到遇见\0结束--6
printf("%d\n", strlen(arr+0));//首元素地址加0偏移量-从首元素开始计算长度直到遇见\0结束--6
//strlen(*arr) → 运行时错误
//*arr是字符'a'(ASCII码97)
//strlen()期望一个指针参数,但这里传递的是char值
//会导致段错误或未定义行为
printf("%d\n", strlen(*arr));//strlen(arr[1]) → 运行时错误
//arr[1]是字符'b'(ASCII码98)
printf("%d\n", strlen(arr[1]));//strlen(&arr) → 6
//&arr是"指向整个数组的指针",但它的值和首元素地址相同
//虽然类型不同(int(*)[7]),但地址相同,所以结果还是6
printf("%d\n", strlen(&arr));//strlen(&arr+1) → 未定义行为
//&arr+1指向数组末尾之后的位置
//访问这个内存区域是未定义行为,可能崩溃或返回随机值
printf("%d\n", strlen(&arr+1));//strlen(&arr[0]+1) → 5
//&arr[0]+1是第二个元素'b'的地址
//从'b'开始计算长度,结果是5
printf("%d\n", strlen(&arr[0]+1));

代码5:

char *p = "abcdef";//这里p是指针变量而不是数组名称了
//所以sizeof p就是计算指针变量类型的大小
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));

代码6:

char *p = "abcdef";
printf("%d\n", strlen(p));
printf("%d\n", strlen(p+1));
//报错--*p解引用得到字符a
printf("%d\n", strlen(*p));
//报错--p[0]解引用得到字符a
printf("%d\n", strlen(p[0]));
//报错二级指针类型--类型不匹配
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p+1));
//
printf("%d\n", strlen(&p[0]+1));
⼆维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));//sizeof 数组名称--计算整个数组大小--12*4
printf("%d\n",sizeof(a[0][0]));//二位数组的第一个元素--int --4
//相当于*(a+0),二维数组首元素的地址--一维数组地址(数组指针)加偏移量解引用得到一维数组名(首元素地址)
//sizeof 数组名称 --计算整个数组大小即计算整个一维数组的大小---4*4=16
printf("%d\n",sizeof(a[0]));//a[0]+1 一维数组名退化成一位维数组首元素地址加偏移量还是指针类型--4/8
printf("%d\n",sizeof(a[0]+1));
//*(a[0]+1)) 一维数组名退化成一维数组首元素地址加偏移量然后解引用得到元素--int--4
printf("%d\n",sizeof(*(a[0]+1)));//a+1 二维数组名称加偏移量退化成二维数组首元素地址即一维数组的地址加偏移量还是指针类型--4/8
printf("%d\n",sizeof(a+1));//*(a+1) 二维数组名称加偏移量退化成二维数组首元素地址即一维数组的地址加偏移量得到第二行的一维数组的
//地址然后解引用得到这个一维数组的数组名,然后sizeof 数组名--得到整个数组的大小--4*4
printf("%d\n",sizeof(*(a+1)));//a[0]->*(a+0) 二维数组名称加偏移量退化成二维数组首元素地址即一维数组的地址加偏移量得到第二行的一维数组的地址然后解引用得到这个一维数组的数组名,然后对数组名取地址就是数组指针然后加偏移量还是数组指针类型--4/8
printf("%d\n",sizeof(&a[0]+1));
//对数组指针类型解引用得到数组名,sizeof 数组名得到一个一维数组的大小--4*4
printf("%d\n",sizeof(*(&a[0]+1)));
//a二位数组名--首元素一维数组的地址--数组指针解引用得到一维数组名称,sizeof 数组名--4*4
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));
数组名的意义:
  1. sizeof(数组名),这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩。

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

  3. 除此之外所有的数组名都表⽰⾸元素的地址

  4. 得到一维数组名有这几个方法:1,对一维数组指针直接解引用

    2,二维数组的首元素地址解引用,因为二维数组就是由一维数组组成的每一个元素就是一个个的一维数组

指针运算笔试题解析

//题⽬1:
#include <stdio.h>
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);//对数组直接取地址得到数组指针加1表示指向下一个数组的开始地址
printf( "%d,%d", *(a + 1), *(ptr - 1));//2 5
return 0;
}
//程序的结果是什么?
//题目2
struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
}*p = (struct Test*)0x100000;
int main()
{printf("%d\n", sizeof(struct Test));//结构体大小32字节//加一表示跨过一个结构体类型的大小指向下一个结构体的起始地址printf("%p\n", p + 0x1);//--0000000000100020//把结构体指针类型转成unsigned long,加一就是按正常的数值运算就行了printf("%p\n", (unsigned long)p + 0x1);//0000000000100001//把结构体指针类型转成unsigned int*,加一表示跨过一个unsigned int类型的大小指向下一个		unsigned int的起始地址printf("%p\n", (unsigned int*)p + 0x1);//0000000000100004return 0;
}
32
0000000000100020
0000000000100001
0000000000100004
#include <stdio.h>
int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };//逗号表达式,计算的结果应该是这样的//int a[3][2] = { 1, 3, 5};int *p;p = a[0];printf( "%d", p[0]);return 0;
}
//假设环境是x86环境,程序输出的结果是啥?
#include <stdio.h>
int main()
{
int a[5][5];
int(*p)[4];
p = a;
//FFFFFFFFFFFFFFFC,-4
printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}

#include <stdio.h>
int main()
{//数组中存储的是一个个字符串常量的起始地址const char *a[] = {"work","at","alibaba"};const char**pa = a;pa++;printf("%s\n", *pa);//atreturn 0;
}

http://www.dtcms.com/a/359205.html

相关文章:

  • 谈谈线程的中断退出
  • nginx(自写)
  • [Windows] 剪映国际版CapCut 6.7.0 视频编辑处理,免费使用素材和滤镜
  • 倾斜摄影是选择RGB图像还是多光谱影响进行操作?
  • RestTemplate工具类用法总结
  • AI融合高等教育:从通识到专业 - 学科+AI人才培养白皮书(下)
  • 最长递增子序列(LIS)的 DFS 解法详解与实现
  • Session
  • PB-重装系统后,重新注册ole控件,pb中窗口控件失效的问题。
  • 2025年06月GESPC++三级真题解析(含视频)
  • 【小宁学习日记5 PCB】电路定理
  • Unity游戏打包——GooglePlay自动传包
  • DFS 回溯 【各种题型+对应LeetCode习题练习】
  • 【多项式】快速莫比乌斯变换(FMT)
  • CCS自定义函数.h与.c问题解决办法
  • Android15适配16kb
  • 计算机毕设项目 基于Python与机器学习的B站视频热度分析与预测系统 基于随机森林算法的B站视频内容热度预测系统
  • Robolectric拿到当前的Activity
  • 轻量化模型-知识蒸馏1
  • Wheat Gene ID Convert Tool 小麦中国春不同参考基因组GeneID转换在线工具
  • 2025年外贸服装跟单管理软件TOP3推荐榜单
  • 手动安装的node到nvm吧版本管理的过程。
  • 基于Docker部署的Teable应用
  • [特殊字符]️ STL 容器快速参考手册
  • 海盗王64位dx9客户端修改篇之三
  • 【有序集合 有序映射 懒删除堆】 3510. 移除最小数对使数组有序 II|2608
  • 9. 函数和匿名函数(一)
  • enumerate 和for in搭配使用
  • 接雨水,leetCode热题100,C++实现
  • 【随笔】【Debian】【ArchLinux】基于Debian和ArchLinux的ISO镜像和虚拟机VM的系统镜像获取安装