【问题标题】:Why do str[5], str[] = "1234" and str = malloc(5) have different sizes?为什么 str[5]、str[] = "1234" 和 str = malloc(5) 的大小不同?
【发布时间】:2017-11-21 16:43:15
【问题描述】:

请考虑以下声明:

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];str 分配5 个字节的内存,那么str 的大小是5 个字节。但是当我用mallocchar *str分配5个字节时,str的大小还是8个字节,也就是一个指针的大小。我希望str3 的大小与我使用malloc 分配给它的内存量相对应。

为什么我错了?

【问题讨论】:

  • 因为前两个是五个chars的数组,而最后一个是指针。分配给str3 的内容无关紧要,sizeof 的结果不会改变。
  • sizeof 不会告诉你数据的大小;只是 type 的大小。 sizeof char[5]5sizeof char[100] 为 100。sizeof char * 始终为 8(在您的机器上);

标签: c arrays pointers sizeof


【解决方案1】:

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

在您的代码中,str1str2“数组”str3“指针”。它们的尺寸根据各自的类型打印。

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

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

【讨论】:

  • @nounoursnoir 不,他们不是。参见 C-FAQ,第 6 章。
  • @nounoursnoir 数组可以衰减指向其第一个元素的指针(例如,将数组传递给函数时会发生这种情况),但它本身不是指针。
  • 哦,好吧,这是我错过的重要事情。求你的答案
  • @nounoursnoir 数组是一组相同类型的项目,它们彼此相邻地存储在内存中(如果需要,它们之间可以填充)。指针是一个变量,用于将某些数据的地址存储在内存中。它们是完全不同的概念。但是,在 C 中,在某些情况下,可以在需要指针的地方使用数组。数组第一个元素的地址就是这个伪指针的值。
【解决方案2】:

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

数组是固定大小的内存块,使用 sizeof 运算符可以得到该块的大小。

【讨论】:

  • 好吧...使用sizeof(*str)输出我1
  • @nounoursnoir 嗯,这是因为当您取消引用数组时,它会衰减为指向其第一个元素的指针,并且您取消引用该指针,该指针会为您提供指针指向的 value .在您的情况下,它是一个类型为char 的字符。所以sizeof(*str) 等于sizeof(str[0]) 等于sizeof(char) 被指定为始终为1
【解决方案3】:
char str[]="1234"

大小为 5,因为它是 str[5] = {'1','2','3','4',0} 的语法糖。

char str[5];

大小为 5,因为它是 sizeof(char)*5

char *str = ...;

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

【讨论】:

    【解决方案4】:

    比较这些代码sn-ps

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

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

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

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

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

    char *p = new char[5];
    

    你将拥有

    对于第一个代码sn-p

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

    对于第二个代码sn-p

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

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

    【讨论】:

      最近更新 更多