C Little endian约定,并保存到二进制文件

C Little endian约定,并保存到二进制文件,c,linux,system-calls,endianness,C,Linux,System Calls,Endianness,我有一个矩阵2-D int指针int**mat,我正试图以Little endian约定在Linux中写入一个文件 以下是写入文件的函数: #define BUFF_SIZE 4 void write_matrix(int **mat, int n, char *dest_file) { int i, j; char buff[BUFF_SIZE]; int fd = open(dest_file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUS

我有一个矩阵2-D int指针int**mat,我正试图以Little endian约定在Linux中写入一个文件

以下是写入文件的函数:

#define BUFF_SIZE 4
void write_matrix(int **mat, int n, char *dest_file) {
    int i, j;
    char buff[BUFF_SIZE];
    int fd = open(dest_file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IXUSR);

    if (fd < 0) {
        printf("Error: Could not open the file \"%s\".\n", dest_file);
    }

    buff[0] = (n & 0x000000ff);
    buff[1] = (n & 0x0000ff00) >> 8;
    buff[2] = (n & 0x00ff0000) >> 16;
    buff[3] = (n & 0xff000000) >> 24;

    write(fd, buff, BUFF_SIZE);

    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            buff[0] = (mat[i][j] & 0x000000ff);
            buff[1] = (mat[i][j] & 0x0000ff00) >> 8;
            buff[2] = (mat[i][j] & 0x00ff0000) >> 16;
            buff[3] = (mat[i][j] & 0xff000000) >> 24;

            if (write(fd, buff, BUFF_SIZE) != BUFF_SIZE) {
                close(fd);
                printf("Error: could not write to file.\n");
                return;
            }
        }
    }

    close(fd);
}
我做错了什么

编辑:

添加了read_矩阵函数

看起来我得到的是一个整数的空头,因为384=110000000变成了-128=bin 1000000

进行了测试,发现:

字符c=128; int i=0; i |=c

给出i=-128。为什么


问题在于您的输入转换:

int byteToInt(char buff[]) {
    return (buff[3] << 24) | (buff[2] << 16) | (buff[1] << 8) | (buff[0]);
}
因为int可能是16位,所以最好使用long,实际上最好使用unsigned long以避免其他转换问题。这意味着要进行双重施放:

unsigned long byteToInt(char buff[]) {
    return   ((unsigned long)(unsigned char)buff[3] << 24)
           | ((unsigned long)(unsigned char)buff[2] << 16)
           | ((unsigned long)(unsigned char)buff[1] << 8)
           | (unsigned long)(unsigned char)buff[0];
}

问题在于您的输入转换:

int byteToInt(char buff[]) {
    return (buff[3] << 24) | (buff[2] << 16) | (buff[1] << 8) | (buff[0]);
}
因为int可能是16位,所以最好使用long,实际上最好使用unsigned long以避免其他转换问题。这意味着要进行双重施放:

unsigned long byteToInt(char buff[]) {
    return   ((unsigned long)(unsigned char)buff[3] << 24)
           | ((unsigned long)(unsigned char)buff[2] << 16)
           | ((unsigned long)(unsigned char)buff[1] << 8)
           | (unsigned long)(unsigned char)buff[0];
}

你所拥有的是一种经常被忽视的未定义的行为。有符号负值的左移未定义。详情请参阅

当你这么做的时候

int byteToInt(char buff[]) {
    return (buff[3] << 24) | (buff[2] << 16) | (buff[1] << 8) | (buff[0]);
}

即使buff的一个元素有一个负值,即二进制数据的一个值设置了MSB,也会出现未定义的行为。因为您的数据是二进制的,所以将其读取为无符号最有意义。您可以使用一个标准类型来明确符号性和长度,例如stdint.h中的uint8_t。

您所拥有的是一种经常被忽略的未定义行为。有符号负值的左移未定义。详情请参阅

当你这么做的时候

int byteToInt(char buff[]) {
    return (buff[3] << 24) | (buff[2] << 16) | (buff[1] << 8) | (buff[0]);
}

即使buff的一个元素有一个负值,即二进制数据的一个值设置了MSB,也会出现未定义的行为。因为您的数据是二进制的,所以将其读取为无符号最有意义。您可以使用一个标准类型,使符号和长度显式,例如stdint.h中的uint8_t。

请给出一个调用该类型的示例,它是如何设置的?很可能不是问题所在,但您的错误检查很奇怪。在检查fd是否小于零之前写入文件。在这种情况下可能不适用,但更安全的做法是先移位,然后屏蔽,以避免符号扩展效应。它还使代码更具可读性,因为您总是提取最低的字节,并且由于您不需要额外的常量,代码更紧凑。关于您的更新,如果char是8位且有符号的,则char c=128已经是实现定义的。char的有效值假设您的值是有符号的,我没有证据表明您的值是-128。。127您的char数据类型溢出了。128是0x80,如果您的实现选择使用-128作为有符号字符,那么它就是-128。然后,对于i |=c计算,该值被提示为int,并进行符号扩展,最终结果为i=-128。我刚才说的是真的;不要使用字符,使用无符号字符。不要手动进行endian转换。这是多余的:。 而且您的代码极易出错。int不必为4字节长。请给出一个调用此函数的示例,它是如何设置的?很可能不是问题所在,但您的错误检查很奇怪。在检查fd是否小于零之前写入文件。在这种情况下可能不适用,但更安全的做法是先移位,然后屏蔽,以避免符号扩展效应。它还使代码更具可读性,因为您总是提取最低的字节,并且由于您不需要额外的常量,代码更紧凑。关于您的更新,如果char是8位且有符号的,则char c=128已经是实现定义的。char的有效值假设您的值是有符号的,我没有证据表明您的值是-128。。127您的char数据类型溢出了。128是0x80,如果您的实现选择使用-128作为有符号字符,那么它就是-128。然后,对于i |=c计算,该值被提示为int,并进行符号扩展,最终结果为i=-128。我刚才说的是真的;不要使用字符,使用无符号字符。不要手动进行endian转换。这是多余的:。 而且您的代码极易出错。int不必是4字节长。unsigned charbuff[3]@chux:我认为,即使int是32位的,理论上也是不可移植的,因为不能保证正符号int左移会产生预期的负符号int,尽管结果是未指定的,不是未定义的。但那片沼泽太深了,度假时不能涉水。祝你快乐:从沼泽般的深渊里,软泥从一个人的头上滴落下来,他点点头,喃喃地说:是的,滚开,泥泞——当他漫步回到自己的巢穴并系上长统袜时,泥泞不堪。nice hatunsigned charbuff[3]@chux:我相信即使int是32位的,理论上也是不可移植的,因为不能保证左移一个正有符号int会产生预期的负有符号int,尽管结果是未指定的,不是未定义的。但是沼泽太深了,不能涉水进去
假期。祝你快乐:从沼泽般的深渊里,软泥从一个人的头上滴落下来,他点点头,喃喃地说:是的,滚开,泥泞——当他漫步回到自己的巢穴并系上长统袜时,泥泞不堪。漂亮的帽子