sizeof运算符的行为?

时间:2013-08-14 18:19:49

标签: c pointers struct sizeof

#include<stdio.h>
struct krishna {
        int i,j,k,l,m;
    char c;
    double d;
    char g[48];
};
int main() {
struct krishna *me={0};
printf("%ld %ld\n",sizeof(me),sizeof(*me));//output is 8 80 how??
return 0;
}

大家好,我是新手,我使用的编译器是gcc编译器,在上面的代码中可以解释为什么

1)指针无论是否分配任何类型8?

2)上面结构的大小是80?任何人都可以向我解释任何结构如何确定结构大小,每次我期待一个值但我得到一个不同的答案时我会感到困惑,我也在堆栈溢出中读到其他问题和答案,我和仍然没有得到它。请帮助。

4 个答案:

答案 0 :(得分:3)

这是因为:

sizeof( me ) // is a pointer.

... me是一个指针。指针的大小是环境中单词的倍数,因此在32位环境中指针是4个字节是常见的,而在64位环境中,指针是8个字节(但不是一成不变的)。如果你要回去几年,16位环境就会有一个2字节的指针。查看下一个sizeof

sizeof( *me ) // is a struct krishna, hence 80 bytes are needed to store it in memory.

...是一个结构,结构krishna的大小是80个字节。如果你看一下结构:

struct krishna {
  int i,j,k,l,m; // sizeof( int ) * 5
  char c; // sizeof( char ) * 1
  double d; // sizeof( double ) * 1
  char g[48]; // sizeof( char ) * 48
  // padding for memory address offset would be here.
};

...如果你将每个字段所需的字节数加起来并包含适当的data structure alignment作为内存地址偏移量,那么它将总共80个字节(如预期的那样)。添加额外3个未使用字节的原因是因为要将结构存储在内存中,它必须位于为结构分配的连续内存块中。出于性能原因,它将填充任何大小问题,以确保内存地址始终是单词的倍数。为了提高性能,3字节的权衡是值得的,现在3个字节不像处理器在保证数据对齐时的性能改进那样有影响力。

答案 1 :(得分:3)

所有指针都是地址,并且给定系统上的所有地址大小相同,通常是32位系统上的4个字节和64位系统上的8个字节。由于你得到8,你必须使用64位系统。

结构的大小取决于编译器如何将结构的各个字段“打包”到一个内存块中以包含整个结构。在您的情况下,您的结构有5个int字段(每个4字节),一个char字段(1个字节),一个双字段(8个字节)和一个48字符数组。添加所有这些,你得到20 + 1 + 8 + 48 = 77字节来存储你的数据。实际大小为80,因为编译器使用3个额外的未使用字节“填充”1字节字符字段,以便将结构中的所有字段与4字节内存地址对齐,这是良好性能所需的。

希望有所帮助!

答案 2 :(得分:3)

printf("%ld %ld\n",sizeof(me),sizeof(*me));//output is 8 80 how??

实际上应该是:

printf("%zu %zu\n",sizeof(me),sizeof(*me));//output is 8 80 how??

"%zu"size_t值的正确格式字符串,例如您从sizeof获得的值。 "%ld"可能会在某些系统上运行(显然它会在你的系统上运行),但你不应该指望它。

如果您的编译器不支持"%zu",您可以使用"%lu"(需要unsigned long参数)并显式转换参数:

printf("%lu %lu\n", (unsigned long)sizeof(me), (unsigned long)sizeof(*me));

8获得sizeof(me),因为这恰好是您正在使用的编译器上的指针的大小(8字节,64位)。如果您在不同的系统上编译和运行程序,则可能会得到4,因为许多系统都有32位指针。 (这假定一个字节是8位,大多数系统都是如此,但语言无法保证。)

大多数编译器使所有指针的大小相同,但语言也无法保证。例如,在字寻址机器上,int*指针可能只是一个机器级地址,但char*指针可能需要额外的信息来指定它所指向的字中的哪个字节。您不太可能遇到具有不同指针大小的系统,但仍然没有必要假设所有指针都是相同的大小。

至于结构的大小,也可能因编译器而异。这是你的结构:

struct krishna {
    int i,j,k,l,m;
    char c;
    double d;
    char g[48];
};

char总是正好是1个字节,char[48]总是正好是48个字节。

int中的字节数可能因系统而异;这些天最常见的是4个字节。

double的大小通常为8个字节,但这也可能有所不同(尽管我认为我从未见过sizeof (double)不是8个字节的系统。)< / p>

结构成员按照声明的顺序排列,因此i将位于结构的最开头,然后是jk,等等。

最后,编译器通常会在成员之间或最后一个成员之后插入填充字节,以便每个成员都正确对齐。例如,在许多系统上,4字节int需要在偏移量上对齐,该偏移量是4个字节的倍数;如果它未对齐,访问它可能会很慢和/或非常困难。

事件sizeof (struct krishna)恰好是系统上的80字节并不是那么重要。更重要的是要理解(a)编译器用于确定结构布局的一般规则,以及(b)这些规则可能导致不同系统的不同布局。

语言定义和编译器保证您可以拥有类型为struct krishna的对象,并且您可以访问这些对象及其成员,获取存储在其中的任何值。如果您需要知道struct krishna有多大,答案就是sizeof (struct krishna)。如果由于某种原因,您需要了解更多详细信息(例如,如果您需要匹配一些外部强加的布局),您可以进行一些实验和/或查阅编译器的文档 - 但请注意具体细节将适用仅适用于您正在使用它的系统上使用的编译器。 (系统的ABI通常会限制编译器的选择。)

您还可以使用sizeofoffsetof(查找)查找每个成员的分配位置。

答案 3 :(得分:0)

只需添加@Jacob Pollack和@ObjetDart的答案,您就可以在Structure padding in C找到有关结构填充的更多信息。