When doing embedded programming with C, many times I find myself doing maps with enum and array because they are fast and memory efficient.
enum {
ID_DOG = 0,
ID_SPIDER,
ID_WORM,
ID_COUNT
};
int const NumberOfEyes[ID_COUNT] = {
2,
8,
0
};
Problem is that sometimes when adding/removing items, I make mistake and enum and array go out of sync. If initializer list is too long, compiler will detect it, but not other way around.
So is there reliable and portable compile time check that initializer list matches the length of the array?
This is possibly a situation where X macros could be applied.
animals.x
X(DOG, 2)
X(SPIDER, 8)
X(WORM, 0)
foo.c
enum {
#define X(a,b) ID_##a,
#include "animals.x"
#undef X
};
int const numberOfEyes[] = {
#define X(a,b) b,
#include "animals.x"
#undef X
};
This not only guarantees that the lengths match, but also that the orders are always kept in sync.
What about a compile time assertion like the following? (Yes, there are more elaborate CT_ASSERT macros; this is to illustrate the idea.)
#define CT_ASSERT(expr, name) typedef char name[(expr)?1:-1]
enum {
ID_DOG = 0,
ID_SPIDER,
ID_WORM,
ID_COUNT
};
int const NumberOfEyes[] = {
2,
8,
0
};
CT_ASSERT (sizeof NumberOfEyes/sizeof *NumberOfEyes == ID_COUNT, foo);
Now when the NumberOfEyes array has more or less elements than ID_COUNT, this will cause an error along x.c:15: error: size of array 'foo' is negative. Negative array dimensions are a constraint violation that must be diagnosed by any C compiler out there.
Related
C99 allows array initializers (among others) to specify which element of the array is being set with a positive integer designator ($6.7.8.6, $6.7.8.17), for example like so:
const char *foo[] = {[2] = "foo", [1] = "bar", [0] = "baz"};
I have previously used this to make an enum-to-string table like so:
enum {THING_FOO = 0, THING_BAR, THING_BAZ};
const char *table[] = {
[THING_FOO] = "foo",
[THING_BAR] = "bar",
[THING_BAZ] = "baz"
}
However, I am now working under the requirement that my code is c89 compliant.
I have looked into preprocessor magic (as in here, for example) but I need the strings to be arbitrary, not copies of the enum symbols.
It isn't sufficient to just do
enum {THING_FOO = 0, THING_BAR, THING_BAZ};
const char *table[] = {"foo", "bar", "baz"};
because I will need to add enum elements in the future. Using the c99 method, this would result in NULL pointers in the table which are acceptably easy to debug if they become problems. If I forgot to update the string table using this method, I'd get segfaults which are harder to debug. Also it defeats the point of having symbols if I have to remember offsets anyway.
If the declaration were in a function, I could achieve the desired effect like this:
enum {THING_FOO = 0, THING_BAR, THING_BAZ, NUM_THINGS};
void foo(void)
{
static const char *table[NUM_THINGS];
table[THING_FOO] = "foo";
table[THING_BAR] = "bar";
table[THING_BAZ] = "baz";
/* ... */
}
However, at least with gcc, this does not get optimized.
Is there any way of declaring such a string table in c89?
(It's no problem in assembly.)
What about the simple, old fashioned
const char* table[] = { "foo", "bar", "baz" };
In other words, just put them in the correct order.
char *foo_string = table[FOO];
Of course, that only works for simple enums like the above, not for enums in the style
enum { FOO = 13; BAR = 15, BAZ = 312 };
But for that, you would have to create an array with at least 313 elements, most of which are NULL anyway, which would be a pretty wasteful construct. In such cases, the compiler can optimize this for you, when you use a switch construct.
Also take a look at the S.O. question #Leandros pointed to: How to convert enum names to string in c. The answer there uses macros to generate the array, which ensures the entries are in the correct order.
Or, as that answer says:
#define enum_str(s) #s
Which gets rid of the array altogether.
#define DEF_FOO_ENUM(E0, S0, E1, S1, E2, S2) \
enum foo { E0, E1, E2 }; \
const char *foo_str = { S0, S1, S2 };
DEF_FOO_ENUM(THING_FOO, "foo",
THING_BAR, "bar",
THING_BAZ, "baz");
The symbols and strings are paired. You're not easily going to add a new symbol without a string, or vice versa. To add an element, you have to two new arguments to the macro—E3, S3—and so on. There is nothing to keep in sync there, just that the enum has all the E-s and the array has all the S-s. This is almost impossible to screw up.
You can keep them together by using X-Macros:
#define MYXMACRO(OP) \
OP(ENUM_FOO, "foo") \
OP(ENUM_BAR, " bar") \
OP(ENUM_BAZ, "baz")
/* use the first parameter to set up your enums*/
enum {
#define AS_ENUMS(x,y) x,
MYXMACRO(AS_ENUMS)
#undef AS_ENUMS /*not required, just playing nice*/
NUMTHINGS
};
/* use the 2nd parameter to set up your strings*/
const char *strings[] = {
#define AS_STRINGS(x,y) y,
MYXMACRO(AS_STRINGS)
#undef AS_STRINGS
};
#undef MYXMACRO
Now your new data can be added as a set of enum and string. If you later decided to add something else based on the enums it's easily extended with a 'z' parameter to OP() or even ... and __VA_ARGS__ for multiple but varying number of parameters.
After trying a few different techniques, this one is easiest to maintain:
const char *table[] = {
#define FOO 0
"foo",
#define BAR (FOO + 1)
"bar",
#define BAZ (BAR + 1)
"baz"
}
Here all the information about an entry is clustered. To insert an element you only have to modify stuff right around it. For example to insert qux:
const char *table[] = {
#define FOO 0
"foo",
#define QUX (FOO + 1) /* new */
"qux", /* new */
#define BAR (QUX + 1) /* modified */
"bar",
#define BAZ (BAR + 1)
"baz"
}
It's a bit ugly (kind of endearing, you know?) but it works good.
Assume i have define structure which has one array. I have initialize the array in main program. But now how can i find the number of element initialized in the array. I have created arrays of struct object too.
#include <stdio.h>
#define noOfArray 10
struct Arrays
{
int data[100];
int size;
int discardArray; //1 for true and 0 for false
};
void main( )
{
int size=0,i,j;
struct Arrays arrayObject[10]={
{{1,2,3,4}},
{{1,3,5,6,3,4}},
{{1,6,7,8,9,10,11,43,4}}
};
size = sizeof arrayObject[0].data / sizeof arrayObject[0].data[0];
}
This size gives me 100 but i need total number of element present in arrayObject[0].data.
Event tried with
int arr[] = {1,2,3,4};
struct Arrays arrayObject[10] = {
{arr,sizeof arr/sizeof arr[0]},
{{1,3,5,6,3,4}},
{{1,6,7,8,9,10,11,43,4}}
};
But this doesn't compile: Near to sizeof start it is saying invalid initialization.
What I'm really looking for is any way to store n arrays, where the first array can be compared to other arrays. The element preset in the arrays with be of varying size.
Your compile time error is that you're trying to use arr as a value to initialize arrayObject to. However, C only allows values that are known at compile time to be used as initializers. arr is an address on the stack that won't be known until execution time, therefore it can't be used as an initializer.
You should be able to initialize to sizeof arr/sizeof arr[0], which will be the count of elements in the array, but you can't initialize to arr, sizeof arr/sizeof arr[0].
The flaw in what you're trying to do is the way you're trying to distinguish between initialized vs. uninitialized elements.
int a[100] = { 1, 2 };
Does initialize all 100 elements. The elements not mentioned in the initializer list are initialized to zero. You can't use sizeof(a)/sizeof(a[0]) to count initialized elements.
You could do something like
#define INIT_LIST { 1, 2, 111} // 257
#define ASIZE 100
int big_array[ASIZE] = INIT_LIST;
// this works with gcc -O1 / -Og, but dummy is there in the object file at -O0
static const char dummy[] = INIT_LIST;
int initialized_count = sizeof(dummy); // sizeof(char) is guaranteed to be 1, so no divisor is needed.
// Or even better, no dummy array in the object file even with -O0:
int initialized_count2 = sizeof((int[])INIT_LIST)/sizeof(int);
// This also avoids compiler warnings when constants in the initializer list don't fit in a char.
// in macro form: Be careful with very large initializers; this could compile slowly if you used it all over the place.
#define COUNT_INITLIST (x) (sizeof((long[])x)/sizeof(long))
// Even with optimization on, this will also compile away to just returning a constant
int initialized_in_big_array() {
// without optimization: dummy2 is there in the object file
// but still not copied to the stack, because of const
const char dummy2[] = INIT_LIST;
return sizeof(dummy2);
}
It turns out even at low optimization levels like -Og, compilers avoid emitting unused arrays entirely. So the inline-function isn't needed. Jens Gustedt's suggestion of casting the initializer list, so there is never an array, is the best.
One solution is to put a sentinel value at the end of the array. For example, if negative values are not normally allowed in the array, then you could use the value -1 to mark the end of the array.
struct Arrays arrayObject[10]={
{{1,2,3,4,-1}},
{{1,3,5,6,3,4,-1}},
{{1,6,7,8,9,10,11,43,4,-1}}
};
This allows you to use a simple for loop to count the number of valid entries in the array.
I'm trying to initialize a const struct with a designated initializer. However, one of the struct elements is a fixed-width array. I already have the contents I would like to initialize the array with in another fixed-width array of appropriate size.
Is there any way to do this with a designated initializer? A simple (failing example) of what I'm trying to accomplish is demonstrated below.
struct foo {
uint8_t array1[4];
uint8_t array2[4];
}
uint8_t array[4] = {
1, 2, 3, 4
};
struct foo const bar = {
.array1 = array, // incompatible pointer to integer conversion
.array2 = { *array } // only copies the first element
};
Short answer: you can't. C does not copy arrays (without the use of (standard library-)functions). The warnings come from the fact that you cannot assign an array as a whole, even when they are static or constant. When an array is used as an r-value in an assignment it decays to a pointer and thus cannot be assigned to another array (as a whole).
The easiest way to go would be to use memcpy, but obviously that must be inside a function.
If bar has global scope, or is declared static, then you won't be able use designated initializers to initialize from non-immediate values, regardless of whether or not the members in question are arrays.
However, if:
bar is declared on the stack of some function, and
Your fixed-size array really does only have 4 elements,
then you might be able to get away with something like this:
#include <stdio.h>
#include <stdint.h>
struct foo {
uint8_t array1[4];
uint8_t array2[4];
};
#define ARRAY_INIT(a) { a[0], a[1], a[2], a[3] }
int main (int argc, char **argv) {
uint8_t arr_init[4] = {
1, 2, 3, 4
};
struct foo const bar = {
.array1 = ARRAY_INIT(arr_init),
.array2 = ARRAY_INIT(arr_init),
};
printf("%d, %d\n", bar.array1[0], bar.array2[3]);
return (0);
}
The initializer array must appear before what is being initialized in the stack frame. Or it may come from a function parameter.
Of course if your array is much bigger than this, then using a macro like this will get very messy indeed.
While you may not be able to initialize the array by copying from another array, it may be helpful to use a preprocessor macro:
#define ARRAY_INIT {1, 2, 3, 4}
struct foo const bar = {
.array1 = ARRAY_INIT,
.array2 = ARRAY_INIT
};
Is there a nice way to combine designated initializers from C99, with the result of a malloc?
The following seems to have needless duplication:
typedef struct {
int a, b, c;
} Type;
Type *t = malloc(sizeof *t);
*t = (Type) {
.a = 2,
.b = 3,
.c = 5,
};
Can the use of Type, and *t be removed from the above code?
Since you asked ;) there is one tool in C to avoid explicit duplication of code, macros. That said I don't see a way not to repeat at least the name of the type. But in C++ they can't either, so C is at least as good :)
The easiest I see is
#define DESIGNATE_NEW(T, ...) \
memcpy(malloc(sizeof(T)), \
&(T const){ __VA_ARGS__ }, \
sizeof(T))
which would give
Type *t = DESIGNATE_NEW(Type,
.a = 2,
.b = 3,
.c = 5,
);
this has several advantages.
It initializes all members correctly, even on architectures with non
standard representations of the 0 for float types or pointers.
Other than Keith' version it is "coding style" acceptable since it is just an expression that looks like an initialization and anybody should immediately capture visually what the second code snipset is supposed to do.
NB: Observe the const in the macro, this allows several instances of the compound literal to be folded, if the compiler decides this to be relevant. Also there are means to have a variant where the list of designators is optional, see P99 below.
The disadvantage is the memcpy and I would be happier with an assignment. Second there is no check for failure of malloc before using the result, but one could probably come across with some weirdness to have the code exit nicely.
In P99 I go a slightly different way. There we always have an initialization function for a type, something like
inline
Type* Type_init(Type* t, int a, int b, int c) {
if (t) {
*t = (Type const){ .a = a, .b = b, .c = c };
}
return t;
}
which by macro magic can be made to provide default arguments for a, b and c if they are omitted. Then you can simply use something like
Type *t = P99_NEW(Type, 1, 2, 3);
in your application code. This is better, since it avoids dereferrencing the pointer when the call to malloc failed. On the other hand this reintroduces an order to the initializers, so not perfect either.
You can with a variadic macro. I'm not going to claim that this is a good idea, but it works:
#include <stdlib.h>
#include <stdio.h>
#define CREATE(type, ptr, ...) \
type *ptr = malloc(sizeof *ptr); \
if (ptr) *ptr = (type){__VA_ARGS__}
int main(void)
{
typedef struct {
int a, b, c;
} Type;
CREATE(Type, t, .a = 2, .b = 3, .c = 5);
printf("t->a = %d, t->b = %d, t->c = %d\n", t->a, t->b, t->c);
return 0;
}
Note that I wasn't able to use the usual do { ... } while (0) macro definition trick (it would create a new scope, and t wouldn't be visible), so you'd have to be careful about the context in which you use this.
Personally, I think I'm happier with the needless duplication.
No, that's the only way to use designated initializers. Without the (Type){}, the compiler doesn't know how to validate the contents.
When declaring a const table, it is possible to get the size of the table using sizeof. However,
once you stop using the symbol name, it does not work anymore. is there a way to have the following program output the correct size for table A, instead of 0 ?
#include <stdio.h>
struct mystruct {
int a;
short b;
};
const struct mystruct tableA[] ={
{
.a = 1,
.b = 2,
},
{
.a = 2,
.b = 2,
},
{
.a = 3,
.b = 2,
},
};
const struct mystruct tableB[] ={
{
.a = 1,
.b = 2,
},
{
.a = 2,
.b = 2,
},
};
int main(int argc, char * argv[]) {
int tbl_sz;
const struct mystruct * table;
table = tableA;
tbl_sz = sizeof(table)/sizeof(struct mystruct);
printf("size of table A : %d\n", tbl_sz);
table = tableB;
tbl_sz = sizeof(tableB)/sizeof(struct mystruct);
printf("size of table B : %d\n", tbl_sz);
return 0;
}
Output is :
size of table A : 0
size of table B : 2
This is the intended behavior of sizeof. But is there a way for a compiler to know the size of a const table, given a pointer to the table instead of the symbol name ?
you are asking for the sizeof a pointer. That is always the pointer size (ie usually 4 bytes on a 32-bit machine and 8 bytes on a 64-bit machine). In the 2nd attempt you are asking for the sizeof the array and hence you get the result you'd expect.
Is there a way for a compiler to know the size of a const table, given a pointer to the table instead of the symbol name?
No, because sizeof() is evaluated at compile-time (unless it is a VLA, but a VLA is not a constant table), and the compiler cannot, in general, tell which table the pointer is pointing to. Granted, in the scenario shown, it might be possible in some hypothetical variation of the C language, but that would mean varying definitions of what sizeof() returns, which would be a bigger problem than not getting the answer you might like but do not get.
So, as everyone else ably pointed out, when you take the size of a pointer, you get the size of the pointer. Assuming a standard 32-bit machine since the results are consistent with that assumption, your structure is 8 bytes and your pointers are 4 bytes, so the result of the division is zero, as expected.
No - you're asking for the sizeof() a pointer. But since what you're really trying to get is the number of elements in an array, you can use a macro that will return that value but will generally give you an error if you pass a pointer instead of an array:
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
See this SO answer for more details: Is there a standard function in C that would return the length of an array?
For an even safer solution when using C++ instead of C, see this SO answer that uses templates to ensure that trying to get an array count on a pointer will always generate an error: Compile time sizeof_array without using a macro
Short answer is no; if all you have is a pointer, then there's no (standard) way to get the size of the thing being pointed to through that pointer.
Although syntactically correct, your sample is more conventionally written as:
const struct mystruct tableA[] = {
{1, 2},
{2, 2},
{3, 3},
};
Which is less verbose and therefore more readable.