memset是C标准库的一个函数,其原型可以在string.h中找到。过多的介绍就不用了, 直接进入主题。
依然是数字图像处理的学习过程中遇到的一个问题。我在写BMP图像处理的时候, 考虑到BMP有灰度图像和彩色图像之分, 在BMP_get_Pixel_at函数中使用了memcpy和memset。代码如下:
BOOL BMP_get_Pixel_at( const BMP *image, const long row, const long col, PIXEL *pixel )
{
int height = BMP_get_Height( image ); //图像高度
int width = BMP_get_Width( image ); //图像像素宽度
int pixelBytes = BMP_get_PixelBits(image)/8; //每像素字节数
int padwidth = (width+3)/4*4; //填充后的像素宽度
if( row>=height || col>=width )
{
printf( "错误:(%d,%d)数据越界!\n",row,col );
return FALSE;
}
//从图像的像素位置读取pixelBytes字节数据,剩下的部分由0填充
memcpy( (void *)pixel, (void *)( image->data+(row*padwidth+col)*pixelBytes ), pixelBytes );
memset( (void *)(pixel+pixelBytes), 0, sizeof(PIXEL)-pixelBytes );
return TRUE;
}
其中 PIXEL 是Windows.h中的结构体 RGBQUAD 的一个别名,RGBQUAD的定义如下:
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
如上面的代码所示,int pixelBytes = BMP_get_PixelBits(image)/8; 保存图片的每像素的字节数。
既然这样,不管图像每像素字节数是多少,
memcpy( (void *)pixel, (void *)( image->data+(row*padwidth+col)*pixelBytes ), pixelBytes );
一句是可以读取一个像素的数据到pixel中的,尽管pixel的大小是4个字节。
显然,pixel的剩余部分要用0来填充。于是很理所当然的使用了
memset( (void *)(pixel+pixelBytes), 0, sizeof(PIXEL)-pixelBytes );
一句。
可以看见,位置偏移,数据数目都正确设置了。结果却出人意料,最后一句(指memset一句)却除了问题。
要知道,要定位到一个库函数出问题,是需要多门长时间的调试。反正,最终,问题被锁定在memset一句上面。大家可以看看锁定过程。
#include
#include
#include
typedef RGBQUAD PIXEL;
typedef struct ACB
{
int a;
char b;
int c;
} ACB;
int main( int argc, char *argv[] )
{
FILE *fp = NULL;
PIXEL pixel;
int n;
ACB acb;
acb.a = 0x99;
acb.b = 'a';
acb.c = 0x9;
fp = fopen( "acb.data", "w" );
n = fwrite( (void *)&acb, sizeof(char), 1, fp );
memset( (void *)&pixel, 23, 3 );
memset( (void *)((&pixel)+3), 0, sizeof(PIXEL)-3 );
n = fwrite( (void*)&pixel, sizeof(char), 2, fp );
fclose( fp );
return 0;
}
为了节省空间,我省略了代码中的所有空行。