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

sizeof 和strlen的对比

在这里插入图片描述

目录

  • 1 sizeof 和strlen的对比
    • 1.1 sizeof
    • 1.2 strlen
    • 1.3 sizeof 和strlen的对比
  • 2 数组和指针笔试题解析
    • 2.1 ⼀维数组
    • 2.2 字符数组
      • 2.2.1代码1:
      • 2.2.2代码2:
      • 2.2.3代码3:
      • 2.2.4代码4:
      • 2.2.5代码5:
      • 2.2.6代码6:
    • 2.3 ⼆维数组
  • 3 指针运算笔试题解析
    • 3.1 题⽬1:
    • 3.2 题⽬2:
    • 3.3 题⽬3:
    • 3.4 题⽬4:
    • 3.5 题⽬5:
    • 3.6 题⽬6:
    • 3.7 题⽬7:
  • 后言

1 sizeof 和strlen的对比

1.1 sizeof

在学习操作符的时候,我们学习了sizeof ,sizeof 计算变量所占内存内存空间⼤小的,单位是字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的⼤小。sizeof只关注占⽤内存空间的⼤⼩,不在乎内存中存放什么数据。

1.2 strlen

strlen是C语⾔库函数,功能是求字符串⻓度。函数原型如下:

 size_t strlen ( const char * str );

统计的是从strlen 函数的参数str 中这个地址开始向后,\0之前字符串中字符的个数。strlen 函数会⼀直向后找\0 字符,直到找到为⽌,所以可能存在越界查找。

1.3 sizeof 和strlen的对比

在这里插入图片描述

2 数组和指针笔试题解析

数组名的理解
数组名是数组首元素(第一个元素)的地址
但是有2个例外:

  1. sizeof(数组名) - 数组名表示整个数组,计算的是整个数组的大小,单位是字节
  2. &数组名 - 数组名表示整个数组,取出的是整个数组的地址
  3. 除此之外,所以的数组名是数组首元素(第一个元素)的地址。

2.1 ⼀维数组

//int main()
//{
//	int a[] = { 1,2,3,4 };//数组有几个元素?
//
//	printf("%zd\n", sizeof(a));//16 -- sizeof(数组名)的场景
//	printf("%zd\n", sizeof(a + 0));//a是首元素的地址-类型是int*, a+0 还是首元素的地址,是地址大小就是4/8
//	printf("%zd\n", sizeof(*a));//a是首元素的地址,*a就是首元素,大小就是4个字节
//	//*a == a[0] == *(a+0)
//	printf("%zd\n", sizeof(a + 1));//a是首元素的地址,类型是int*,a+1跳过1个整型,a+1就是第二个元素的地址,4/8
//	printf("%zd\n", sizeof(a[1]));//a[1]就是第二个元素,大小4个字节
//	printf("%zd\n", sizeof(&a));//&a是数组的地址,数组的地址也是地址,是地址大小就是4/8个字节
//	printf("%zd\n", sizeof(*&a));//1. *& 互相抵消了,sizeof(*&a) = sizeof(a) -16
//	//2. &a 是数组的地址,类型是int(*)[4],对数组指针解引用访问的是数组, 计算的是数组的大小 -16
//	//
//	printf("%zd\n", sizeof(&a + 1));//&a+1是跳过整个数组后的那个位置的地址,是地址就是4/8个字节
//	printf("%zd\n", sizeof(&a[0])); //首元素的地址,大小4/8个字节
//	printf("%zd\n", sizeof(&a[0] + 1));//&a[0] + 1 -- 数组第二个元素的地址,大小是4/8个字节
//
//	return 0;
//}

2.2 字符数组

2.2.1代码1:

