为什么 str[5]、str[] = "1234" 和 str = malloc(5) 有不同的大小?

Why do str[5], str[] = "1234" and str = malloc(5) have different sizes?

请考虑以下声明:

char str1[5];
char str2[] = "1234";
char *str3 = malloc(sizeof(char) * 5);

打印每个str的尺寸:

printf("str1 has size %ld\n", sizeof(str1));
printf("str2 has size %ld\n", sizeof(str2));
printf("str3 has size %ld\n", sizeof(str3));

输出是:

str1 has size 5
str2 has size 5
str3 has size 8

我了解到指针的大小是 8 个字节。 3种情况下,str是一个指针,*str对应字符串的第一个字符str:3种情况下,它的大小都是1个字节,也就是大小char.

如果我让程序用char str[] = "1234"char str[5];分配5个字节的内存给str,那么str的大小就是5个字节。但是当我用mallocchar *str分配5个字节时,str的大小还是8个字节,也就是一个指针的大小。我希望 str3 的大小与我用 malloc.

分配给它的内存量相对应

为什么我错了?

TL;DR -- Arrays are not pointers and vice-versa

在您的代码中,str1str2"arrays",而 str3 "pointer"。它们的尺寸是根据各自的类型印刷的。

    根据定义,
  • str1 有 5 个 char 元素。
  • str2 也有 5 个 char 元素,初始值设定项 + 空终止符。
  • str3是一个指针,所以sizeof(str3) === sizeof(char *) [注意:这取决于你的环境,它不是固定的,最常见的值是8(64 位 rach)和 4(32 位 arch)]

FWIW,使用 %zu 打印 sizeof 运算符的输出,因为它是 size_t.

类型

获取指针的大小得到的是指针的大小,而不是它指向的内容。你得到大小 8 意味着你在一个 64 位系统上,其中指针是 64 位(8 字节)。

数组是固定大小的内存块,在其上使用 sizeof 运算符将为您提供该块的大小。

char str[]="1234"

大小为 5,因为它是 str[5] = {'1','2','3','4',0}.

的语法糖
char str[5];

sizeof(char)*5 尺寸为 5。

char *str = ...;

大小为 8,因为它是一个指针。

比较这些代码片段

char str2[] = "1234";
char *p = str2;

char *p = malloc(sizeof(char) * 5);

它们的共同点如下:指针p指向已分配内存的第一个字节。在第一种情况下,内存由编译器分配,在第二种情况下,内存由您在堆中分配。

为了更清楚,最好考虑 C++ 中的类似代码片段。它们看起来像

char str2[] = "1234";
char *p = str2;

char *p = new char[5];

你将拥有

第一个代码片段

printf( "%zu\n", sizeof( str2 ) ); // 5
printf( "%zu\n", sizeof( p ) ); // 8

第二个代码片段

printf( "%zu\n", sizeof( char[5] ) ); // 5
printf( "%zu\n", sizeof( p ) ); // 8

不同之处在于,在第二种情况下,我们没有创建的动态数组的名称。所以你必须使用 sizeof( char[5] ) 而不是 sizeof( array_name ).