C 在并集中组合指针和整数

C 在并集中组合指针和整数,c,pointers,integer,unions,C,Pointers,Integer,Unions,我对工会的定义如下: union { uintptr_t refcount; struct slab_header *page; } u; 页面指针保证在页面边界上对齐(最有可能是4096),并且永远不会为NULL。这意味着最低可能的地址将是4096 refcount将在0之内。。4095 创建封闭结构后,我可以使用u.refcount=0或u.page=mmap(…) 围绕这个联盟的代码是这样的: if (u.refcount < 4096) { /* work with

我对工会的定义如下:

union {
  uintptr_t refcount;
  struct slab_header *page;
} u;
页面
指针保证在页面边界上对齐(最有可能是4096),并且永远不会为
NULL
。这意味着最低可能的地址将是
4096

refcount
将在
0之内。。4095

创建封闭结构后,我可以使用
u.refcount=0
u.page=mmap(…)

围绕这个联盟的代码是这样的:

if (u.refcount < 4096) {
  /* work with refcount, possibly increment it */
} else {
  /* work with page, possibly dereference it */
}
if(u.refcount<4096){
/*使用refcount,可能会增加它*/
}否则{
/*使用页面,可能会取消引用*/
}

这是否总是保证在完全符合POSIX的实现上工作?
uintpttr\u t
struct slab\u header*
是否可能有不同的表示形式,例如,当
u.page==8192
时,
u.refcount<4096
产生真值?

我认为
和C99标准保证了
uintptr\u t
void*
具有相同的尺寸,并且可以铸造而不会丢失

指针的页面对齐是一个实现细节。

我认为
和C99标准保证了
uintpttr\t
void*
具有相同的大小,并且可以毫无损失地浇铸

指针的页面对齐是一个实现细节。

我不认为它“总是保证工作”,因为:

  • uintpttr\u t
    是可选的(7.18.1.4)
  • void*
    可以转换为
    uintpttr\u t
    并返回(7.18.1.4)。不能保证
    struct slab\u header*
    的情况就是这样。
    void*
    与指向字符类型的指针具有相同的表示和对齐要求。指向结构的指针不必具有相同的表示或对齐方式(6.2.5 27)。即使不是这样,也不能保证
    sizeof(uintpttr_t)=sizeof(void*)
    ,它显然可以更大,并且在同构指针的典型情况下仍然满足转换为
    void*
    的要求
  • 最后,即使它们大小相同且可转换,指针值的表示形式也可能与无符号整数的表示形式存在奇怪的差异。无符号整数的表示相对受限(6.2.6.2 1),但指针上不存在此类约束
  • 因此,我认为最好的方法是有一个共同的初始元素来告诉状态。

    我不认为它“总是保证有效”,因为:

  • uintpttr\u t
    是可选的(7.18.1.4)
  • void*
    可以转换为
    uintpttr\u t
    并返回(7.18.1.4)。不能保证
    struct slab\u header*
    的情况就是这样。
    void*
    与指向字符类型的指针具有相同的表示和对齐要求。指向结构的指针不必具有相同的表示或对齐方式(6.2.5 27)。即使不是这样,也不能保证
    sizeof(uintpttr_t)=sizeof(void*)
    ,它显然可以更大,并且在同构指针的典型情况下仍然满足转换为
    void*
    的要求
  • 最后,即使它们大小相同且可转换,指针值的表示形式也可能与无符号整数的表示形式存在奇怪的差异。无符号整数的表示相对受限(6.2.6.2 1),但指针上不存在此类约束

  • 因此,我认为最好的方法是使用一个公共的初始元素来告知状态。

    该代码应该有任何问题。但在任何情况下,您都可以在程序的init中进行检查:

    if (sizeof(uintptr_t) != sizeof (struct slab_header*)
    {
        print error
    }
    

    但似乎有些不对劲(或不清楚)。当您有一个页面时,您希望“refcount”为0。当页面为空时不为零?

    该代码应该有任何问题。但在任何情况下,您都可以在程序的init中进行检查:

    if (sizeof(uintptr_t) != sizeof (struct slab_header*)
    {
        print error
    }
    
    但似乎有些不对劲(或不清楚)。当您有一个页面时,您希望“refcount”为0。当页面为空时是否不为零


    这总是保证有效吗

    不,你不能阅读与上一篇文章不同的工会成员。优化器确实考虑到了这一点,所以这不是一个理论问题

    uintpttr_t和struct slab_header*是否可能有不同的表示形式, 例如,当u.page==8192时,u.refcount<4096产生true

    这在理论上也是可能的。我想不出当前的实现是在什么地方发生的


    这总是保证有效吗

    不,你不能阅读与上一篇文章不同的工会成员。优化器确实考虑到了这一点,所以这不是一个理论问题

    uintpttr_t和struct slab_header*是否可能有不同的表示形式, 例如,当u.page==8192时,u.refcount<4096产生true


    这在理论上也是可能的。我想不出当前的实现是在哪里发生的。

    我将回答一个不同的问题--“这是个好主意吗?”我从您的代码中看到的更重要的担忧是别名问题。如果有可能编写一段具有

    • 写些东西到u.refcount
    • 写点东西到
      u.page
    • 读取
      u.refcount
    • 发现您读取的值与第一次写入的值相同
    您可能会嘲笑,但我看到过这种情况——如果您不了解这种危险,那么调试将需要很长时间

    你和这个特殊的联盟可能是安全的;我会把它留下的