C-sizeof和strlen区别,以及sizeof如何计算结构体大小

本文深入解析C语言中sizeof运算符与strlen函数的区别及应用。sizeof用于计算变量或类型的字节数,可在编译期确定;strlen用于计算字符串长度,运行期计算,遇''终止。文章通过实例展示两者特性,包括对数组、类型大小计算,以及结构体字节对齐规则。

come from :  https://www.cnblogs.com/lifexy/p/10386552.html

sizeof和strlen区别

  • sizeof是关键字,在编译时就能计算出值,可以计算任何类型
  • strlen是函数,只有在运行时才能去计算,且只能计算字符型的.

对于数组时,strlen是判断’\0’为标志结尾的,而sizeof则计算的是数组整个空间
示例如下:

char buf1[]="abcde";
char buf2[30]="ABC";
printf("buf1: %d %d\n",sizeof(buf1),strlen(buf1));
printf("buf2: %d %d\n",sizeof(buf2),strlen(buf2));

打印如下:

可以看到当我们的buf1没有指定长度时,sizeof打印的是6,这是因为它把’\0’也包含进去了.


sizeof还可以计算类型大小,一般对于32位C程序而言,对应的long则为4字节
如下图所示:

示例:

 

printf("char: %d\n",sizeof(char));
printf("short: %d\n",sizeof(short)); 
printf("int: %d\n",sizeof(int));
printf("long: %d\n",sizeof(long)); 
printf("long long: %d\n",sizeof(long long));
printf("float: %d\n",sizeof(float)); 
printf("double: %d\n",sizeof(double));

 

打印如下:

 

sizeof计算结构体大小
计算机为了加快取读结构体的内容速度,所以会对结构体进行字节对齐.
字节对齐的规律就是:结构体大小必须是最大成员的倍数(方便寻址)
示例1:

 

struct TestA{
  short a;
  long b;    //b=4, a=2 ,而5%4=1,所以会在a上面补齐3字节,所以s1=8
};
struct TestB{
  char c;
  TestA d;    
  int f;    //c=1,d=8,f=4,而1+8+4=13,13%8=5,还差3字节,所以会在c上面补齐3字节, s2=16
              
};
int main()
{
  printf("%d\n",sizeof(TestA));
  printf("%d\n",sizeof(TestB));
}

 

打印如下:

 

示例2:

 

struct TestA {
  short a;
  long b;    //s1=8,之前已经分析过
};
struct TestB{
  char c;
  TestA d;    
  long long f;    //c=1,s1=8,f=8,由于8最大,且17%8=1,所以会在c上面补齐7字节,则s2=24
};
int main()
{
  printf("%d\n",sizeof(TestA));
  printf("%d\n",sizeof(TestB));
}

 

打印如下:

 

#include <stdio.h>
#include <string.h>
typedef struct {
        char a;
        int b;
        double c;
}type_t;
//第一个OFFSET宏
//#define OFFSET(TYPE , MEMBER , OFF) \
        TYPE temp; \
        OFF = (unsigned long)(&(temp.MEMBER)) - (unsigned long)(&(temp));
//第二个OFFSET宏
#define OFFSET(TYPE , MEMBER)((unsigned long)(&(((TYPE *)0)->MEMBER)))
int main(void)
{
        int offset = 0;
        type_t type;
        //offset = (unsigned long)(&(type.c)) - (unsigned long)(&(type));         //不使用宏
        //OFFSET(type_t , c , offset);  //使用第一个OFFSET
        offset = OFFSET(type_t , c);    //使用第二个OFFSET
        printf("offset = %d\n" , offset);
}
 

