文章

C sizeof

在 C 语言中,sizeof 是一个 编译时运算符而非函数,用于获取某个类型或变量所占用的字节(Byte)大小。

基本语法

1
2
3
sizeof(类型名)
sizeof(变量名)
sizeof 变量名

实际上,sizeof计算对象的大小也是转换成对对象类型的计算

sizeof也可以对一个函数调用求值,其结果是函数返回类型的大小,函数并不会被调用

程序示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

int main() {
    int a = 10;
    double b = 3.14;
    char c = 'A';

    printf("sizeof(int): %zu\n", sizeof(int));
    printf("sizeof a: %zu\n", sizeof a);
    printf("sizeof(b): %zu\n", sizeof(b));
    printf("sizeof(char): %zu\n", sizeof(char));

    return 0;
}

在64位系统上的输出结果:

1
2
3
4
sizeof(int): 4
sizeof a: 4
sizeof(b): 8
sizeof(char): 1

特点说明

特性说明
编译时计算sizeof 在编译阶段就能确定,不会在运行时产生开销。
与类型无关你可以传入变量、类型、表达式,都会得到正确的大小。
不求值表达式即使你写 sizeof(x++),也不会执行 x++。它不会改变变量的值。
结构体对齐对结构体使用 sizeof 也能看到结构体对齐带来的额外字节填充。

特殊用法

  1. 用于数组大小计算
1
2
3
int arr[10];
size_t len = sizeof(arr) / sizeof(arr[0]);  // 数组元素个数
// 数组的大小 / 数组中一个元素的大小

注意

  • 如果使用int *p = arrint *p = &arr[0],通过sizeof(p)获取的是指针的大小,而不是数组的大小。
  • 在函数中传入的数组其实是指针,无法用 sizeof 获取数组的元素个数,因此通常要另外传入一个表示长度的参数
  1. 结构体填充分析
1
2
3
4
5
struct Example {
    char a;
    int b;
};
printf("%zu\n", sizeof(struct Example)); // 可能是 8 而不是 5,因为字节对齐
  1. 获取字符串长度或数组长度
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
 
int main()
{
	int array[] = {5,2,4,6,1,3};
	char str[] = {"This is a string!"};
    int length = sizeof(array)/sizeof(*array);
	printf("The length of string '%s' is %d\n",str,sizeof(str)-1);
	printf("The length of array is %d\n",length);
    return 0;
}

输出结果:

1
2
The length of string 'This is a string!' is 17
The length of array is 6

注意事项

  • sizeof(arr) 对数组有效,但如果传入函数变成了指针,结果就不同。
  • sizeof("abc") 是 4,因为 "abc" 实际是 char[4],包含了结尾的 \0
  • 使用 %zu 来打印 sizeof 的结果,%lu%d 不一定安全(取决于平台)。
  • sizeof 是编译期进行计算,C99标准规定sizeof也可以在运行时刻进行计算
  • 针对结构体,结构类型变量的占用空间遵从字节对齐,且“空结构体”(不含数据成员)的大小不为0,而是1
  • 如果在定义数组时就给定了数组的大小,如int array[len];,则不管数组中初始化了多少个(显然应不大于len)元素,最后的数组中的元素个数都是len
本文由作者按照 CC BY 4.0 进行授权