当0xFF在char数组中时,它将与下一个char一起读取为整数

时间:2018-02-02 06:17:41

标签: c arrays char dos turbo-c

我在MS-DOS上使用C,特别是Turbo C,我遇到了一些奇怪的问题,我的数据正在这里阅读。我有一个名为writeBitmap的函数,它实质上是一个带有路径,x和y大小的结构,然后是一个sprite表的偏移量,以及一个用这个定义每个图像的数组。

我遇到的问题是,当我重申从文件中获取的缓存图像数据时,如果以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,它就不会消除它。

以下是屏幕输出:Screen output

正如您所看到的,非0xFF的所有内容都被打印为1字节字符,但如果有一个0xFF,则会将其读取为整数以及下一个数据字节。

我不知道这是怎么发生的。我有一种感觉,它可能是我动态分配的数组,但它的类型为char,并且它不应该读取每个数组成员一次多于一个字节的数据。

1 个答案:

答案 0 :(得分:2)

/* 1 */ { "23613" : { "_id" : "5a65a047992e3c2572f74102", "_class" : "com.vuelogix.location.model.LocationModel", "type" : "Feature", "properties" : { "address" : "Purna to Loha Rd, Maharashtra 431511, India", "device_id" : 23613.0, "last_updated" : "2018-01-22T08:26:47.237Z" }, "geometry" : { "_class" : "com.vuelogix.location.model.geojson.geometry.Point", "coordinates" : [ 77.065659, 19.145168 ], "type" : "Point" } } } /* 2 */ { "23658" : { "_id" : "5a65ae1e992e3c2572f74114", "_class" : "com.vuelogix.location.model.LocationModel", "type" : "Feature", "properties" : { "address" : "Taranagar - Churu Rd, Chalkoi Baneerotan, Rajasthan 331001, India", "device_id" : 23658.0, "last_updated" : "2018-01-22T09:25:50.893Z" }, "geometry" : { "_class" : "com.vuelogix.location.model.geojson.geometry.Point", "coordinates" : [ 74.956284, 28.497661 ], "type" : "Point" } } } 格式说明符需要%x。 printf()包括其int参数的默认参数提升。因此,除非您明确告诉它输入应该被视为char,否则它不会被激活。 int在您的系统上是16位,因此打印了2个字节。

问题的根源是int完全不适合用于除角色之外的任何事情。它具有实现定义的签名 - 在Turbo C上它与signed char相同。因此,当您在其中存储大于0x7F的值时,您将调用实现定义的转换为char,最终得到负值。

解决方案是使用signed char中的uint8_t代替。由于您没有使用专业标准C工具链,而是使用侏罗纪时期的非标准工具链,因此您必须使用stdint.h

当您使用typedef unsigned char uint8_t / uint8_t时,在printf转换为unsigned char时不会有任何负号保留,您将获得预期产出。