C “是什么意思?”;(无效*)”;in:if(test==(void*)-1)
函数返回-1 但是,以下代码中的C “是什么意思?”;(无效*)”;in:if(test==(void*)-1),c,posix,ipc,C,Posix,Ipc,函数返回-1 但是,以下代码中的(void*)是什么意思: 没有它能工作吗 test = shmat(shm_id, NULL, 0); if (test == (void *)-1) { /* handle shmat failure */ } shmat具有以下原型: void *shmat(int shmid, const void *shmaddr, int shmflg); i、 e.它返回指向void的指针,而不是整数 出错时,它会将整数-1转换返回到指向void的指针
(void*)
是什么意思:
没有它能工作吗
test = shmat(shm_id, NULL, 0);
if (test == (void *)-1) {
/* handle shmat failure */
}
shmat
具有以下原型:
void *shmat(int shmid, const void *shmaddr, int shmflg);
i、 e.它返回指向void
的指针,而不是整数
出错时,它会将整数-1转换返回到指向void的指针。从Linux手册页:
成功时,shmat()
返回连接的共享内存段的地址;出现错误时,将返回(void*)-1
,并设置errno
,以指示错误原因
这就是您必须正确进行比较以检查错误返回的方式。C11标准对中的操作员==
作了如下说明:
5否则,至少有一个操作数是指针。如果一个操作数是指针,而另一个是空指针常量,则空指针常量将转换为指针的类型
如果一个操作数是指向对象类型的指针,而另一个操作数是指向void的限定或非限定版本的指针,则前者将转换为后者的类型
6两个指针比较相等当且仅当两个指针都是空指针,都是指向同一对象(包括指向对象的指针及其开头的子对象)或函数的指针,都是指向同一数组对象最后一个元素的指针,或者一个指针指向一个数组对象的末尾,另一个指针指向另一个数组对象的开头,该数组对象恰好紧跟地址空间中的第一个数组对象。109)
也就是说,标准定义了正好2次转换的行为:一个操作数是指向void的指针,另一个操作数是指向其他对象的指针;或者一个操作数是指针,另一个操作数是空指针常量(即0或(void*)0左右)。由于不带强制类型转换的-1
既不是空指针常量,也不是指针,因此该标准没有为这种情况指定任何行为,因此该行为是未定义的
test==-1
是错误的,test==(void*)-1
是正确的(ish)
事实证明,这仍然是一个灰色地带-1
是一个int
,在我的计算机上是32位。整数到指针的转换由实现定义。委员会:
如果指针表示大于整数类型,则从指针到整数的强制转换将丢弃最高有效位;如果指针表示小于整数类型,则符号扩展,否则位将保持不变
脚注2说
GCC的未来版本可能会进行零扩展,或者使用目标定义的ptr_扩展模式。不要依赖符号扩展
因此,这意味着(void*)-1
也可能变得不正确;更安全的方法是将其写成(void*)(intptr\u t)-1
由于某种原因,
(void*)0
,即空指针,不用于信号错误条件(即使在C中使用该指针在标准方向上是错误的)。是的
函数shmat()
返回一个void*
,因此类型转换用于将-1(int
)转换为正确的类型(void*
)
事实上,是的,它可以工作,但你会从编译器得到一些警告
永远不要忽视警告,因为它们可能隐藏bug。在我看来不像便携式C。你能添加更多的标签吗?@Bathsheba posix…bro void表示空值。更多参考签出:-@kannu--
void
和void*
是两件不同的事情。我以为你至少有50个代表才能发表评论…@kannu:语言不同,概念也不同。过去,可以映射零页(因此(void*))0
变成可以放置对象的有效地址。这就是为什么mmap
在失败时不返回NULL
。我不知道这是否也适用于shmat
,但这可能是此行为的原因。它是否应该是test==(void*)-1L
甚至test==(void*)-1LL
在64位系统上?我的观点是,虽然GCC目前是这样做的,但它不保证符号扩展(将来)。mmap和shmat的手册页只提到(void*)-1
,clang
碰巧实现了(void*)-1
作为(void*)(inptr\t)-1
我想所有符合Posix的编译器都必须这样做才能保持规范的一致性。有趣的是,我想人们可以检查errno
,而不是试图从返回的指针中解码错误状态。请注意,errno
仅在错误时设置,因此必须显式清除它在调用shmat
“…编译器会给您一些警告”之前,您确定吗?