关于sizeof的使用问题

发布于 2024-08-27 02:32:57 字数 844 浏览 10 评论 0原文

问题 1

我有一个这样的结构,

struct foo
{
    int a;
    char c;
};

当我说 sizeof(foo) 时,我的机器上得到 8 。根据我的理解,4 个字节用于 int,1 个字节用于 char,3 个字节用于填充。这是正确的吗?给定一个像上面这样的结构,我如何知道将添加多少字节作为填充?

问题2

我知道sizeof可以用来计算数组的大小。大多数情况下,我见过这样的用法 (foos is an array of foo)

sizeof(foos)/sizeof(*foos)

但我发现以下内容也会给出相同的结果。

sizeof(foos) / sizeof(foo)

这两者有什么区别吗?哪一个是首选?

问题 3

考虑以下陈述。

foo foos[] = {10,20,30};

当我执行 sizeof(foos) / sizeof(*foos) 时,它给出 2。但是该数组有 3 个元素。如果我将语句更改为

foo foos[] = {{10},{20},{30}};

它会给出正确的结果 3. 为什么会发生这种情况?

有什么想法..

Question 1

I have a struct like,

struct foo
{
    int a;
    char c;
};

When I say sizeof(foo), I am getting 8 on my machine. As per my understanding, 4 bytes for int, 1 byte for char and 3 bytes for padding. Is that correct? Given a struct like the above, how will I find out how many bytes will be added as padding?

Question 2

I am aware that sizeof can be used to calculate the size of an array. Mostly I have seen the usage like (foos is an array of foo)

sizeof(foos)/sizeof(*foos)

But I found that the following will also give same result.

sizeof(foos) / sizeof(foo)

Is there any difference in these two? Which one is preferred?

Question 3

Consider the following statement.

foo foos[] = {10,20,30};

When I do sizeof(foos) / sizeof(*foos), it gives 2. But the array has 3 elements. If I change the statement to

foo foos[] = {{10},{20},{30}};

it gives correct result 3. Why is this happening?

Any thoughts..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

燃情 2024-09-03 02:32:57

回答 1

是的 - 您的计算是正确的。在您的计算机上,sizeof(int) == 4int 必须是 4 字节对齐。

