sizeof与strlen

本文详细介绍了C语言中sizeof运算符的使用方法,包括其概念、如何应用于不同类型及变量,以及与strlen函数的区别,并通过实例说明了对齐问题的影响。
一、sizeof的概念 
  sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等。它并不是函数。sizeof操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型定。 


二、sizeof的使用方法 

1、用于数据类型 
sizeof使用形式:sizeof(type) 
数据类型必须用括号括住。如sizeof(int)。 
  
2、用于变量 
sizeof使用形式:sizeof(var_name)或sizeof var_name 
变量名可以不用括号括住。如sizeof (var_name),sizeof var_name等都是正确形式。
注意:sizeof操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知
存储大小的数据类型。如未知存储大小的数组类型、未知内容的结构或联合类型、void类
型等。 
  注意:sizeof 操作数为用户定义类型时,要考虑到对齐问题:
联合类型操作数的sizeof是其最大字节成员的字节数。结构类型操作数的sizeof是这种类型对象的总字节数包括任何垫补在内。   
  如:struct 
{     char b; 
      double x;
} a; 
  
vc6.0结果为16。
这是因为编译器在考虑对齐问题时在结构中插入空位以控制各成员对象的地址对齐。
如double类型的结构成员x要放在被8整除的地址。
可以通过#pragma pack(n)改变字节对
齐。 
例如: 
struct mystruct1
{  
    
char a;             //1 
    
int b;               //4 
    
short c;           //2 
    
long d;            //4 
    
double e;        //8 
}; 
默认的结构体的sizeof结果是24。
 
#pragma pack(2) 
struct mystruct1
{  
    char a;             //1 
   
 int b;               //4 
    
short c;           //2 
    
long d;            //4 
    
double e;        //8 


}; 
此时结果为20。 所以,默认时以最大字节作为存储单位,即8字节.而对齐方式则以两两之间的最大字节对齐,比如char与int以4字节对齐,占用了一个8字节空间,short重新开始一个8字节空间,short与long以4字节对齐,再结合成一个8字节空间,同时double单独占用一个8字节空间.所以最后总空间为24字节。 
    
改变对齐方式为2字节时,则char以2字节后接int的2个2字节,再接short的2字节,再接long的2个2字节最后接double的4个2字节,此时计算总数为2字节 *  (1+2+1+2+4)= 20字节。
三,strlen与sizeof的区别
1.从功能定义上:strlen函数用来求字符串的长度,sizeof函数是用来求指定变量或变量类型等所占用内存的大小.
2.sizeof是运算符,而strlen是C库函数strlen只能用char*做参数,且以'/0'结尾的.


对于静态数组处理: 

char str[20]="0123456789"; 
strlen(str)=10;   //表示数组中字符串的长度 
sizeof(str)=20;   //表示数组变量分配的长度 
  
