Reputation: 13198
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
Upvotes: 1
Views: 4531
Reputation: 239201
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.
Upvotes: 0
Reputation: 123558
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;
.
selection operator, you'd be attempting to store the boolean value in a or b as a pointer, which isn't what you want;
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.
Upvotes: 1
Reputation: 43390
Two problems:
Not sure why you are trying to convert unsigned int a:1
to a void*
. If you are trying to reference it, the syntax would be &mine->a
rather than mine->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));
}
Upvotes: 0
Reputation: 84189
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 }};
Upvotes: 2