为什么这个函数返回的值不同于我内联的函数?

时间:2016-02-10 17:43:15

标签: c++ function visual-c++ bitmap

从.NET高回来,想要制作一个更快,更高效的图像库我想我会尝试手动完成所有操作最大控制 空气 学习经验,你知道吗?

所以,我正在阅读一些测试位图(.bmp扩展名)。在读取一些位图文件头时,我注意到大小块给了我负值。

我设法在某种程度上追查了这个问题,但我在调试方面并不是那么出色。当我用同一块代码替换我的get_u32函数 - 内联 - 它给了我正确的大小。我想有一些隐式的类型转换正在进行中,但我无法说清楚。

这是相关代码

typedef struct IMGLIB_API{
    unsigned short type;
    unsigned long size;
    unsigned short reserved1;
    unsigned short reserved2;
    unsigned long offbits;
} BITMAP_FILE_HEADER;

unsigned short get_u16(char b0, char b1){
    return ((b1 << 8) | b0);
}

unsigned long get_u32(char b0, char b1, char b2, char b3){
    return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
}

IMAGE_DATA bitmap_loader(const char* file_path){
    IMAGE_DATA r;
    ifstream ifs;
    const unsigned short valid_formats[] = {
        16973, // BM - Windows 3.1x, 95, NT, ...
        16961, // BA - OS/2 struct bitmap array
        17225, // CI - OS/2 struct color icon
        17232, // CP - OS/2 const color pointer
        18755, // IC - OS/2 struct icon
        20564  // PT - OS/2 pointer
    };
    const int BMP_FILE_HEADER_SIZE = 14;

    ifs.open(file_path, ifstream::in | ifstream::binary);
    unsigned char* rhead = new unsigned char[BMP_FILE_HEADER_SIZE];
    ifs.read((char*)rhead, BMP_FILE_HEADER_SIZE);

    BITMAP_FILE_HEADER bmp_header;
    bmp_header.type = get_u16(rhead[0], rhead[1]);
    bmp_header.size = get_u32(rhead[2], rhead[3], rhead[4], rhead[5]); // - doesn't work
    //bmp_header.size = (rhead[5] << 24) | (rhead[4] << 16) | (rhead[3] << 8) | rhead[2]; // - works
    bmp_header.reserved1 = get_u16(rhead[6], rhead[7]);
    bmp_header.reserved2 = get_u16(rhead[8], rhead[9]);
    bmp_header.offbits = get_u32(rhead[10], rhead[11], rhead[12], rhead[13]); // correct, reports 54 bytes

    // TODO: check if valid bitmap type
    // TODO: read the dib header
    // TODO: read in pixel data and decompress (if needed)

    r.size = bmp_header.size;
    r.type = img_type::IM_BITMAP;

    ifs.close();
    delete rhead;
    rhead = 0;
    return r;
}

例如,当加载大小为86 454字节的特定位图时,使用函数get_u32时得到-74。我认为将return设置为unsigned,而struct member设置为unsigned意味着它不能被..签名。最好将自己重命名为Snow,因为显然我什么都不知道抱怨

随意提供有关优化/更好方法的一些提示。

1 个答案:

答案 0 :(得分:2)

char可以是已签名或未签名的。转换为更大类型符号时的签名字符扩展。当你对char进行数学运算时,它会转换为int,这是一个更大的类型。

进行位操作时,默认为unsigned。

unsigned short get_u16(char b0, char b1){
  return ((b1 << 8) | b0);
}

是问题的一个例子。 b0可以延长标志。

实现可以将char视为已签名或未签名。