sizeof是C语言的编译时运算符,用于获取数据类型或对象的内存字节数(返回size_t类型),关键特性包括:数组名在sizeof中保留完整大小(不退化为指针)、结构体大小可能含填充字节、指针大小依赖系统位数(32位为4字节,64位为8字节);常用作计算数组元素个数(sizeof(arr)/sizeof(arr[0])),但不可用于函数、位域或void类型。

基本概念

  • sizeof是C语言中的一个运算符,用于获取数据类型或对象在内存中占用的字节数
  • 作用:避免在程序中指定依赖于计算机的数据大小
  • 是编译时计算,不会触发任何运行时操作(不会构造/析构对象、不会调用函数等)
  • 返回值类型为size_t,在头文件<stddef.h>中定义为无符号整数类型

语法形式

sizeof unary-expression     // 对表达式求大小
sizeof (type-name)          // 对类型名求大小

注意

  • 类型名必须用括号括起来(sizeof(int)
  • 表达式形式可以省略括号(sizeof x
  • 以下写法错误:sizeof intsizeof (x)(表达式形式可省略括号)

返回值类型

  • 返回类型为size_t(无符号整数)
  • 通常定义为typedef unsigned int size_t;(64位系统可能是unsigned long
  • 在64位系统中,size_t是无符号长整型

常见类型大小(64位系统示例)

类型大小(字节)说明
char1C++标准保证
int4依赖于平台
short2依赖于平台
long8依赖于平台
float4依赖于平台
double8依赖于平台
long double16依赖于平台
指针864位系统
数组总字节数int a[10]为40字节
结构体总字节数(含填充)依赖于对齐规则

常见用法

1. 计算数组元素个数

int arr[10];
size_t count = sizeof(arr) / sizeof(arr[0]); // 10

关键点:数组名在sizeof中不会退化为指针,保留"整个数组"身份

2. 用于内存分配

int *buffer = (int *)calloc(100, sizeof(int)); // 100个int的内存

3. 计算结构体大小

struct Example {
    int a;
    double b;
    char c;
};
printf("Size of struct: %zu\n", sizeof(struct Example));

4. 指针大小

int *p;
printf("Size of pointer: %zu\n", sizeof(p)); // 64位系统为8

特殊情况与陷阱

1. 数组在不同上下文中的行为

上下文sizeof(arr)说明
在函数外数组总大小int a[10]返回40
作为函数参数指针大小void func(int arr[])sizeof(arr)为4或8
数组名参与运算指针大小sizeof(a+0)sizeof(&a)为4或8

2. 结构体对齐

  • 结构体大小可能包含填充字节

  • 对齐规则:char(1)、short(2)、int(4)、double(8)

  • 例如:

    struct Example {
        char a;
        int b;   // 会填充3字节
        double c;
    };
    // 实际大小可能为16(含填充)
    

3. 不能使用的场景

  • 函数:sizeof(func) 错误
  • 位域:sizeof(struct S.f1) 错误
  • void类型:sizeof(void) 错误
  • 未确定大小的数组作为结构体最后一个元素:返回没有该数组的结构体大小

4. 与strlen的区别

  • sizeof:计算对象在内存中占用的字节数(编译时确定)
  • strlen:计算字符串实际长度(运行时确定,不包括终止符'\0')

实用示例

示例1:计算数组元素个数

int arr[10];
printf("%zu\n", sizeof(arr) / sizeof(arr[0])); // 输出10

示例2:结构体大小计算

struct Point {
    int x;
    int y;
    double z;
};

printf("Size of struct: %zu\n", sizeof(struct Point)); 
// 可能为24(含填充)

示例3:指针与数组区别

int a[10];
int *p = a;
printf("%zu\n", sizeof(a));     // 40(数组总大小)
printf("%zu\n", sizeof(p));     // 8(指针大小)
printf("%zu\n", sizeof(a+0));   // 8(数组名退化为指针)
printf("%zu\n", sizeof(*a));    // 4(数组元素大小)

总结

  1. sizeof是编译时计算,不触发运行时操作
  2. 数组名在sizeof中保留"整个数组"身份,不退化为指针
  3. 结构体大小包含填充字节,与成员大小之和可能不一致
  4. 指针大小依赖于系统位数(32位为4,64位为8)
  5. 不能用于函数、位域、void类型、动态分配的数组
  6. 常用表达式:sizeof(array)/sizeof(array[0])计算数组元素个数

掌握sizeof运算符,能帮助你在内存管理、底层编程和跨平台开发中更加得心应手。