【问题标题】:What is the meaning of " ( void * ) " in : if ( test == ( void * ) -1 ) [duplicate]if(test ==(void *)-1)中的“(void *)”是什么意思
【发布时间】:2017-12-23 02:29:06
【问题描述】:

函数返回-1。

但是,下面代码中(void*)是什么意思:

没有它可以工作吗?

test = shmat(shm_id, NULL, 0);

if (test == (void *)-1) {
    /* handle shmat failure */
}

【问题讨论】:

  • 对我来说看起来不像便携式 C。你能添加更多标签吗?
  • @Bathsheba posix...
  • bro void 表示空值。更多参考结帐:-stackoverflow.com/questions/29792827/void-as-return-type
  • @kannu-- voidvoid * 是两个不同的东西。我认为你不能发表评论,直到你至少有 50 名代表......
  • @kannu : 语言不同,概念也不同。

标签: c posix ipc


【解决方案1】:

shmat 有以下原型:

void *shmat(int shmid, const void *shmaddr, int shmflg);

即它返回一个指向void 的指针,而不是一个整数。

如果出错,它将返回 整数 -1 转换为指向 void 的指针。来自 Linux 手册页shmat(2)

成功时,shmat() 返回附加的共享内存段的地址;出错时,返回(void *) -1,并设置errno 指示错误原因。

这就是您必须正确进行比较以检查错误返回的方式。 C11 标准对6.5.9p5-6 中的运算符== 有如下说明:

5 否则,至少有一个操作数是指针。如果一个操作数是指针而另一个是空指针常量,则空指针常量将转换为指针的类型

如果一个操作数是一个指针指向一个对象类型而另一个是一个指针指向一个合格或不合格的void版本,前者被转换为后者。

6 两个指针比较相等当且仅当两者都是空指针,两者都是指向同一个对象(包括指向对象的指针和在其开头的子对象)或函数的指针,两者都是指向最后一个元素的指针同一个数组对象,或者一个是指向一个数组对象末尾的指针,另一个是指向另一个数组对象的开头的指针,该数组对象恰好紧跟在地址空间中的第一个数组对象之后。109)

也就是说,标准定义了两种转换的行为:一个操作数是指向 void 的指针,另一个操作数是指向其他对象的指针;或者一个操作数是指针,而另一个操作数是空指针常量(即 0 或 (void*)0 等)。由于没有强制转换的-1 既不是空指针常量也不是指针,因此标准没有为这种情况指定任何行为,因此行为未定义"by the omission of any explicit definition"

test == -1 是错误的,test == (void *) -1 是正确的(ish)。

事实证明,这仍然是一个灰色区域。 -1int,在 my 计算机上,它是 32 位的。整数到指针的转换由实现定义。 GCC manuals say

如果指针表示大于整数类型,则从指针到整数的强制转换丢弃最高有效位,如果指针表示小于整数类型,则符号扩展[2],否则位没有变化。

脚注2说

GCC 的未来版本可能会进行零扩展,或使用目标定义的 ptr_extend 模式。不要依赖符号扩展。

因此这意味着(void *)-1 也可能变得不正确;更安全的方法是将其写为(void *)(intptr_t)-1


由于某种原因,(void *)0,即空指针,不用于指示错误条件(即使在 C 中使用这样的指针在标准方面是错误的)。

【讨论】:

  • 从历史上看,它曾经可以映射零页(这样(void *) 0 就变成了可以放置对象的有效地址。这就是mmap 不返回NULL 的原因失败。我不知道这是否也适用于shmat,但这可能是这种行为的原因。
  • 在 64 位系统上不应该是 test == (void *) -1L 甚至是 test == (void *) -1LL 吗?
  • 我的意思是,虽然 GCC 目前是这样做的,但它不保证符号扩展(将来)。
  • mmapshmat 的手册页只提到 (void*)-1clang 恰好将 (void*)-1 实现为 (void*)(inptr_t)-1 我想所有符合 Posix 的编译器都必须为规范保持一致。有趣的角落案例。
  • 我想可以检查errno,而不是尝试从返回的指针中解码错误状态。请注意,errno 仅在错误时设置,因此您必须在调用 shmat 之前明确清除它
【解决方案2】:

type casting

函数shmat() 返回一个void*,因此类型转换用于将-1 (int) 转换为正确的类型(void*)。

实际上,是的,它可以工作,但你会从编译器中得到一些警告。

永远不要忽略它们可以隐藏错误的警告。

【讨论】:

  • "...你会从编译器收到一些警告"你确定吗?
猜你喜欢
  • 2019-11-19
  • 1970-01-01
  • 2012-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-01
  • 2017-01-09
相关资源
最近更新 更多