是否总是安全地转换成一个整数值为void *,并再次回到POSIX? [英] Is it always safe to convert an integer value to void* and back again in POSIX?

查看:123
本文介绍了是否总是安全地转换成一个整数值为void *,并再次回到POSIX?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这问题几乎是其他一些我发现的一个副本,但具体涉及POSIX,并且在我遇到好几次pthreads的一个很常见的例子。我主要关心的事务(即C99和POSIX.1-2008或更高版本)的当前状态,但任何有趣的历史信息,当然也很有趣。

This question is almost a duplicate of some others I've found, but this specifically concerns POSIX, and a very common example in pthreads that I've encountered several times. I'm mostly concerned with the current state of affairs (i.e., C99 and POSIX.1-2008 or later), but any interesting historical information is of course interesting as well.

问题基本上可以归结为B是否将始终以相同的值作为在以下code:

The question basically boils down to whether b will always take the same value as a in the following code:

long int a = /* some valid value */
void *ptr = (void *)a;
long int b = (long int)ptr;

据我所知,这通​​常工作,但问题是,它是否是做正确的事(即,莫非是C99和/或POSIX标准,保证它会正常工作)。

I am aware that this usually works, but the question is whether it is a proper thing to do (i.e., does the C99 and/or POSIX standards guarantee that it will work).

当涉及到C99似乎不是这样,我们有6.3.2.3:

When it comes to C99 it seems it does not, we have 6.3.2.3:

5的整数可以被转换为任何指针类型。除
  previously特定网络版,其结果是实现德科幻定义,可能不
  正确对齐,可能不会指向引用的实体
  类型,并且可能是一个陷阱重新presentation.56)

5 An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.56)

6的任何指针类型可以是
  转换为整数类型。除previously特定网络版,该
  结果是实现德网络定义。如果结果不能被重新presented
  在整数类型,其行为定义理解过程网络。结果不必是
  在任何整数类型的值的范围。

6 Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

即使使用使用intptr_t标准似乎只保证任何有效无效*可以转换为intptr_t和返回,但它不保证任何使用intptr_t可以转换到void *,然后再返回。

Even using intptr_t the standard seems to only guarantee that any valid void* can be converted to intptr_t and back again, but it does not guarantee that any intptr_t can be converted to void* and back again.

但是它仍然是可能的,POSIX标准允许此

However it is still possible that the POSIX standard allows this.

我没有用一个void *作为任何变量的存储空间,伟大的愿望(我觉得pretty丑就算POSIX应该允许它),但我觉得我要问,因为常用的例子,使用的pthreads_create功能在哪里的start_routine参数是一个整数,并且在为void *过去了,转换成int或长整型中的start_routine功能。例如本手册页有这样一个例子(见链接全code):

I have no great desire to use a void* as a storage space for any variable (I find it pretty ugly even if POSIX should allow it), but I feel I have to ask because of the common example use of the pthreads_create function where the argument to start_routine is an integer, and it is passed in as void* and converted to int or long int in the start_routine function. For example this manpage has such an example (see link for full code):

//Last argument casts int to void *
pthread_create(&tid[i], NULL, sleeping, (void *)SLEEP_TIME);
/* ... */
void * sleeping(void *arg){
    //Casting void * back to int
    int sleep_time = (int)arg;
    /* ... */
}

我也看到了一本教科书(由Peter S.帕切科介绍到并行编程)类似的例子。考虑到这似乎是的,我想知道如果我错了,被人们使用的常见的例子谁应该知道这东西比我好多了,这实际上是在做一个安全和便携的事情。

I've also seen a similar example in a textbook (An Introduction to Parallel Programming by Peter S. Pacheco). Considering that it seems to be a common example used by people who should know this stuff much better than me, I'm wondering if I'm wrong and this is actually a safe and portable thing to be doing.

推荐答案

正如你所说,C99并不能保证任何整数类型可以被转换成无效* 和回来而不丢失信息。它确实使对类似的保证使用intptr_t uintptr_t形式中所定义; stdint.h> ,但这些类型都是可选的。 (担保是一个无效* 可转换为 {U,}使用intptr_t 和背部而不会丢失信息;有任意整数值没有这样的保证。)

As you say, C99 doesn't guarantee that any integer type may be converted to void* and back again without loss of information. It does make a similar guarantee for intptr_t and uintptr_t defined in <stdint.h>, but those types are optional. (The guarantee is that a void* may be converted to {u,}intptr_t and back without loss of information; there's no such guarantee for arbitrary integer values.)

POSIX似乎没有做出任何这样的保证无论是。

POSIX doesn't appear to make any such guarantee either.

1所述的POSIX描述; limits.h中&GT; 要求 INT 无符号整型来为至少32位。这超过了它们至少是16比特的C99要求。 (事实上​​,这些要求都在范围内,而不是大小方面,但效果是 INT unsigned int类型必须至少32(下POSIX)或16(根据C99)位,因为C99要求二进制重新presentation。)

The POSIX description of <limits.h> requires int and unsigned int to be at least 32 bits. This exceeds the C99 requirement that they be at least 16 bits. (Actually, the requirements are in terms of ranges, not sizes, but the effect is that int and unsigned int must be at least 32 (under POSIX) or 16 (under C99) bits, since C99 requires a binary representation.)

1所述的POSIX描述; stdint.h&GT; 表示,使用intptr_t uintptr_t形式必须至少 16 的位,C标准规定的同样的要求。由于无效* 可转换为使用intptr_t ,然后再返回而不会丢失信息,这意味着无效* 可以是16位的小。再加上与POSIX的要求,即 INT 至少32位(和的POSIX和C要求长是至少32位),它可能是一个无效* 只是没有大到足以容纳一个 INT 不会丢失信息长值。

The POSIX description of <stdint.h> says that intptr_t and uintptr_t must be at least 16 bits, the same requirement imposed by the C standard. Since void* can be converted to intptr_t and back again without loss of information, this implies that void* may be as small as 16 bits. Combine that with the POSIX requirement that int is at least 32 bits (and the POSIX and C requirement that long is at least 32 bits), and it's possible that a void* just isn't big enough to hold an int or long value without loss of information.

在pthread_create的POSIX说明()并不矛盾这一点。它只是说, ARG (即无效* 第四个参数为在pthread_create()传递给的start_routine()。presumably的意图是, ARG 点到的一些数据,的start_routine()可以使用。POSIX没有例子,说明 ARG 的使用。

The POSIX description of pthread_create() doesn't contradict this. It merely says that arg (the void* 4th argument to pthread_create() is passed to start_routine(). Presumably the intent is that arg points to some data that start_routine() can use. POSIX has no examples showing the usage of arg.

您可以看到POSIX标准 rel=\"nofollow\">;你必须创建一个免费帐户来访问它。

You can see the POSIX standard here; you have to create a free account to access it.

这篇关于是否总是安全地转换成一个整数值为void *,并再次回到POSIX?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