int main()
{char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", sizeof(arr));//数组名单独放在sizeof内部了,计算的是数组的大小,单位是字节-6printf("%d\n", sizeof(arr + 0));//arr是数组名表示首元素的地址,arr+0还是首元素的地址,是地址就是4/8个字节printf("%d\n", sizeof(*arr));//arr是首元素的地址,*arr就是首元素,大小就是1个字节//*arr -- arr[0] - *(arr+0)printf("%d\n", sizeof(arr[1]));//arr[1] 是第二个元素,大小也是1个字节printf("%d\n", sizeof(&arr));//&arr 是数组地址,数组的地址也是地址,大小是4/8个字节//&arr -- char (*)[6]这是一个数组指针的类型。printf("%d\n", sizeof(&arr + 1));//&arr+1, 跳过整个数组,指向了数组后边的空间,4/8个字节printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址,是地址就是4/8字节return 0;
}

2.2.2代码2:

#include <string.h>int main()
{char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", strlen(arr));//arr是首元素的地址,数组中没有\0,就会导致越界访问,结果就是随机的printf("%d\n", strlen(arr + 0));//arr+0是数组首元素的地址,数组中没有\0,就会导致越界访问,结果就是随机的//printf("%d\n", strlen(*arr));//arr是首元素的地址,*arr是首元素,就是'a','a'的ascii码值是97//就相当于把97作为地址传递给了strlen,strlen得到的就是野指针, 代码是有问题的//printf("%d\n", strlen(arr[1]));//arr[1]--'b'--98,传给strlen函数也是错误的printf("%d\n", strlen(&arr));//&arr是数组的地址,起始位置是数组的第一个元素的位置,随机值 xprintf("%d\n", strlen(&arr + 1));//随机值 x-6printf("%d\n", strlen(&arr[0] + 1));//从第2个元素开始向后统计的,得到的也是随机值 x-1return 0;
}

2.2.3代码3:

int main()
{char arr[] = "abcdef";printf("%d\n", sizeof(arr));//arr是数组名,单独放在sizeof内部,计算的是数组总大小,是7个字节printf("%d\n", sizeof(arr + 0));//arr表示数组首元素的地址,arr+0还是首元素的地址,是地址就是4/8printf("%d\n", sizeof(*arr));//arr表示数组首元素的地址,*arr就是首元素,大小是1字节printf("%d\n", sizeof(arr[1]));//arr[1]是第二个元素,大小1个字节printf("%d\n", sizeof(&arr));//&arr是数组的地址,是地址就是4/8printf("%d\n", sizeof(&arr + 1));//&arr是数组的地址,+1跳过整个数组,还是地址,是地址就是4/8个字节printf("%d\n", sizeof(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址,大小是4/8个字节return 0;
}

2.2.4代码4:

#include <string.h>int main()
{char arr[] = "abcdef";printf("%d\n", strlen(arr));//6printf("%d\n", strlen(arr + 0));//arr首元素的地址,arr+0还是首元素的地址,向后在\0之前有6个字符//printf("%d\n", strlen(*arr));//'a'-97, 出错//printf("%d\n", strlen(arr[1]));//'b'-98, 出错printf("%d\n", strlen(&arr));//&arr是数组的地址,也是从数组第一个元素开始向后找,6//&arr -- char (*)[7]//size_t strlen(const char* s);printf("%d\n", strlen(&arr + 1));//随机值printf("%d\n", strlen(&arr[0] + 1));//5return 0;
}

2.2.5代码5:

int main()
{const char * p = "abcdef";printf("%d\n", sizeof(p));//p是指针变量,我们计算的是指针变量的大小,4/8个字节printf("%d\n", sizeof(p + 1));//p + 1是b的地址,是地址大小就是4/8个字节printf("%d\n", sizeof(*p));//p的类型是const char*, *p就是char类型了,1个字节printf("%d\n", sizeof(p[0]));//1. p[0] --> *(p+0)--> *p --> 'a',大小是1字节//2. 把常量字符串想象成数组,p可以理解为数组名,p[0], 就是首元素printf("%d\n", sizeof(&p));//取出的是p的地址,地址的大小是4/8个字节printf("%d\n", sizeof(&p + 1));//&p + 1是跳过p指针变量后的地址,是地址就是4/8个字节printf("%d\n", sizeof(&p[0] + 1));//4/8 &p[0]-取出字符串首字符的地址,+1是第二个字符的地址,大小是4/8个字节return 0;
}

