当 0xFF 在 char 数组中时,它与下一个 char 一起被读取为整数
When 0xFF is in char array, it gets read as integer along with next char
我在 MS-DOS 上使用 C,特别是 Turbo C,在这里读取我的数字时遇到了一些奇怪的事情。我有一个名为 writeBitmap 的函数,它本质上采用具有路径、x 和 y 大小的结构,然后是精灵的偏移 sheet,以及一个使用此定义每个图像的数组。
我遇到的问题是,当我重复从文件中获取的缓存图像数据时,如果数组的输出以 FF 开头,它总是被读取为整数。我的意思是,如果我的数组中有一个 FF,当我使用 if 语句来测试它是否存在时,它的行为就像它正在读取一个包含 FF 的整数,然后连接下一个字符。这意味着我无法检测到 FF(顺便说一句,这是一个透明字节),因为只要它存在,它就会同时读取它和下一个字节,即使在转换为 char 时也是如此。
这是我的代码,我省略了一些东西,但最重要的是我有这些信息:
#include <dos.h>
#include <stdio.h>
/* define structs */
struct imageFile {
char path[16];
unsigned short size_x;
unsigned short size_y;
char offset;
};
/*define globals */
struct imageFile imgMap[1] =
{
{"./OUTP.DAT", 24, 24, 8}
};
这些是对函数很重要的变量,这是写的函数:
void writeBitmap(unsigned x, unsigned y, unsigned id){
int i, j, k;
int imgSize = (imgMap[id].size_x * imgMap[id].size_y); /*get size, init cache, and open file to offset*/
char *imgCache = (char *)malloc(imgSize);
FILE *fimg;
if(x + imgMap[id].size_x > 321 || y + imgMap[id].size_y > 201){
return;
}
fimg = fopen(imgMap[id].path, "rb");
fseek(fimg, (imgMap[id].offset * imgSize), SEEK_SET);
fread(imgCache, 1, imgSize, fimg);
fclose(fimg);
k = 0;
for(i = 0; i < imgMap[id].size_y; i++){
for(j = 0; j < imgMap[id].size_x; j++){
if((char)imgCache[k] != 0xFFFF){
/*setPixel(x + j, y + i, (char)imgCache[k]);*/
printf("%x ", imgCache[k]);
}/*else printf("TRANS: %x\n", imgCache[k]);*/
k++;
}
printf("\n");
}
}
setPixel 指的是另一个已知有效的函数。它只是计算图形模式 0x13 的段和偏移量,然后写入内存。
因此,我目前已将此代码设置为处于调试状态。如果它不是 0xFFFF,我让它打印一些东西,这消除了任何作为整数读取的东西。如果尝试消除任何 0xFF,它不会消除它。
这是屏幕输出:
如您所见,所有不是 0xFF 的内容都打印为 1 字节字符,但如果有 0xFF,它会被读取为整数以及下一个数据字节。
我不知道这怎么会发生。我感觉它可能是我动态分配的数组,但它是 char 类型的,并且每个数组成员一次读取的数据不应多于一个字节。
%x
格式说明符需要 int
。 printf() 包括将其参数默认提升为 int
。因此,除非您明确告诉它输入应被视为字符,否则它不会。 int
在您的系统上是 16 位,因此打印 2 个字节。
问题的根源在于 char
完全不适合用于除字符以外的任何内容。它具有实现定义的符号性——在 Turbo C 上它与带符号的 char 相同。因此,当您在其中存储大于 0x7F 的值时,您将调用实现定义的转换为 signed char
,以负值结束。
解决方案是改用 stdint.h
中的 uint8_t
。由于您使用的不是专业的标准 C 工具链,而是侏罗纪时期的非标准工具链,因此您必须 typedef unsigned char uint8_t
。
当你使用 uint8_t
/unsigned char
时,printf 转换为 int
时不会保留任何负号,你会得到预期的输出。
我在 MS-DOS 上使用 C,特别是 Turbo C,在这里读取我的数字时遇到了一些奇怪的事情。我有一个名为 writeBitmap 的函数,它本质上采用具有路径、x 和 y 大小的结构,然后是精灵的偏移 sheet,以及一个使用此定义每个图像的数组。
我遇到的问题是,当我重复从文件中获取的缓存图像数据时,如果数组的输出以 FF 开头,它总是被读取为整数。我的意思是,如果我的数组中有一个 FF,当我使用 if 语句来测试它是否存在时,它的行为就像它正在读取一个包含 FF 的整数,然后连接下一个字符。这意味着我无法检测到 FF(顺便说一句,这是一个透明字节),因为只要它存在,它就会同时读取它和下一个字节,即使在转换为 char 时也是如此。
这是我的代码,我省略了一些东西,但最重要的是我有这些信息:
#include <dos.h>
#include <stdio.h>
/* define structs */
struct imageFile {
char path[16];
unsigned short size_x;
unsigned short size_y;
char offset;
};
/*define globals */
struct imageFile imgMap[1] =
{
{"./OUTP.DAT", 24, 24, 8}
};
这些是对函数很重要的变量,这是写的函数:
void writeBitmap(unsigned x, unsigned y, unsigned id){
int i, j, k;
int imgSize = (imgMap[id].size_x * imgMap[id].size_y); /*get size, init cache, and open file to offset*/
char *imgCache = (char *)malloc(imgSize);
FILE *fimg;
if(x + imgMap[id].size_x > 321 || y + imgMap[id].size_y > 201){
return;
}
fimg = fopen(imgMap[id].path, "rb");
fseek(fimg, (imgMap[id].offset * imgSize), SEEK_SET);
fread(imgCache, 1, imgSize, fimg);
fclose(fimg);
k = 0;
for(i = 0; i < imgMap[id].size_y; i++){
for(j = 0; j < imgMap[id].size_x; j++){
if((char)imgCache[k] != 0xFFFF){
/*setPixel(x + j, y + i, (char)imgCache[k]);*/
printf("%x ", imgCache[k]);
}/*else printf("TRANS: %x\n", imgCache[k]);*/
k++;
}
printf("\n");
}
}
setPixel 指的是另一个已知有效的函数。它只是计算图形模式 0x13 的段和偏移量,然后写入内存。
因此,我目前已将此代码设置为处于调试状态。如果它不是 0xFFFF,我让它打印一些东西,这消除了任何作为整数读取的东西。如果尝试消除任何 0xFF,它不会消除它。
这是屏幕输出:
如您所见,所有不是 0xFF 的内容都打印为 1 字节字符,但如果有 0xFF,它会被读取为整数以及下一个数据字节。
我不知道这怎么会发生。我感觉它可能是我动态分配的数组,但它是 char 类型的,并且每个数组成员一次读取的数据不应多于一个字节。
%x
格式说明符需要 int
。 printf() 包括将其参数默认提升为 int
。因此,除非您明确告诉它输入应被视为字符,否则它不会。 int
在您的系统上是 16 位,因此打印 2 个字节。
问题的根源在于 char
完全不适合用于除字符以外的任何内容。它具有实现定义的符号性——在 Turbo C 上它与带符号的 char 相同。因此,当您在其中存储大于 0x7F 的值时,您将调用实现定义的转换为 signed char
,以负值结束。
解决方案是改用 stdint.h
中的 uint8_t
。由于您使用的不是专业的标准 C 工具链,而是侏罗纪时期的非标准工具链,因此您必须 typedef unsigned char uint8_t
。
当你使用 uint8_t
/unsigned char
时,printf 转换为 int
时不会保留任何负号,你会得到预期的输出。