C语言内存机制深度解析:指针运算、数组与字符串实战指南

一、sizeof与strlen对比

1.1 sizeof

sizeof是一个操作符,绝对不是函数,如果操作数是变量,则计算变量所占内存空间的大小,如果操作数是类型,则计算使用该类型创建变量所占内存空间的大小
sizeof只关注占内存空间的大小,不在乎内存中存放的是什么数据

  • sizeof里的表达式不会运算
    表达式是在产生.exe可执行程序时双击运行时才会运行表达式,而sizeof运算是在编译时就计算好了,编译完以后表达式就没在代码里面了,自然就不会算表达式

1.2 strlen

是一个库函数,只针对字符串,求字符串的长度,把首地址的地址传给函数,统计\0之前的个数

三种写法:

错误写法:

1.3 sizeof与strlen对比

二、sizeof练习

2.1 整形数组

已知:int arr[]={1,2,3,4}

sizeof(arr+0)的结果

计算机假设计算arr+0运行,算出结果的类型,但是实际并不会进行真正的运算,arr没有单独与sizeof结合,arr就是首元素的地址,arr+0还是首元素的地址,sizeof(arr+0)的结果就是4/8

sizeof(&arr)的结果

&arr也是数组的地址,数组的地址也是地址,sizeof计算出来为4/8

sieof(*&a)的结果

  • 方法1:*与&相抵消,就是sizeof(arr)也就是整个数组的大小
  • 方法2:&arr取出的是数组的地址,类型是int(*)4,对数组指针解引用,而旁边直接有sizeof,所以访问的是一个数组,也就是一个数组的大小

sizeof(&arr+1)

&arr+1没有访问内存空间,是跳过这个数组后那个位置的地址,是地址就是4/8

2.2 字符数组

已知: char arr[] = { 'a','b','c','d','e','f' };

sizeof(arr)的结果

arr与sizeof()结合求整个数组的大小

sizeof(arr+0)的结果

arr就是首元素的地址,arr+0还是首元素的地址,sizeof(arr+0)的结果就是4/8

sizeof(&arr)的结果

&arr为整个数组的地址,类型是int (*)6

sizeof(&arr[0]+1)的结果

&arr0为第一个元素的地址,&arr0+1为第二个元素的地址

2.3 存字符串数组

  • 存到数组中
    已知: char arr[] = "abcdef";

sizeof(arr)的结果

arr是数组名,单独放在sizeof()内部,计算的是数组总大小,加上\0有7个

sizeof(arr+0)的结果

arr表示数组首元素的地址,arr+0还是首元素的地址,是地址就是4/8

  • 还有一种也是字符串,但是放到指针类型
    const char *p="abcdef"

printf("%d",sizeof(p))的结果

p是指针变量,我们计算的是指针变量的大小,4/8个字节

printf("%d",sizeof(p+1))的结果

p+1是b的地址,是地址大小就是4/8个字节

printf("%d",sizeof(*p))的结果

*p的类型是const char*,*p就是char类型了,1个字节

printf("%d",sizeof(p[0]))的结果

理解方式:

  1. p0-->*(p+0)-->'a',大小是一个字节
  2. 把常量字符串想象成数组,p可以理解为数组名,p[0],就是首元素

printf("%d",sizeof(&p))的结果

p是个指针变量,&p去的是p空间的地址,与"abcdef"没关系,结果为4/8

printf("%d",sizeof(&p+1))的结果

跳过char*类型的地址,也是地址

2.4 二维数组

已知:int arr[3][4] = { 0 };

printf("%d", sizeof(arr))的结果

arr单独与sizeof结合,计算的是整个数组的大小,结果为3* 4 *4等于48

printf("%d", sizeof(arr[0]))的结果

a0第一行的数组名,数组名单独放在sizeof内部了,计算的是数组的总大小16个

理解方式:

printf("%d", sizeof(arr[0]+1))的结果

arr0没有单独放在sizeof()内部,所以arr0就是首元素的地址,就是arr00,+1后变成arr01的地址,结果为4/8

printf("%d", sizeof(*(arr[0] + 1)))的结果

(arr0 + 1)代表的是第二个元素的地址,*(arr0 + 1)指的是第二个元素

printf("%d", sizeof(arr + 1))的结果

arr没有放在sizeof内部,arr表示二维数组的首地址,也就是一维数组的地址(第一行的地址),+1就是第二行的地址,a+1是数组指针,结果是4/8

printf("%d", sizeof(*(arr + 1)))的结果

理解方式:

  1. (arr+1)是第二行的地址,数组指针解引用,访问的是第二行,*(arr+1)计算的是第二行的大小
  2. *(arr+1)==arr1,arr1是第二行的数组名,相当于把第二行的数组名放在sizeof()里面,计算的是第二行的大小