2.2.6代码6:

int main()
{char* p = "abcdef";printf("%d\n", strlen(p));//6printf("%d\n", strlen(p + 1));//5//printf("%d\n", strlen(*p));//*p就是'a'-97,err//printf("%d\n", strlen(p[0]));//p[0]--> *(p+0)--> *p //errprintf("%d\n", strlen(&p));//&p是指针变量p的地址,和字符串"abcdef"关系就不大了//从p这个指针变量的起始位置开始向后数的,p变量存放的地址是什么,不知道,所以答案是随机值printf("%d\n", strlen(&p + 1));//随机值printf("%d\n", strlen(&p[0] + 1));//&p[0]-取出字符串首字符的地址,+1是第二个字符的地址, 5return 0;
}

2.3 ⼆维数组

int main()
{int a[3][4] = { 0 };printf("%d\n", sizeof(a));//a是数组名,单独放在sizeof内部,计算的是数组的大小,单位是字节 - 48 = 3*4*sizeof(int)printf("%d\n", sizeof(a[0][0]));//a[0][0] 是第一行第一个元素,大小4个字节 printf("%d\n", sizeof(a[0]));//a[0]第一行的数组名,数组名单独放在sizeof内部了,计算的是数组的总大小 16 个字节printf("%d\n", sizeof(a[0] + 1));//a[0]第一行的数组名,但是a[0]并没有单独放在sizeof内部,所以这里的数组名a[0]就是//数组首元素的地址,就是&a[0][0],+1后是a[0][1]的地址,大小是4/8个字节printf("%d\n", sizeof(*(a[0] + 1)));//*(a[0] + 1)表示第一行第二个元素,大小就是4printf("%d\n", sizeof(a + 1));//a作为数组名并没有单独放在sizeof内部,a表示数组首元素的地址,是二维数组首元素的地址,也就是//第一行的地址,a+1,跳过一行,指向了第二行,a+1是第二行的地址,a+1是数组指针,是地址大小就是4/8个字节printf("%d\n", sizeof(*(a + 1)));//1.a+1是第二行的地址,*(a+1)就是第二行,计算的是第二行的大小 - 16//2. *(a + 1) == a[1], a[1]是第二行的数组名,sizeof(*(a + 1))就相当于sizeof(a[1]),意思是把第二行的数组名单独放在//sizeof内部,计算的是第二行的大小printf("%d\n", sizeof(&a[0] + 1));//a[0]是第一行的数组名,&a[0]取出的就是数组的地址,就是第一行的地址//&a[0]+1 就是第二行的地址,是地址大小就是4/8个字节printf("%d\n", sizeof(*(&a[0] + 1)));//*(&a[0] + 1)意思是对第二行的地址解引用,访问的就是第二行,大小是16字节printf("%d\n", sizeof(*a));//a作为数组名并没有单独放在sizeof内部,a表示数组首元素的地址,是二维数组首元素的地址,也就是//第一行的地址,*a就是第一行,计算的就是第一行的大小,16字节//*a == *(a+0) == a[0]printf("%d\n", sizeof(a[3]));//a[3]无需真实存在,仅仅通过类型的推断就能算出长度//a[3]是第四行的数组名,单独放在sizeof内部,计算的是第四行的大小,16个字节return 0;
}

这里是引用

3 指针运算笔试题解析

3.1 题⽬1:

#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));//打印结果2和5return 0;
}

这里是引用

3.2 题⽬2:

//在X86(32位)环境下
//假设结构体的大小是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);//结构体指针+1,跳过一个结构体,0x100000+20----->00100014printf("%p\n", (unsigned long)p + 0x1);//整型值+1,就是+1 0x100000+1--->0x100001printf("%p\n", (unsigned int*)p + 0x1);//0x100000+4---> 0x100004return 0;
}

3.3 题⽬3:

#include <stdio.h>int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };//初始化int* p;p = a[0];printf("%d", p[0]);//1return 0;
}

这里是引用

