你如何从位域转换为指针?

时间:2011-01-03 21:56:11

标签: c casting void-pointers bit-fields gcc-warning

我编写了以下代码来生成

  

警告:初始化使得整数指针不带强制转换

或A

  

警告:从不同大小的整数转换为指针

来自gcc(GCC)4.1.1 20070105(Red Hat 4.1.1-52)

struct my_t {
  unsigned int a     : 1;
  unsigned int b    : 1;
};

struct my_t mine = {
  .a = 1,
  .b = 0
};

const void * bools[] = { "ItemA", mine->a, "ItemB", mine->b, 0, 0 };

int i;
for (i = 0; bools[i] != NULL; i += 2)
  fprintf(stderr, "%s = %d\n", bools[i], (unsigned int) bools[i + 1] ? "true" : "false");

如何让警告消失?无论我试图投射什么,似乎总会出现警告。

谢谢, Chenz

4 个答案:

答案 0 :(得分:2)

嗯,你为什么坚持用指针作为布尔?这个替代方案怎么样?

struct named_bool {
    const char* name;
    int         val;
};

const struct named_bool bools[] = {{ "ItemA", 1 }, { "ItemB", 1 }, { 0, 0 }};

答案 1 :(得分:1)

const void * bools[] = { "ItemA", mine->a, "ItemB", mine->b, 0, 0 }; 

此代码段有几个问题:

  1. mine未声明为指针类型(至少不在您发布的代码中),因此您不应使用->组件选择运算符;
  2. 如果你改变它以使用.选择运算符,你将试图将布尔值存储在a或b中作为指针,这不是你想要的;
  3. 但这没关系,因为你不能取位字段的地址(第6.5.3.2节,第1段)。

如果您尝试将布尔值与另一个对象相关联,那么最好声明类似

的类型
struct checkedObject {void *objPtr; int check};

并将数组初始化为

struct checkedObject[] = {{"ItemA", 1}, {"ItemB", 0}, {NULL, 0}};

比特字段有它们的用途,但这不是其中之一。在这种情况下,你真的没有节省任何空间,因为至少需要分配一个完整的可寻址存储单元(字节,字,等等)来保存两个位域。

答案 2 :(得分:0)

两个问题:

  1. 不确定为什么要将unsigned int a:1转换为void*。如果您尝试引用它,则语法为&mine->a而不是mine->a,但是......

  2. 你不能在C中创建指向某个位的指针(至少据我所知)。如果您尝试创建指向某个位的指针,您可能需要考虑以下选项之一:

    • 创建指向位域结构的指针(即struct my_t *),并且(如果需要)使用单独的数字来指示要使用的位。例如:

      struct bit_ref {
          struct my_t  *bits;
          unsigned int  a_or_b; // 0 for bits->a, 1 for bits->b
      }
      
    • 不要使用位域。对每个标志使用char,因为它是您可以创建指针的最小数据类型。

    • 请使用位字段,但使用布尔运算手动实现。例如:

      typedef unsigned int my_t;
      
      
      #define MY_T_A (1u << 0)
      #define MY_T_B (1u << 1)
      
      
      struct bit_ref {
          struct my_t  *bits;
          unsigned int  shift;
      };
      
      
      int deref(const struct bit_ref bit_ref)
      {
          return !!(bit_ref.bits & (1 << bit_ref.shift));
      }
      

答案 3 :(得分:0)

有几种方法可以摆脱警告,但仍然使用指针值作为布尔值。例如,您可以这样做:

const void * bools[] = { "ItemA", mine->a ? &bools : 0, "ItemB", mine->b ? &bools : 0, 0, 0 };

这使用NULL指针表示false,而非空指针(在本例中为&bools,但指向正确存储持续时间的任何对象的指针都可以)为true。然后,您还可以在测试中删除强制转换为unsigned int,以便它只是:

fprintf(stderr, "%s = %d\n", bools[i], bools[i + 1] ? "true" : "false");

(空指针始终计算为false,非空指针计为true)。

然而,我同意您最好创建一个structs数组。