【问题标题】:write/read int into/from char array将 int 写入/读取 char 数组
【发布时间】:2014-11-07 18:40:21
【问题描述】:

我正在尝试编写一个程序,我可以将int 复制到char 数组中,然后使用write 系统调用将该char 数组写入文件。在另一个程序中,我想将文件的内容读入char 数组,然后从数组中检索int。我无法理解的是如何将int 的内容写入数组以及如何从char 数组中读取int

这就是我所拥有的

写入文件:

int fd2 = open("file2.txt", O_RDWR | O_CREAT, S_IRUSR | S_IRGRP | S_IROTH); 
//create buff2 with 1024 chars and last 4 bytes as int
write(fd2, buff2, 1028); 

我不确定如何准确实现注释行

从文件中读取:

int fd2 = open("file2.txt", O_RDWR | O_CREAT, S_IRUSR | S_IRGRP | S_IROTH); 
char buff2[1028];
read(fd2, buff2, 1028);
int val = *((int)((buff2+1023)+sizeof(int))); // file contains exactly 1028 bytes. first 1024 are characters, next 4 is int
printf("%d\n", val);

我试图读取整数的行给了我一个编译器错误,说invalid type argument of unary '*' (have 'int')

如果有任何帮助,我将不胜感激

【问题讨论】:

  • write(fd2, &my_int, sizeof(int))read(fd2, &my_int, sizeof(int)) 有什么问题?

标签: c arrays


【解决方案1】:

使用int val = *(int*)(buff2+1024) 可以轻松修复编译错误本身。

但是,如果您尝试从不能被sizeof(int) 整除的地址中读取/写入int 值,那么您只会得到错误的结果,或者更糟 - 内存访问冲突。

也就是说,除非底层硬件架构以及指定的编译器支持未对齐的加载和存储操作(大多数情况不是)。

由于您不知道buff2 的地址,您无法确定buff2+1024 指向的地址可以被sizeof(int) 整除。因此,您必须一次读取/写入 int 值一个 char

char* pVal = (char*)&val;

// Read 'int' on little-endian architecture
for (i=0; i<sizeof(val); i++)
    pVal[i] = buff2[1024+i];

// Read 'int' on big-endian architecture
for (i=0; i<sizeof(val); i++)
    pVal[sizeof(val)-1-i] = buff2[1024+i];

// Write 'int' on little-endian architecture
for (i=0; i<sizeof(val); i++)
    buff2[1024+i] = pVal[i];

// Write 'int' on big-endian architecture
for (i=0; i<sizeof(val); i++)
    buff2[1024+i] = pVal[sizeof(val)-1-i];

如果将buff2 声明为全局变量,则可以强制编译器将其分配到对齐的内存地址。例如,假设您的平台上有sizeof(int) == 4

char buff[1028] __attribute__ ((aligned(4)));

然后,您可以安全地将int 值从/写入任何可被sizeof(int) 整除的偏移量:

// Read 'int'
val = *(int*)(buff2+1024);

// Write 'int'
*(int*)(buff2+1024) = val;

【讨论】:

  • 谢谢!在我尝试这个之前,我该如何将 int 写入 char 缓冲区,以便我可以使用 write 系统调用来写入文件?
  • @AndroidDev93:请查看更新的答案...但是,除非您的目标是避免 2 个文件操作,否则您只需按照 twalberg 对您问题的评论进行操作即可。
  • @barakmanos 从未对齐的内存中读取/写入 int,而 yes 可能会因为垃圾数据和可能的访问冲突而导致崩溃/不良行为。除非您使用有限的编译器,例如嵌入式环境,否则普通编译器(甚至许多汇编器),比如 gcc、clang、visual studio,都足够聪明,可以生成指令来处理未对齐的加载/存储(加载正在被跨区域,并进行移位以将您想要的范围放入寄存器)。但是,根据硬件的不同,它可能会导致大量速度变慢。
  • @D'Nabre:我同意将此类代码编译成未对齐的加载/存储操作会导致运行时性能下降。但我认为在很多情况下(包括 VS,如果我没记错的话),生成的代码不会在此类指令中使用(导致完全的运行时错误)。
  • @barakmanos 除非您正在处理内存映射 I/O 或其他问题,否则我就是看不到。如果你有一些例子,我会很感兴趣(这并不是在挑战你的证明,我真的很感兴趣)。
【解决方案2】:

int val = *((int)((buff2+1023)+sizeof(int))); 不会编译,因为它看起来像 int val = *some_integer; 并且需要是 int val = *some_integer_pointer;

按照@barak manos 的建议,使用int val = *(int*)(buff2+1024) 是很好的第一步。但它不能很好地处理内存对齐问题。

不要使用 char* 来表示“前 1024 个是字符,接下来的 4 个是 int”,而是使用结构。

typedef struct AD93 {
  char ch[1024];
  int val; // or int32_t
} AD93_T;

AD93_T buff2;
write(fd2, &buff2, sizeof buff2);

read(fd2, &buff2, sizeof buff2);
printf("%d\n", buff2.val);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多