对于指针处理:
char *str="0123456789"; 
strlen(str)=10;     //表示字符串的长度 
sizeof(str)=4;      //表示指针变量的所占内存大小 
sizeof(*str)=1;     //表示'0'这个字符变量的所占内存大小 
`sizeof` 和 `strlen` 是 C 语言中两个常被混淆的概念,它们都“大小”有关,但含义和用途完全不同。 --- ### 一、基本定义 | 名称 | 类型 | 作用 | |------|------|------| | `sizeof` | **运算符**(编译时计算) | 计算**数据类型或对象所占的字节数**(包括数组、结构体、指针等) | | `strlen` | **函数**(运行时计算) | 计算**字符串中字符的个数**(不包含末尾的 `\0`) | --- ### 二、代码对比示例 ```c #include <stdio.h> #include <string.h> int main() { char str[] = "hello"; // 包含 'h','e','l','l','o','\0' → 共6字节 char *ptr = "world"; // 字符串字面量,ptr 是指向它的指针 printf("sizeof(str) = %zu\n", sizeof(str)); // 输出:6(包括 \0) printf("sizeof(ptr) = %zu\n", sizeof(ptr)); // 输出:8(64位系统上指针大小为8字节) printf("sizeof(char*)= %zu\n", sizeof(char*)); // 输出:8 printf("strlen(str) = %zu\n", strlen(str)); // 输出:5(只算有效字符,不含 \0) printf("strlen(ptr) = %zu\n", strlen(ptr)); // 输出:5 return 0; } ``` #### 输出结果(64位系统): ``` sizeof(str) = 6 sizeof(ptr) = 8 sizeof(char*)= 8 strlen(str) = 5 strlen(ptr) = 5 ``` --- ### 三、详细解释 #### ✅ `sizeof` - 是一个 **编译时运算符**,在编译阶段就确定值。 - 对数组使用时,返回整个数组占用的字节数。 - 对指针使用时,返回的是指针本身的大小(如 8 字节 on x86_64)。 - 不会进入内存去读数据,只是根据类型判断。 ```c char arr[100]; printf("%zu\n", sizeof(arr)); // 输出 100 ``` > 即使数组未完全初始化,`sizeof` 仍返回声明的总大小。 #### ✅ `strlen` - 是 `<string.h>` 中的库函数:`size_t strlen(const char *s);` - 从给定地址开始逐字节扫描,直到遇到 `\0`(空字符)为止。 - 返回的是字符个数(不包含 `\0`)。 - 必须保证传入的是以 `\0` 结尾的字符串,否则行为未定义(可能崩溃)。 ```c char *p = NULL; // strlen(p); // ❌ 危险!空指针解引用 → 段错误 ``` --- ### 四、常见陷阱误区 #### ❌ 误区 1:认为 `sizeof` 能获取动态字符串长度 ```c char *s = malloc(100); strcpy(s, "hi"); printf("sizeof(s) = %zu\n", sizeof(s)); // 输出 8(指针大小),不是 100 或 2! ``` ✅ 正确做法:用 `strlen(s)` 获取实际内容长度。 --- #### ❌ 误区 2:对函数参数中的数组使用 `sizeof` ```c void func(char arr[]) { printf("%zu\n", sizeof(arr)); // 输出 8(实际是 char* 的大小) } int main() { char data[100]; printf("%zu\n", sizeof(data)); // 输出 100 func(data); // 传数组名 → 实际上传的是地址 return 0; } ``` 原因:当数组作为函数参数时,会退化为指针,`sizeof(arr)` 就变成了指针大小。 ✅ 解决方案:额外传递长度参数: ```c void func(char arr[], size_t len) { printf("Length: %zu\n", len); } ``` --- #### ❌ 误区 3:`strlen` 对非字符串内存调用 ```c int nums[] = {1, 2, 3, 4}; // strlen((char*)nums); // ❌ 非法!这不是字符串,没有 \0 终止符 ``` 会导致无限扫描,直到碰到 `\0` 或访问非法内存。 --- ### 五、总结对比表 | 特性 | `sizeof` | `strlen` | |------|----------|---------| | 类型 | 运算符 | 函数 | | 头文件 | 无需包含 | `#include <string.h>` | | 计算时机 | 编译时 | 运行时 | | 是否包含 `\0` | 是(如果是数组) | 否 | | 参数可以是 NULL 吗? | 可以(`sizeof(NULL)` 合法) | 不可以(会崩溃) | | 返回值单位 | 字节数 | 字符数(不包括 `\0`) | | 对数组有效吗? | 是(完整大小) | 是(需以 `\0` 结尾) | | 对指针有效吗? | 是(返回指针本身大小) | 是(但必须指向合法字符串) | --- ### 六、实用技巧 #### ✅ 安全地获取数组长度(仅限本地数组) ```c #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) int arr[] = {1, 2, 3, 4, 5}; printf("Elements: %zu\n", ARRAY_SIZE(arr)); // 输出 5 ``` ⚠️ 注意:只能用于**本地定义的数组**,不能用于函数参数或动态分配的内存。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值