前言
在C语言学习过程中, sizeof 、 strlen 、数组名、指针的区分是高频易错点,也是看懂内存布局的关键基础。本篇整理学习笔记,厘清字符串数组、字符指针、标准库字符串函数的坑点。
一、 sizeof 和 strlen 核心区别
1. sizeof :运算符,计算占用内存字节数
- 数组名传给 sizeof : sizeof(arr) 得到整个数组总字节大小;
- arr+0 、 arr 单独参与表达式,退化为首元素地址;
- &arr 是整个数组的地址,地址数值和数组首地址一样,但类型是数组指针;
重点:只要不是直接写 sizeof(数组名) ,数组名都会退化为首元素指针。
2. strlen() :库函数,统计有效字符长度,遇到 \0 停止计数,不包含末尾结束符 \0 **
致命坑:
strlen(*arr) 直接传字符值,不是字符串起始地址,程序直接崩溃。
strlen只接收字符串首地址作为参数。
示例对比
c
char arr[] = "abcdef";
// sizeof
sizeof(arr); //7,6个字符 + '\0'
sizeof(arr+0); //指针大小(64位系统8字节)
sizeof(*arr); //*arr等价arr[0],单个char占1字节
sizeof(&arr); //数组地址,指针大小8字节
// strlen
strlen(arr); //6
strlen(&arr); //可以运行,地址数值一致,长度6
strlen(&arr+1); //跳到数组后面的内存,随机值,野内存
strlen(&arr[0]+1);//从下标1开始,结果5
char指针形式字符串
c
char *p = "abcdef";
strlen(p); //6
strlen(p+1); //5
// strlen(*p); //崩溃!*p是字符'a',不是地址
sizeof(p); //指针大小8字节,不是字符串长度
sizeof(*p); //1
小结:
数组:内存连续存着 a b c d e f \0 ;
指针p:p变量保存字符串常量的首地址,字符串常量放在只读内存。
二、二维数组 sizeof 快速计算
c
int arr[3][4] = {0};
sizeof(arr); //3*4*4 =48
sizeof(arr[0][0]); //单个int占4
sizeof(arr[0]+1); //arr[0]退化成指针,8字节
sizeof(*(arr+1)); //arr+1是第二行数组地址,解引用一行数组,4*4=16
sizeof(&arr[0]+1); //地址,8字节
sizeof(*(*(arr+1)));//取到int值,4字节
三、字符串处理函数(string.h)
1. strcmp(str1,str2)
按ASCII逐字符比较
- str1 < str2 返回 -1
- 相等返回 0
- str1 > str2 返回 1
2. strncpy(dst, src, n)
拷贝n个字符,不会自动补 \0 ,容易出现字符串没有结束符,后续访问乱码。
工程规范:尽量少用不安全的 strcpy ,优先带长度限制版本。
3. strncat
追加字符串,最多追加n个字符,追加结束后自动补上 \0 终止符。
4. strncmp :指定比较前n个字符。
5. strstr(str1,str2) :在str1查找str2第一次出现的位置,返回对应指针。
6. strtok :字符串分割函数,会直接修改原字符串,内部保存静态指针,多次分割传 NULL ;不能用于字符串常量。
7. strerror(errno) :根据错误码打印错误描述。
四、踩坑总结
1. 分清**数组本身、数组首元素地址、数组指针 &arr **三者类型差异;
2. strlen 参数必须是字符串起始地址,不能传入单个字符;
3. 字符串常量 char *p="xxx" 存放在只读段,不要尝试修改;
4. strcpy 无长度检查容易缓冲区溢出,工程代码优先使用带长度限制函数;
5. strtok 有静态变量记忆位置,多线程不安全,不要在循环嵌套分割。
https://gitcode.com/gcw_RyL6LF93/study‑c‑languague.git