<think>我们被要求解释C语言中sizeofstrlen区别。根据引用内容,我们可以总结以下几点: 1. **本质区别**: - `sizeof`是C语言中的单目运算符(操作符),而`strlen`是标准库函数(需要包含头文件`string.h`)。 2. **功能区别**: - `sizeof`用于计算操作数的内存占用大小(以字节为单位)。它可以用于任何数据类型,包括基本类型(如int、char)、数组、结构体等。当用于字符数组时,它返回整个数组的大小(包括终止符'\0')。 - `strlen`用于计算字符串的长度(即字符的个数),直到遇到第一个'\0'(不包括'\0')。它只能用于以'\0'结尾的字符串(即C风格字符串)。 3. **参数区别**: - `sizeof`可以用类型或表达式(包括变量、数组、函数调用等)作为参数。 - `strlen`只能用`char*`类型的参数(即字符串的起始地址),并且要求字符串必须以'\0'结尾。 4. **计算时机**: - `sizeof`在编译时计算(因为是运算符),表达式中的运算不会被执行(如`sizeof(函数调用)`实际上不会调用函数)。 - `strlen`在运行时计算,它遍历内存直到遇到'\0'。 5. **安全性**: - `sizeof`是安全的,因为它不会访问内存(编译时已知)。 - `strlen`如果传入的字符串没有'\0'结尾,则会继续向后访问内存直到遇到'\0',这可能导致未定义行为(如越界访问)。 下面通过代码示例进一步说明: ```c #include <stdio.h> #include <string.h> int main() { char arr[] = "Hello"; // 使用sizeof计算整个数组的大小,包括结尾的'\0',所以是6个字符(每个字符1字节) printf("sizeof(arr) = %zu\n", sizeof(arr)); // 输出6 // 使用strlen计算字符串长度,遇到'\0'停止,不包括'\0' printf("strlen(arr) = %zu\n", strlen(arr)); // 输出5 // 注意:如果数组不是以'\0'结尾,则strlen的行为不确定 char arr2[5] = {'H', 'e', 'l', 'l', 'o'}; // 没有空间存放'\0' printf("sizeof(arr2) = %zu\n", sizeof(arr2)); // 输出5,数组大小为5字节 printf("strlen(arr2) = %zu\n", strlen(arr2)); // 未定义行为,因为arr2没有以'\0'结尾 return 0; } ``` 输出(注意最后一行是未定义的,可能输出任意值或导致程序崩溃): ``` sizeof(arr) = 6 strlen(arr) = 5 sizeof(arr2) = 5 strlen(arr2) = ? // 可能是5,也可能是一个很大的数,或者程序崩溃,这是未定义行为 ``` 总结: | 特性 | sizeof | strlen | |--------------|------------------------|----------------------------| | 类型 | 运算符 | 函数 | | 头文件 | 不需要 | 需要`#include <string.h>` | | 参数 | 类型或表达式 | 以'\0'结尾的字符串 | | 计算内容 | 操作数的内存占用大小 | 字符串长度(不含'\0') | | 计算时机 | 编译时 | 运行时 | | 安全性 | 安全 | 可能不安全(依赖'\0') | | 是否计算'\0' | 是 | 否 | §§相关问题§§ 1. 为什么在C语言中字符串需要以'\0'结尾? 2. 如何安全地使用strlen函数以避免未定义行为? 3. sizeof运算符在计算结构体大小时会考虑内存对齐吗? </think>### C语言中`sizeof``strlen`的区别 `sizeof``strlen`是C语言中处理内存字符串的两个关键工具,它们的核心区别在于**本质、功能行为机制**: | 特性 | `sizeof` | `strlen` | |--------------|-----------------------------------|-----------------------------------| | **本质** | 编译器运算符(编译时计算)[^1] | 标准库函数(运行时计算)[^1] | | **头文件** | 不需要 | 需要`#include <string.h>`[^4] | | **参数类型** | 任意类型/表达式(含数据类型)[^2] | 仅`char*`(字符串指针)[^2] | | **计算内容** | 操作数的内存字节大小 | 字符串实际长度(不含`\0`)[^3] | | **终止条件** | 无(编译时确定) | 遇到`\0`终止[^3] | | **安全性** | 绝对安全 | 依赖`\0`,未终止会导致越界[^4] | #### 关键差异详解: 1. **本质差异** - `sizeof`是**编译器运算符**,在编译阶段直接计算结果[^1] - `strlen`是**运行时函数**,执行时遍历内存计算[^4] 2. **字符串处理对比** ```c char str[] = "Hello"; printf("sizeof: %zu\n", sizeof(str)); // 输出6(包含'\0') printf("strlen: %zu\n", strlen(str)); // 输出5(不含'\0') ``` 3. **未终止字符串的危险性** ```c char arr[3] = {'a','b','c'}; // 无终止符 printf("strlen: %zu\n", strlen(arr)); // 未定义行为(可能越界)[^4] ``` 4. **表达式处理差异** ```c int x = 10; printf("%zu\n", sizeof(x++)); // x不递增(编译时计算) printf("%d\n", x); // 仍输出10 ``` #### 使用场景建议: - ✅ 需内存分配时用`sizeof`(如`malloc(sizeof(int)*n)`) - ✅ 处理字符串长度时用`strlen`(但需确保有`\0`) - ❌ 避免对非字符串使用`strlen` - ❌ 避免用`sizeof`获取动态字符串长度 > 数学表达示例: > 若定义字符串数组$s[n]$,则: > $$ > \text{sizeof}(s) = n \times \text{sizeof(char)} \quad \text{而} \quad \text{strlen}(s) < n > $$
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值