C 中的结构

Structures in C

我在 PSET4(侦探侦探)中遇到了问题。我真的不明白为什么在下面的下一个案例中会出现错误,尽管编译不会发出警告。

在这个问题中,我应该读取给定 .bmp 文件的每个像素,用白色像素替换每个红色像素,然后在新的 .bmp 文件中写入新图像。

这是我的代码的两个版本。在第一个列表中有一个正确版本的代码,并且程序可以正常运行,正如我所希望的那样。在第二个清单中有一个代码示例,已成功编译,但像素仍然相同,或者发生了一些奇怪的事情。

正确版本

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

        // read RGB triple from infile
        fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
        if((triple.rgbtRed == 0xff) && (triple.rgbtGreen == 0x00) && (triple.rgbtBlue == 0x00))
        {
            triple.rgbtBlue = 0xff;
            triple.rgbtGreen = 0xff;
            triple.rgbtRed = 0xff;
        }

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

版本不正确

// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
    // iterate over pixels in scanline
    for (int j = 0; j < bi.biWidth; j++)
    {                                                  //INCORRECT VERSION
        // temporary storage
        RGBTRIPLE triple[i][j];

        // read RGB triple from infile
        fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
        if((triple[i][j].rgbtRed == 0xff) && (triple[i][j].rgbtGreen == 0x00) && (triple[i][j].rgbtBlue == 0x00))
        {
            triple[i][j].rgbtBlue = 0xff;
            triple[i][j].rgbtGreen = 0xff;
            triple[i][j].rgbtRed = 0xff;
        }

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

根据 "arrays" 课程(以 CS50 中的 "students" 结构为例),需要为数组和结构变量包含索引 [i] 和 [j] "for"-循环执行。但在这种情况下,如果我将这些索引放入代码中,一切都会变得无效。如果我不写那些索引,一切都很好。为什么这个逻辑会在这里中断,有结构?

当您声明 RGBTRIPLE triple[i][j]; 时,您会创建一个具有有效索引 0..i-10..j-1 的二维数组。访问 triple[i][j] 是未定义的行为;这就是为什么你的第二个解决方案失败了。

但是,您不需要 RGBTRIPLE 的整个数组,因为您一次只处理一个。这就是您的第一个解决方案有效的原因。

如果您需要读取整个数组,请在 之前 具有正确维度的外循环声明它:

RGBTRIPLE triple[abs(bi.biHeight)][abs(bi.biWidth)];

请谨慎使用此解决方案,因为您可能会因 bi.biHeight*bi.biWidth.

的非常大的值而导致崩溃