3.4 题⽬4:

 //假设环境是x86环境,程序输出的结果是啥?#include <stdio.h>int main(){int a[5][5];int(*p)[4];// p 是 int(*)[4]类型的一个数组指针p = a;//a是数组名,数组名是首元素的地址,因为a是二维数组,二维数组的每一个元素是一维数组。a的类型是int(*)[5]。printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//&p[4][2]==*(*(p+4)+2)return 0;}

根据分析,指针相减的结果表示两者之间的元素个数差。由于数组地址随着下标增加而递增,因此计算&p[4][2] - &a[4][2]会得到一个负数,具体结果为-4,这表明两者之间相差4个元素。

在这里插入图片描述

了解运算结果后,我们需要探讨计算机如何存储这些数据。实际上,计算机采用二进制补码的形式来保存数据。那么,-4的补码具体是多少呢?x86环境下是32个比特位

在这里插入图片描述

计算机完成数据存储后,用户可根据需求随时调用这些信息。
在这里插入图片描述
%p 以十六进制格式打印地址,而计算机内部存储的是二进制数据。因此,我们需要了解如何将二进制数转换为十六进制数。实际上,每 4 位二进制数对应 1 位十六进制数,由此可得:
在这里插入图片描述

输出结果为:
在这里插入图片描述

3.5 题⽬5:

#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));//*(aa+1) --> aa[1] 是第二行的数组名,数组名表示首元素的地址aa[1]也是&arr[1][0] printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;}

这里是引用

输出结果为:
在这里插入图片描述

3.6 题⽬6:

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

a 是一个指针数组,其每个元素均为 char * 类型的指针,分别存储字符串 “work”、“at” 和 “alibaba” 的首地址。pa 是一个指向 char * 类型数据的指针,它存储的是数组 a 的首元素地址。对 pa 进行解引用操作即可获取 a 数组中的元素。

在这里插入图片描述

输出结果:
在这里插入图片描述

3.7 题⽬7:

#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;}

> *cpp[-2]+3 ----> * ( * (cpp-2)) +3
> cpp[-1][-1] + 1 ---->  * (*(cpp - 1) - 1) + 1

输出结果:
在这里插入图片描述

后言

以上就是关于sizeof 和strlen的对比及数组指针相关笔试题解析的全部内容,希望能对大家有所帮助或有所启发,感谢各位小伙伴的耐心阅读。咱们下期见!拜拜~

在这里插入图片描述

http://www.xdnf.cn/news/6841.html

相关文章:

  • 【C++ - 仿mudou库one thread one loop式高并发服务器实现】
  • 聊一聊如何确保接口文档的完整性和准确性
  • 深度学习中ONNX格式的模型文件
  • Linux——MySQL用户管理与链接
  • OpenAI Agent调用MCP Server案例分析
  • JavaScript【4】数组和其他内置对象(API)
  • 如何在 Windows 10 或 11 中安装 PowerShellGet 模块?
  • 【软考中级软件设计师】进程管理
  • Windows/MacOS WebStorm/IDEA 中开发 Uni-App 配置
  • Unable to get end effector tips from jmg
  • UDP三种通信方式
  • Harmony开发 List、Grid拖动自定义排序实现
  • 车载诊断架构 --- 核心网关流控制机制需求
  • Python训练打卡Day26
  • c++成员函数返回类对象引用和直接返回类对象的区别
  • 时间筛掉了不够坚定的东西
  • STM32之蜂鸣器和按键
  • Face Over 84.0| 利用AI技术交换照片或视频中的面孔,制作有趣内容
  • (8)python开发经验
  • 如何在纷杂的环境当中保持保持独立思考能力?
  • 基于多头自注意力机制(MHSA)增强的YOLOv11主干网络—面向高精度目标检测的结构创新与性能优化
  • HCIP第六次作业
  • Web3开发工具与框架全解析:从入门到实战
  • 【matlab技巧】通过手绘的方法设计二维运动轨迹,附MATLAB程序
  • 机器学习 day04
  • 线性dp练习(碱基配对)
  • 【OpenCV】基本数据类型及常见图像模式
  • java中的循环结构
  • MySQL——4、表的约束
  • 【Java】应对高并发的思路