【发布时间】:2015-02-22 23:04:13
【问题描述】:
我有一个矩阵(二维 int 指针 int **mat),我试图在 Linux 中以 Little-endian 约定写入一个文件。
这是我写入文件的函数:
#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; 诠释 i = 0; 我 |= c;
给出
i = -128。为什么????
【问题讨论】:
-
请展示一个调用这个的例子,它是如何设置的?
-
很可能不是问题,但是您的错误检查很奇怪。在检查 fd 是否小于零之前写入文件。
-
在这种情况下可能不适用,但更安全的是先移位,THEN 掩码,以避免符号扩展效应。它还使代码更具可读性,因为您总是提取最低字节,并且更紧凑,因为您不需要额外的常量。
-
关于您的更新,如果
char是 8 位且已签名,则char c = 128已经是实现定义的。char的有效值为-128 .. 127。您正在溢出您的char数据类型。 128 是0x80,如果您的实现选择了(并且确实如此),则-128作为签名字符。然后将该值提示为int以进行i|=c计算并扩展符号,从而为您提供最终结果i=-128。我的意思是我之前所说的;不要用char做这些东西,用unsigned char。 -
不要手动进行字节序转换。多余的:man7.org/linux/man-pages/man3/endian.3.html.而且您的代码极易出错。
int不必是 4 字节长。
标签: c linux system-calls endianness