您可以通过手动添加基本元素的大小并从 sizeof() 报告的大小中减去该值来了解填充。如果您了解机器上的对齐要求,则可以预测填充量。请注意,有些机器非常挑剔,当您访问未对齐的数据时会出现 SIGBUS 错误;其他的则更宽松,但当您访问未对齐的数据时会减慢您的速度(并且它们可能支持“#pragma Pack”或类似的内容)。通常,基本类型的大小是 2 的幂 (1, 2, 4, 8, 16),并且类似的 n 字节类型必须是 n 字节对齐的。另外,请记住,必须填充结构,以便结构数组将使所有元素正确对齐。这意味着结构通常会被填充到结构中最严格对齐的成员的大小的倍数。

答案 2

一般来说,第一个的变体更好;当您将数组的基本类型从“foo”更改为“foobar”时,它仍然是正确的。我通常使用的宏是:

#define DIM(x) (sizeof(x)/sizeof(*(x)))

其他人对相同的基本操作有不同的名称 - 你可以将我使用的名称归结为来自昏暗和遥远的过去的污染以及对 BASIC 的一些使用。

像往常一样,有一些警告。最值得注意的是,您不能将其有意义地应用于函数的数组参数或动态分配的数组(使用 malloc() 等或 new[]);您已应用于数组的实际定义。通常该值是编译时常量。在 C99 下,如果数组是 VLA(可变长度数组),则可以在运行时对其进行评估。

答案 3

因为当你没有足够的大括号时初始化的工作方式。您的“foo”结构必须有两个元素。 10和20分配到第一行; 30 和隐式 0 被提供给第二行。因此大小是二。当您提供子大括号时,数组中有 3 个元素,其中第一个组件的值为 10、20、30,第二个组件的值全部为零。

Answer 1

Yes - your calculation is correct. On your machine, sizeof(int) == 4, and int must be 4-byte aligned.

You can find out about the padding by manually adding the sizes of the base elements and subtracting that from the size reported by sizeof(). You can predict the padding if you know the alignment requirements on your machine. Note that some machines are quite fussy and give SIGBUS errors when you access misaligned data; others are more lax but slow you down when you access misaligned data (and they might support '#pragma packed' or something similar). Often, a basic type has a size that is a power of 2 (1, 2, 4, 8, 16) and an n-byte type like that must be n-byte aligned. Also, remember that structures have to be padded so that an array of structures will leave all elements properly aligned. That means the structure will normally be padded up to a multiple of the size of the most stringently aligned member in the structure.

Answer 2

Generally, a variant on the first is better; it remains correct when you change the base type of the array from a 'foo' to a 'foobar'. The macro I customarily use is:

#define DIM(x) (sizeof(x)/sizeof(*(x)))

Other people have other names for the same basic operation - and you can put the name I use down to pollution from the dim and distant past and some use of BASIC.

As usual, there are caveats. Most notably, you can't apply this meaningfully to array arguments to a function or to a dynamically allocated array (using malloc() et al or new[]); you have apply to the actual definition of an array. Normally the value is a compile-time constant. Under C99, it could be evaluated at runtime if the array is a VLA - variable-length array.

Answer 3

Because of the way initialization works when you don't have enough braces. Your 'foo' structure must have two elements. The 10 and the 20 are allocated to the first row; the 30 and an implicit 0 are supplied to the second row. Hence the size is two. When you supply the sub-braces, then there are 3 elements in the array, the first components of which have the values 10, 20, 30 and the second components all have zeroes.

念三年u 2024-09-03 02:32:57
  1. 填充通常与 hist CPU 上的寄存器大小有关 - 在您的情况下,您有一个 32 位 CPU,因此 int 的“自然”大小是 4 个字节。 CPU 访问小于此大小的内存量会更慢且更困难,因此通常最好将值对齐到 4 字节边界。因此,该结构的大小为 4 字节的倍数。大多数编译器将允许您修改所使用的填充量(例如使用“#pragma”),但这仅应在结构的内存占用绝对关键的情况下使用。

  2. “*foos”引用 foos 数组中的第一个条目。 “foo”引用该类型(的单个实例)。所以它们本质上是相同的。我自己会使用 sizeof(type) 或 sizeof(array[0]),因为 *array 更容易误读。

  3. 在第一个示例中,您没有正确初始化数组条目。您的结构有 2 个成员,因此您必须使用 { a, b } 来初始化数组的每个成员。因此,您需要 { {a, b}, {a, b}, {a, b} } 的形式来正确初始化条目。

  1. The padding is usually related to the size of the registers on the hist CPU - in your case, you've got a 32-bit CPU, so the "natural" size of an int is 4 bytes. It is slower and more difficult for the CPU to access quantities of memory smaller than this size, so it is generally preferable to align values onto 4-byte boundaries. The struct thus comes out as a multiple of 4 bytes in size. Most compilers will allow you to modify the amount of padding used (e.g. with "#pragma"s), but this should only be used where the memory footprint of the struct is absolutely critical.

  2. "*foos" references the first entry in the foos array. "foo" references (a single instance of) the type. So they are essentially the same. I would use sizeof(type) or sizeof(array[0]) myself, as *array is easier to mis-read.

  3. In your first example, you are not intialising the array entries correctly. Your struct has 2 members so you must use { a, b } to initialise each member of the array. So you need the form { {a, b}, {a, b}, {a, b} } to correctly initialise the entries.

奢欲 2024-09-03 02:32:57

要了解有多少填充,只需将结构中每个元素的 sizeof() 相加,然后从整个结构的 sizeof() 中减去该总和。

您可以使用 offsetof() 来准确找出更复杂的结构中填充的位置。这可以帮助您通过重新排列元素来填补漏洞,从而减少整个结构的大小。

通过手动插入填充元素来显式对齐结构元素是一种很好的做法,这样可以保证每个元素“自然对齐”。您可以在将来重复使用这些填充元素以获取有用的数据。如果您编写的库需要稳定的 ABI,那么这将是一项必需的技术。

To find out how much padding you have, simply add up the sizeof() each element of the structure, and subtract this sum from the sizeof() the whole structure.

You can use offsetof() to find out exactly where the padding is, in more complex structs. This may help you to fill holes by rearranging elements, reducing the size of the struct as a whole.

It is good practice to explicitly align structure elements, by manually inserting padding elements so that every element is guaranteed to be "naturally aligned". You can reuse these padding elements for useful data in the future. If you ever write a library that will require a stable ABI, this will be a required technique.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文