为什么可以在嵌套循环中声明STRUCT呢?

时间:2019-09-14 19:20:02

标签: c cs50

这是一些提供的(CS50)代码的片段,这些代码在嵌套循环中一遍又一遍地声明相同的STRUCT“三元组”。为什么这样可以呢?在我看来,将STRUCT“三元组”声明为嵌套循环的范围上方并在每次迭代中更改值会更有效。

typedef struct
{
    BYTE rgbtBlue;
    BYTE rgbtGreen;
    BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;

 for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
    // iterate over pixels in scanline
    for (int j = 0; j < bi.biWidth; j++)
    {
        // temporary storage
        RGBTRIPLE triple;

        // read RGB triple from infile
        fread(&triple, sizeof(RGBTRIPLE), 1, inptr);

        // write RGB triple to outfile
        fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
    }

3 个答案:

答案 0 :(得分:8)

在大多数情况下,此级别的效率是编译器关心的问题。编译器可以为每个RGBTRIPLE重新使用相同的堆栈空间! (尽管不是必须的。)

将RGBTRIPLE放入需要它的最小括号对(范围)内,可以防止当变量的内容可能无效时,意外,错误地访问该范围之外的变量。

答案 1 :(得分:3)

  

还是,同一声明的数千次迭代是否比第一个循环之前的单个声明要好?

当然可以。无论哪种方式,一个好的编译器都不会发出具有任何性能差异的代码。

适度的 linear 性能更改可能会导致减少调用fread()的次数。

for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++) {
    RGBTRIPLE triple[bi.biWidth];
    fread(triple, sizeof triple, 1, inptr);
    fwrite(triple, sizeof triple, 1, outptr);
}

甚至

RGBTRIPLE triple[biHeight][bi.biWidth];
fread(triple, sizeof triple, 1, inptr);
fwrite(triple, sizeof triple, 1, outptr);

很多因素都在编码考虑中。避免专注于此类微优化。

答案 2 :(得分:2)

这里要理解的重要一点是,语句RGBTRIPLE triple;声明了变量,但并不直接对应于“正在创建存储”,或者实际上根本没有翻译成任何机器语言输出。

您只是向编译器声明此变量的范围和用法(并且在最局部的块内进行声明是一种仅表示您希望其在该区域内有效的良好做法)。您可以将此行放在循环之外或函数的顶部,而无需更改可执行输出。

编译器的工作是在堆栈上有效地创建空间,以便在运行时使用局部变量。实际上,它将简单地重复使用相同的空间来进行每次循环迭代。 (这里的人会正确地告诉您,这不是保证的行为,从技术上讲是正确的,但实际上,它将始终重用相同的空间,就像您在循环上方声明它一样。 )