C:sizeof运算符的一个陷阱

时间:2022-11-07 11:48:56

sizeof运算符通常用于获取变量或类型所占内存的大小(单位是字节)

#include <stdio.h>

struct D{
    char a;
    int b;
};

int main()
{
    int a = 0;
    struct D d;
    printf("sizeof(a)=%ld\n", sizeof(a));
    printf("sizeof(int)=%ld\n", sizeof(int));
    printf("sizeof(d)=%ld\n", sizeof(d));
    printf("sizeof(struct D)=%ld\n", sizeof(struct D));
    return 0;
}

运行程序输出:

sizeof(a)=4
sizeof(int)=4
sizeof(d)=8
sizeof(struct D)=8

使用此特性可以结合memset,对数据结构进行初始化:

#include <stdio.h>
#include <string.h>

struct D{
    char a;
    int b;
};

int main()
{
	D d;
	printf("before init:a=%d, b=%d\n", d.a, d.b);
	memset(&d, 0, sizeof(d));
	printf("after init:a=%d, b=%d\n", d.a, d.b);
    return 0;
}

运行程序输出:

before init:a=16, b=0
after init:a=0, b=0

不过在使用sizeof时需要注意,对于指针类型的变量,只会求值指针的大小,不会求值其指向内容的大小:

#include <stdio.h>

int main()
{
    char str[10] = {0};
    char* pStr = str;
    printf("sizeof(str)=%ld\n", sizeof(str));
    printf("sizeof(pStr)=%ld\n", sizeof(pStr));
    return 0;
}

运行程序输出:

sizeof(str)=10
sizeof(pStr)=8

这对于通过函数参数进行sizeof求值是一个陷阱:

#include <stdio.h>
#include <string.h>

void f(char *pStr)
{
	memset(pStr, 'a', sizeof(pStr));
	printf("pStr:%s sizeof(pStr)=%ld\n", pStr, sizeof(pStr));
}

int main()
{
    char str[10] = "123456789";
    printf("str:%s sizeof(str)=%ld\n", str, sizeof(str));
    f(str);
    return 0;
}

运行程序输出:

str:123456789 sizeof(str)=10
pStr:aaaaaaaa9 sizeof(pStr)=8

可见,在函数f内,通过指针pStr求值sizeof,获得的是指针的大小(64位系统上位8个字节),如果依据此指来初始化str,那么只能操作8个字节,也就导致了调用函数f后,str进入了一种混乱的状态,其内容为:aaaaaaaa9