You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何打印mmap映射文件内容?void*转char*报错问题解决

错误原因
  1. C语言标准中void*属于无具体类型的指针,编译器无法确定void类型的大小,因此不允许对void*直接做下标访问、指针偏移类运算。你最初写的adr[i]本质是*(adr + i),编译器不知道要偏移多少字节,直接触发「invalid use of void expression」编译错误。
  2. 你后续的强转写法存在运算符优先级错误:下标运算符[]的优先级高于强制类型转换,因此(char*) adr[i]实际等价于(char*)(adr[i])——也就是先执行非法的void*下标取值,再把取到的无意义值强转为char*,完全没有修改指针本身的类型,自然无法解决报错。
  3. 代码还存在隐藏的越界bug:循环条件写为i <= bf.st_size时,最后一次循环会访问偏移为bf.st_size的地址,而mmap映射的文件内容有效地址范围是0 ~ bf.st_size - 1,越界访问会触发段错误。
修正方案

两种合法写法都可以实现需求:

  • 写法1:定义接收mmap返回值的指针时,直接使用char*类型,从根源避免无类型指针的访问问题
  • 写法2:如果保持adr为void*类型,访问时先把指针整体强转为char*,再做下标运算,注意强转的指针部分必须用括号包裹

修正后的核心代码如下:

int fd = open(argv[1], O_RDONLY);
struct stat bf;
fstat(fd, &bf);
// 推荐直接用char*接收返回值
char *adr = mmap(NULL, bf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
// 修正循环条件为i < bf.st_size,避免越界
for (size_t i = 0; i < bf.st_size; i++)
{
    printf("%c", adr[i]);
}
// 若必须保留void* adr的定义,访问语句改为:
// printf("%c", ((char*)adr)[i]);

// 使用完映射区域后记得释放资源
munmap(adr, bf.st_size);
close(fd);
额外注意
  • 对void*做算术/下标运算属于GCC的非标准扩展,可移植性极差,正式代码不要依赖这个特性
  • 实际生产代码中需要对open、fstat、mmap的返回值做错误校验,避免空指针、非法文件描述符引发的崩溃

内容的提问来源于stack exchange,提问作者kueen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 08:39:10