How do you cast from a bit-field to a pointer?
I've written the following bit of code that is producing a
warning: initialization makes pointer from integer without a cast
OR A
warning: cast to pointer from integer of different size
from 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");
How do I get the warning to go away? No matter what I've tried casting, a warning seems to always appears.
Thanks, Chenz
Hmm, why do you insist on using pointers as booleans? How about this alternative?
struct named_bool {
const char* name;
int val;
};
const struct named_bool bools[] = {{ "ItemA", 1 }, { "ItemB", 1 }, { 0, 0 }};
const void * bools[] = { "ItemA", mine->a, "ItemB", mine->b, 0, 0 };
There are several problems with this snippet:
mine
isn't declared as a pointer type (at least not in the code you posted), so you shouldn't be using the->
component selection operator;- If you change that to use the
.
selection operator, you'd be attempting to store the boolean value in a or b as a pointer, which isn't what you want; - But that doesn't matter, since you cannot take the address of a bit-field (§ 6.5.3.2, paragraph 1).
If you're trying to associate a boolean value with another object, you'd be better off declaring a type like
struct checkedObject {void *objPtr; int check};
and initialize an array as
struct checkedObject[] = {{"ItemA", 1}, {"ItemB", 0}, {NULL, 0}};
Bit-fields have their uses, but this isn't one of them. You're really not saving any space in this case, since at least one complete addressable unit of storage (byte, word, whatever) needs to be allocated to hold the two bitfields.
Two problems:
Not sure why you are trying to convert
unsigned int a:1
to avoid*
. If you are trying to reference it, the syntax would be&mine->a
rather thanmine->a
, but...You can't create a pointer to a bit in C (at least as far as I know). If you're trying to create a pointer to a bit, you may want to consider one the following options:
Create a pointer to the bitfield structure (i.e.
struct my_t *
), and (if necessary) use a separate number to indicate which bit to use. Example:struct bit_ref { struct my_t *bits; unsigned int a_or_b; // 0 for bits->a, 1 for bits->b }
Don't use a bit field. Use
char
for each flag, as it is the smallest data type that you can create a pointer to.Do use a bit field, but implement it manually with boolean operations. Example:
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)); }
There's a few ways you could get rid of the warning, but still use a pointer value as a boolean. For example, you could do this:
const void * bools[] = { "ItemA", mine->a ? &bools : 0, "ItemB", mine->b ? &bools : 0, 0, 0 };
This uses a NULL
pointer for false, and a non-null pointer (in this case, &bools
, but a pointer to any object of the right storage duration would be fine) for true. You would also then remove the cast to unsigned int
in the test, so that it is just:
fprintf(stderr, "%s = %d\n", bools[i], bools[i + 1] ? "true" : "false");
(A null pointer always evaluates as false, and a non-null pointer as true).
However, I do agree that you are better off creating an array of structs
instead.
精彩评论