printf("%d", sizeof(&arr[0] + 1))的结果

arr0是第一行的数组名,与sizeof结合,就是第一行的地址,arr0+1就是第二行的地址,是地址结果就是4/8

printf("%d", sizeof(*(&arr[0] + 1)))的结果

(&arr0+1)是第二行的地址,数组指针,解引用访问的是第二行,大小是16

printf("%d", sizeof(*arr))

arr是二维数组的首元素的地址,也就是第一行的地址,*arr就是第一行,计算的是第一行的大小
*a == *(a+0) == a[0]

sizeof(arr[3]), 会越界访问吗?

arr3无需存在,仅仅通过类型的推断就能算出长度,arr3是第四行的数组名,与sizeof()单独结合,计算的是第四行的大小,16个字节
注:sizeof不会真实访问空间,可以自己推断类型


总结:

三、strlen练习

3.1 字符数组

已知: char arr[] = { 'a','b','c','d','e','f' };

strlen(arr)的结果

首先分析arr既没与sizeof结合,也没与&结合,所以也是数组名表示首元素的地址,把首元素的地址传给strlen,从这个位置向后数,数到 \0就停下来统计个数,数组没有\0就会越界访问,结果为随机值

strlen(*arr)的结果

是首元素的地址,*arr是首元素,就是'a',strlen这个函数接受的是地址,a的Ascill码值为97,拿到一个野指针97,97这个地址不允许我们访问,运行到这里程序会崩溃

sizeof(&arr)的结果

arr是数组的地址,起始位置是数组的第一个元素的位置,strlen也是从这开始的,结果为随机值

3.2 存字符串数组

  • 存到数组中
    已知: char arr[] = "abcdef";

strlen(*arr)

*arr为首元素,为'a',Ascill码值为97,出错

strlen(&arr)

补充:strlen函数是char*类型的,而取地址数组是char * arr6的类型,会发生强制类型转换

&arr是数组的地址,也是从数组第一个元素开始向后找,结果是6

strlen(&arr+1)

跳过整个数组,结果为随机值

strlen(&arr0+1)

从第二个地址开始,结果为5

  • 还有一种也是字符串,但是放到指针类型
    已知:char* p = "abcdef";

printf("%d", strlen(p));

p存放的是a的地址,从前往后数,到\0为止,结果为6

printf("%d", strlen(p+1));

p+1是b的地址,从前往后数,到\0为止,结果是5

printf("%d", strlen(*p));

*p是'a',Ascill码值是97,程序会报错

printf("%d", strlen(&p));

&p是指针变量p的地址,和字符串"abcdef"关系就不大了,/从p这个指针变量的起始位置开始向后数的,变量存放的地址是什么,不知道,所以答案是随机值

printf("%d", strlen(&p0+1));

从第二个地址向后数,结果为5

四、巩固指针

易错题分析

  • 指针加减
  • 逗号表达式与指针
  • 指针类型转换区别
  • 二维数组的理解
  • 字符串与指针
  • 指针综合:优先级、多级指针

++、--会把值改掉,[] (下标运算符不会改)
*得到里面的空间,会把里面的值改掉

相关推荐
J2虾虾13 分钟前
C 语言 sizeof 完全用法指南
c语言·数据结构·算法
xxwxx__34 分钟前
51单片机定时器/计数器中断详解(T0和T1)——从入门到精通
c语言·单片机·嵌入式硬件·51单片机
cft56200_ln1 小时前
TDA4时间同步3 网卡添加虚拟时间戳
c语言·开发语言·arm开发·驱动开发·嵌入式硬件·网络协议
189228048611 小时前
NV091固态MT29F16T08EWLCHD8-QJES:C
c语言·开发语言
AI thought1 小时前
C语言企业项目实战(四)
c语言·单元测试·压力测试·企业项目·工程体系
AI科技星1 小时前
《数术工坊:无穷套娃录》 一部用数学套娃写成的“天书小说”
c语言·开发语言·网络·量子计算·agi
m0_547486662 小时前
华南农业大学《C语言程序设计》期末试卷及答案2018-2025年PDF
c语言·开发语言·pdf·c语言程序设计
Hello:CodeWorld13 小时前
C 风格变参 vs C++ 变参模板:核心区别与选型指南
c语言·c++·算法
十月的皮皮15 小时前
C语言学习笔记20260606- 求月份天数三种写法
c语言·笔记·学习
caimouse15 小时前
Reactos 第 5 章 进程与线程 — 5.8 Windows 的 APC 机制
c语言·windows