我写了一个函数,用于从HZK16字库中提取字模:
#include <stdio.h>
#include <stdint.h>
uint16_t *
get_bitmap_font(long offset, const unsigned char *str, uint16_t *data)
{
unsigned offset_size = 16 * 16 / 8;
unsigned code_point = (str[0] - 0xA1) * 94 + (str[1] - 0xA1);
if (str[0] >= 0xA1) {
offset += code_point * offset_size;
} else {
offset += (str[0] + 156 - 1) * offset_size;
}
FILE *fp = fopen("HZK16", "rb");
fseek(fp, offset, SEEK_SET);
printf("before fread: 0x%x 0x%x\n", str[0], str[1]);
/* 比方说,我提供的参数 str 是一个 GB2312 字符“金” */
/* 那么此处输出就是对应的编码:0xbd 0xf0 */
fread(data, sizeof(*data), offset_size, fp);
printf(" after fread: 0x%x 0x%x\n", str[0], str[1]);
/* 输出居然变成了 0x0 0x1 */
fclose(fp);
fp = NULL;
return data;
}
int
main(void)
{
unsigned char *str = "\xbd\xf0";
uint16_t font_data[16];
get_bitmap_font(0, str, font_data);
for (int row = 0; row < 16; row++) {
for (int col = 7; col >= 0; col--) {
fputs(((font_data[row] >> col) & 1)? "@@": " ", stdout);
}
for (int col = 15; col >= 8; col--) {
fputs(((font_data[row] >> col) & 1)? "%%": " ", stdout);
}
putchar('\n');
}
}
return 0;
}
运行之后,发现这个函数的行为和预期的不同。在检查的过程中,加上了上面的两个printf
,发现fread
前后str
指向的内容居然变了!
但是fread
的调用当中并未提到str
啊?求解释…
附上点阵字体:
https://github.com/aguegu/BitmapFont/blob/master/font/HZK16
get_bitmap_font
是如何调用的?你向
data
指向的空间写了64个bytes, 是否溢出?data
如果没有64, 且str
的空间和data
在一起(比如都在上一层栈中), 那么就把str
复写了.