【问题标题】:Is it possible to cast directly into write?可以直接转换成write吗?
【发布时间】:2019-06-18 09:00:59
【问题描述】:

在创建自己的 malloc 时,我使用 write 来打印一些值。

我在打印值时没有任何问题,我只是创建一个 char 变量来存储我的号码并打印它,但我不明白为什么演员表不起作用。 write的原型是:

ssize_t write(int fd, const void *buf, size_t count)

所以我将我的号码输入 void * 没有任何结果。

int nb = 3;
char numb = nb + '0';

write(1, (void *)(nb + '0'), 1); // Display nothing
write(1, &numb, 1); // Display 3

谁能解释一下为什么第一次写什么都不显示?

【问题讨论】:

  • (void *)(nb + '0') 是指向无效地址的指针 - 我很惊讶它没有段错误。
  • 你为什么不检查write的返回值是否有错误?
  • @PaulR 系统调用不会出现段错误,它们是EFAULT
  • write(1, &numb, 1); // Display 34 - 这让我很吃惊。尤其是当您告诉它只打印一个字符时它正在打印两个字符。
  • @GregLoupy 您正在获取一个随机整数(在本例中为 82)并将其转换为指针。那怎么会是一个有效的地址?

标签: c unistd.h


【解决方案1】:

转换为 void* 仅意味着它应该将给定值视为 void 指针。 但是给定的“地址”是 34 + '0' 这显然是无效的。 你必须给write 一个指针,所以不可能做这样的事情。您必须将要打印的值存储在内存中的某个位置并提供指向该位置的指针。

【讨论】:

  • 但是(nb + '0') 没有地址。
【解决方案2】:

(void *)(nb + '0') 正在尝试以nb + '0' 的实际值取消对内存的引用,就好像该值是一个地址一样。 (nb + '0') 不是左值,因此您也不能在其上使用 & 运算符。你应该做的是:

如果您使用的是 little-endian 系统(似乎是 OP 的情况):

nb += '0';
write(..., &nb, ...);

如果您使用的是大端系统:

char foo = (nb >> (CHAR_BIT * (sizeof(int) - 1))) & 0xff;
foo += '0';
write(..., &foo, ...);

【讨论】:

  • nb 是一个int。你希望write 对此做什么?
  • 如果nb 的类型大于char,则此答案是错误的并且取决于字节序。
  • @GovindParmar 是的,对...numb 是字符...我认为,更好的方法是将它分配给一个字符以独立于字节序问题。
  • @Ctx 别难过;我认为nb 也是char,直到 R.. 指出来
  • @GovindParmar:您只是用显式的字节序逻辑重新实现了大字节序的损坏,而不是通过读取内存中int 的第一个字节。正确的解决方法是 char foo = nb; 但它并不能解决 OP 避免临时的目标。
【解决方案3】:

是的,但它不是 cast,它是一个 复合文字

write(1, (char[]){nb + '0'}, 1);

或:

write(1, &(char){nb + '0'}, 1);

【讨论】:

  • 谢谢你,这正是我正在寻找的! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-25
  • 1970-01-01
  • 1970-01-01
  • 2010-10-07
  • 1970-01-01
  • 2013-12-18
  • 1970-01-01
相关资源
最近更新 更多