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-1
和 0..j-1
的二维数组。访问 triple[i][j]
是未定义的行为;这就是为什么你的第二个解决方案失败了。
但是,您不需要 RGBTRIPLE
的整个数组,因为您一次只处理一个。这就是您的第一个解决方案有效的原因。
如果您需要读取整个数组,请在 之前 具有正确维度的外循环声明它:
RGBTRIPLE triple[abs(bi.biHeight)][abs(bi.biWidth)];
请谨慎使用此解决方案,因为您可能会因 bi.biHeight*bi.biWidth
.
的非常大的值而导致崩溃
我在 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-1
和 0..j-1
的二维数组。访问 triple[i][j]
是未定义的行为;这就是为什么你的第二个解决方案失败了。
但是,您不需要 RGBTRIPLE
的整个数组,因为您一次只处理一个。这就是您的第一个解决方案有效的原因。
如果您需要读取整个数组,请在 之前 具有正确维度的外循环声明它:
RGBTRIPLE triple[abs(bi.biHeight)][abs(bi.biWidth)];
请谨慎使用此解决方案,因为您可能会因 bi.biHeight*bi.biWidth
.