我有一个矩阵(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);
}
问题是,当我写出一个足够大的矩阵,其形式为 mat[i][i] = i
(比方说 512 X 512)时,我想我会溢出,因为我得到奇怪的负数。
要转换回来,我使用:
void read_matrix(int fd, int **mat, int n, char buff[]) {
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
assert(read(fd, buff, BUFF_SIZE) == BUFF_SIZE);
mat[i][j] = byteToInt(buff);
}
}
}
int byteToInt(char buff[]) {
return (buff[3] << 24) | (buff[2] << 16) | (buff[1] << 8) | (buff[0]);
}
我做错了什么?
已编辑:
添加了
read_matrix
函数。似乎我得到的是
short
而不是int
,因为 384 = (110000000) 变成 -128 = (bin) 1000000做了一个测试,发现:
字符 c = 128; 诠释我= 0; 我 |= c;
给出
i = -128
。为什么????
最佳答案
问题出在你的输入转换上:
int byteToInt(char buff[]) {
return (buff[3] << 24) | (buff[2] << 16) | (buff[1] << 8) | (buff[0]);
}
你没有提到你在哪个平台上,但在大多数常见平台上char
已签署。这会导致问题。例如,假设 buff[1]
是 0x80 (0b1000000)。因为它是一个带符号的值,所以它是值 -128 的代码。由于移位运算符首先对它们的两个参数进行整数提升,因此在执行移位操作之前会将其转换为整数 -128;换句话说,它将具有值 0xFFFFFF80,在移位后将变为 0xFFFF8000。
按位逻辑运算符(例如 |
)在进行按位运算之前执行通常的算术转换;在 (buff[1] << 8) | (buff[0])
的情况下, 左边的运算符已经是一个带符号的整数(因为 <<
的类型是它的 promoted 左边参数的类型);右边的参数,一个隐式签名的 char
, 也将被提升为带符号的 int,因此如果它是 0x80,它最终将被符号扩展为 0xFFFFFF80。
无论哪种情况,按位或运算都会以不需要的高位 1 位结束。
显式转换 buff[x]
到unsigned int
不会有帮助,因为它首先会被符号扩展为 int
在被重新解释为 unsigned int
之前.相反,有必要将其转换为 unsigned char
。 :
int byteToInt(char buff[]) {
return ((unsigned char)buff[3] << 24)
| ((unsigned char)buff[2] << 16)
| ((unsigned char)buff[1] << 8)
| (unsigned char)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];
}
关于c - 小端约定,并保存到二进制文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27643499/