gpt4 book ai didi

c - 是在函数内部重新声明结构体还是将其声明为静态并每次都设置为 0 更好?

转载 作者:行者123 更新时间:2023-11-30 16:09:40 25 4
gpt4 key购买 nike

基本上,如果我有一个像这样的结构:

struct header {
char ptr[512];
};

我有一个像这样的函数:

void some_function() {
struct header header = { 0 };

// do something with struct
}

这样做实际上对性能有好处吗:

void some_function() {
static struct header header;

memset((char *)&header, 0, sizeof(header));
// do something with struct
}

我知道如果结构包含指针,memset 并不总是有效,因为 NULL 可能不位于地址 0x0000,但对于这种情况,当这并不重要时,更好的方法是什么?

最佳答案

如果 C 程序指定了实际的静态对象或在堆栈上自动分配的对象,则这两段代码的性能几乎相同。根据处理方式的不同,可能会存在微小的性能差异,或者根据相对于其他数据和缓存属性的分配位置,可能会存在一些性能差异。 (特别是,自动版本可能具有更好的属性,因为内存不是专门为结构保留的。在执行其他函数而不是 some_function 时,它将与其他数据共享,因此它可能驻留在更频繁地进入缓存并导致更少的内存访问。此外,由于它将与其他函数共享,因此整个程序总体上可能使用更少的内存,从而提高性能。)

但是,C 程序并不直接指定计算机必须执行的操作(尽管某些 C 实现可能会以这种方式实现或具有开关来执行此操作,或类似的操作)。根据 C 标准,C 程序在抽象机中指定虚数计算。 C 编译器的工作是将计算转换为真实机器的程序。它被赋予了很大的自由度来这样做。

这意味着,如果编译器查看并充分分析足够多的源代码,以发现该函数的两个版本的行为相同(就可观察的行为而言),它可以将它们翻译成相同的代码。 (可观察的行为包括输入和输出交互、对 volatile 对象的访问以及写入文件的数据。)在这种情况下,不存在性能差异。

如果有的话,自动版本更容易让编译器分析。它知道当函数结束时,自动对象将消失(在抽象机中)。尽管在这两种情况下,您都会在函数开始时清除对象,因此编译器(假设已内置有关 memset 的知识)知道每次函数启动时对象都会在这方面重新开始,还有编译器编写者必须担心的行为可能不同的其他方式。例如,如果获取静态结构的地址,特别是如果将其传递给任何其他例程,则编译器必须担心其中的数据可能会在函数返回后被保留了静态结构的其他代码使用。它的地址。相反,对于自动结构,编译器的行为可能就像函数返回后从未​​使用自动对象一样,因为在抽象机中,当函数返回时它不再存在。 (因此,如果任何其他代码确实保留了其地址,则该地址的使用不是由 C 标准定义的,并且编译器不必为其执行任何操作。)

因此,除了在深奥的情况下或仅仅是内存和缓存行为的偶然情况之外,我们通常可以期望自动版本至少与静态版本一样好。

一般来说,编写软件来表达您需要的内容,并且仅表达您需要的内容。如果一个对象不需要在函数的生命周期之外持续存在,那么就将其保留为自动对象,并且不要将其设为静态。

请注意,通常没有必要将所有此类结构归零,因为:

  • 所使用的结构部分可能用长度或标记(例如标记结束的空字符)来指示,因此没有软件会尝试读取任何后续部分,因此无需初始化它。
  • 或者,如果要读取所有结构,则可以将软件设计为填充非零部分,然后仅将剩余部分归零,而不是首先将整个结构归零。

关于c - 是在函数内部重新声明结构体还是将其声明为静态并每次都设置为 0 更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59075479/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com