C Nested Structs Initialization - c

I'm an avid embedded c programmer. I recently started working with the ESP IDF framework to program the ESP32. Even though I think that the following code is initializing a struct within a struct (not sure); but for some reason, I cannot grasp how and why there is just a ".mode" rather than the struct's name within gpio_config_t + ".mode". This is just an example but there are several instances of similar types of initialization.
for example:
typedef struct example_struct{
int mode;
int pull_up_en;
.
.
}example_struct;
typedef struct gpio_config_t
{
example_struct test;
} gpio_config_t;
Shouldn't the initialization be done the following way?
gpio_config_t io_test_config =
{
test.mode = 3;
test.pull_up_en = 1;
etc
};
Can someone please clarify this?
The actual type of initialization I'm referring to:
gpio_config_t io_conf = {
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = 1,
};

The technical term for the notation you're using is designated initializers. The designators always start with either a . or a [, and there are no semicolons in the initializers (until after the } at the end of the initializer). There are many ways that you could initialize that structure, including:
gpio_config_t io_test_config1 =
{
.test.mode = 3, .test.pull_up_en = 1
};
gpio_config_t io_test_config2 =
{
.test = { .mode = 3, .pull_up_en = 1 }
};
gpio_config_t io_test_config3 =
{
{ 3, 1 }
};
gpio_config_t io_test_config4 =
{
3, 1
};
The last one doesn't compile cleanly with GCC when you specify -Wmissing-braces (usually activated by -Wall).

Related

initialize flexible array members at compile time

I'm trying to optimize boot-time and run-time of an embedded application, and to do that, I'd like to initialize some constant flexible array members at compile time. I've found a few posts that say you must use malloc, but theoretically, it should be possible to do this without...
As an example, say I have:
typedef struct _foo_t {
foo_t *next;
int num_bars;
bar_t bars[];
} foo_t __attribute((__packed__));
And I have literally have several million instances of foo_t. I then have a script to generate a header file with all the information. So I might have something like this:
const foo_t foo1 = {.next = &foo2, .num_bars = 2};
const bar_t foo1_bar1 = {...};
const bar_t foo1_bar2 = {...};
foo_t *const first_foo = &foo1;
But, the problem with this is that the compiler spec does not guarantee that &foo1_bar1 is not guaranteed to be at &foo1.bars[0]. I'm wondering if there's any trickery anyone knows to force the fooX_barY members to be placed in the correct locations in memory.
Note that my goals are:
reduce boot time by avoiding unnecessary mallocs
reduce memory thrashing by having the bar's typically in the same cache pages as corresponding foos
reduce memory requirements by not having pointers to bars
If anyone knows of any good tricks to do this, I'd love to hear them
GCC and clang seem to support standard initializers for flexible arrays so if you can restrict yourself to these compilers, you only need to add casts for const removal. The initializer does not have to use designated members, classic intializers work fine at least for clang.
This extension is actually quite consistent with the C syntax for array initializers where the length of the array can be omitted if it can be determined from the initializer.
For compilers that do not support this syntax, here is a trick to achieve what you want:
//----------------
// you can move these to foo.h
typedef int bar_t;
typedef struct foo_t {
struct foo_t *next;
char name[8];
int num_bars;
bar_t bars[];
} foo_t;
extern foo_t * const first_foo;
extern foo_t * const second_foo;
//----------------
// The definitions can be generated automatically into a separate module
// disable warnings cf: https://stackoverflow.com/a/55877109/4593267
#pragma GCC diagnostic ignored "-Wcast-qual"
#pragma clang diagnostic ignored "-Wcast-qual"
// Trick for VLA initialization
#define foo_t(n) struct { foo_t *next; char name[8]; int num_bars; bar_t bars[n]; }
// using a classic structure initializers
static const foo_t(2) foo2 = { 0, "foo2", 2, { 1, 2 }};
static const foo_t(1) foo1 = { (foo_t *)&foo2, "foo1", 1, { 42 }};
foo_t * const first_foo = (foo_t *)&foo1;
// using a compound literal
foo_t * const second_foo = (foo_t *)&(foo_t(3)){ 0, "foo3", 3, { 10, 20, 30 }};
// using gcc / clang flexible array initializer
#pragma clang diagnostic ignored "-Wgnu-flexible-array-initializer"
static foo_t third_foo = { 0, "foo4", 2, { 1, 2 }};
//----------------
// Test framework
#include <stdio.h>
void foo_print(const char *name, foo_t *p) {
printf("%s: {\n", name);
for (; p; p = p->next) {
printf(" { \"%s\", %d, { ", p->name, p->num_bars);
for (int i = 0; i < p->num_bars; i++)
printf("%d, ", p->bars[i]);
printf("}},\n");
}
printf("}\n");
}
int main() {
foo_print("first_foo", first_foo);
foo_print("second_foo", second_foo);
foo_print("third_foo", &third_foo);
return 0;
}
Output:
first_foo: {
{ "foo1", 1, { 42, }},
{ "foo2", 2, { 1, 2, }},
}
second_foo: {
{ "foo3", 3, { 10, 20, 30, }},
}
third_foo: {
{ "foo4", 2, { 1, 2, }},
}
Your attempts using certain ordering of the related variables is prone to error as the compiler does not need to allocate the variables at the place you want.
The only way to use static variables instead of dynamically allocated memory is to add the members of that flexible array directly into the initializer of your variable:
const foo_t foo1 =
{
.next = &foo2,
.num_bars = 2,
.bars =
{ [0] = {...},
[1] = {...}
}
};
Dedicated initializers are optional.
At least for GCC this should work.
Unfortunately it is not possible to use the common (sizeof(arr)/sizeof(arr[0])) trick to get the number of elements in an array:
foo_t foo1 =
{
.next = &foo2,
.bars =
{ [0] = 1,
[1] = 2
},
.num_bars = sizeof(foo1.bars)/sizeof(foo1.bars[0]),
};
test.c:21:21: error: invalid application of ‘sizeof’ to incomplete type ‘bar_t[]’ {aka ‘int[]’}
21 | .num_bars = sizeof(foo1.bars)/sizeof(foo1.bars[0]),
| ^

ctypes Structure strange behaviour?

I'm defining my structure in python according to the docs (or so I think) but when calling the c function the values don't match:
Python code:
print(f"SchemaID:{appHandResp.supportedAppProtocolRes.SchemaID}, SchemaID_isUsed:{appHandResp.supportedAppProtocolRes.SchemaID_isUsed}")
errn = openv2g.encode_appHandExiDocument(byref(oStream), byref(appHandResp))
C code:
int encode_appHandExiDocument(bitstream_t* stream, struct appHandEXIDocument* exiDoc) {
if (exiDoc->supportedAppProtocolRes_isUsed)
printf("SchemaID:%d, SchemaID_isUsed:%d\n", exiDoc->supportedAppProtocolRes.SchemaID, exiDoc->supportedAppProtocolRes.SchemaID_isUsed);
Output:
# in Python right before calling the C function
SchemaID:2, SchemaID_isUsed:1
# in the C function
SchemaID:1, SchemaID_isUsed:0
The structure definitons:
# Python3.8
appHandresponseCodeType = ctypes.c_uint8
appHandresponseCodeType_OK_SuccessfulNegotiation,\
appHandresponseCodeType_OK_SuccessfulNegotiationWithMinorDeviation,\
appHandresponseCodeType_Failed_NoNegotiation = map(appHandresponseCodeType, range(3))
class appHandAnonType_supportedAppProtocolRes(ctypes.Structure):
_fields_ = [
("ResponseCode", appHandresponseCodeType),
("SchemaID", ctypes.c_uint8),
("SchemaID_isUsed", ctypes.c_uint, 1),
]
.
// C
typedef enum {
appHandresponseCodeType_OK_SuccessfulNegotiation = 0,
appHandresponseCodeType_OK_SuccessfulNegotiationWithMinorDeviation = 1,
appHandresponseCodeType_Failed_NoNegotiation = 2
} appHandresponseCodeType;
struct appHandAnonType_supportedAppProtocolRes {
appHandresponseCodeType ResponseCode ;
uint8_t SchemaID ;
unsigned int SchemaID_isUsed:1;
};
Playing with the structure definition in python I was able to get the expected result:
appHandresponseCodeType = ctypes.c_uint
appHandresponseCodeType_OK_SuccessfulNegotiation,\
appHandresponseCodeType_OK_SuccessfulNegotiationWithMinorDeviation,\
appHandresponseCodeType_Failed_NoNegotiation = map(appHandresponseCodeType, range(3))
class appHandAnonType_supportedAppProtocolRes(ctypes.Structure):
_fields_ = [
("ResponseCode", appHandresponseCodeType),
("SchemaID", ctypes.c_uint8),
("SchemaID_isUsed", ctypes.c_uint8),
]
Output:
# in Python right before calling the C function
SchemaID:2, SchemaID_isUsed:1
# in the C function
SchemaID:2, SchemaID_isUsed:1
I can't explain why this is the case, am I defining my structure in ctypes wrong?
Not 100%, but I think that this shows the underlying problem:
#include <stdio.h>
typedef struct A {
char x;
unsigned y:1;
} A;
int main() {
printf("%zu\n", sizeof(A));
return 0;
}
prints the value '4' using clang/macos/64bit, gcc/linux/64bit. It is because of the bitfield permitting the compiler to compact the structure.
This should work for you. A C enum is equivalent to a c_int. You don't need to cast the enum values. Just assign them to ResponseCode as needed. It is odd to use a bitfield for a single bit. That one bit will still occupy a full c_uint (typically 32-bits) anyway. There will also normally be three padding bytes between the c_uint8 and the next c_uint for alignment purposes, unless you also set _pack_ as well (must be before _fields_ if used). Check the C header for any packing directives.
from ctypes import *
appHandresponseCodeType_OK_SuccessfulNegotiation = 0
appHandresponseCodeType_OK_SuccessfulNegotiationWithMinorDeviation = 1
appHandresponseCodeType_Failed_NoNegotiation = 2
class appHandAnonType_supportedAppProtocolRes(Structure):
# _pack_ = 1 # if needed, uncomment.
_fields_ = (('ResponseCode',c_int),
('SchemaID',c_uint8),
('SchemaID_isUsed',c_uint,1))

Unclear structure variable usage - C

While browsing through the Linux kernel code, I came across something like this.
struct dma_chan {
int lock;
const char *device_id;
};
static struct dma_chan dma_chan_busy[MAX_DMA_CHANNELS] = {
[4] = { 1, "cascade" },
};
what is this - [4] = { 1, "cascade" }, - usage implying ?
Note : Kernel version is 2.6.32
This is a designated initializer. It initializes the fifth element to { 1, "cascade" } explicitly, the other ones are default-initialized.

How do I suppress PC-Lint errors for C99-style initialization of structure members?

I am using PC-Lint 8.00x with the following options:
+v -wlib(1) +fan +fas
I receive a number of error messages from PC-Lint when I run code similar to the following:
typedef union
{
struct
{
unsigned int a : 4;
unsigned int b : 4;
unsigned int c : 4;
unsigned int d : 4;
} bits;
unsigned short value;
} My_Value;
int main (void)
{
My_Value test[] =
{
{
.bits.a = 2,
.bits.b = 3, //Errors 133 and 10
.bits.c = 2,
.bits.d = 3,
},
{
.bits.a = 1,
.bits.b = 1, //Errors 133 and 10
.bits.c = 1,
.bits.d = 0,
},
};
/* Do something meaningful. */
return 0;
}
The reported errors are defined by PC-Lint as follows:
Error 133: Too many initializers for aggregate 'unknown-name'
Error 10: Expecting '}'
I have tried searching Gimpel and have done some Google searches, but I cannot find anything useful. The code functions as intended and everything initializes properly. Here are my questions.
1. Does PC-Lint 8.00x support C99 style initialization of structure members?
2. If so, what options/flags do I have to set for PC-Lint to suppress these messages globally?
EDIT
I should have been more detailed in regards to question 2. I would like to globally suppress these messages in regards to my usage of designated initializers as shown above. I cannot suppress them globally for all situations as these errors can detect true errors in the code.
As far as I can tell, this syntax:
My_Value test[] =
{
{
.bits.a = 2,
.bits.b = 3,
.bits.c = 2,
.bits.d = 3,
},
{
.bits.a = 1,
.bits.b = 1,
.bits.c = 1,
.bits.d = 0,
},
};
is valid in C99 (and C11). Looking in section 6.7.8 of the standard, the thing preceding the = in an initializer is a designator-list, which is a sequence of one or more designators. .bits.a is valid in that context.
Apparently PC-Lint doesn't support that syntax. (You might want to notify the maintainers, unless it's already supported in a later version.)
As a workaround, if you change it to this:
My_Value test[] =
{
{ .bits =
{
.a = 2,
.b = 3,
.c = 2,
.d = 3,
},
},
{ .bits =
{
.a = 1,
.b = 1,
.c = 1,
.d = 0,
},
},
};
it's still valid C (and arguably clearer) and, based on what you just wrote in a comment, PC-Lint accepts it.
(If you want to be even more explicit, you might consider adding [0] = and [1] = designators.)
UPDATE : QUoting a new commment:
The good people at Gimpel software have responded stating that "this
appears to be a bug" and are working to correct it.
Not sure to the C99 and 8.00x support question, as I have 9.00k installed. But 9.00k dislikes your form of union initialization, but Visual Studio has no issue.
But for Jacchim Pileborg's case it just emits a Info 708: union initialization while might be safer to turn off.
As noted in the comments you dont want to fully globally remove these error types, so -e133 and -e10 will not solve your problems.
So using Joachim's form, I can using a macro suppress it like so:
typedef union
{
struct
{
unsigned int a : 4;
unsigned int b : 4;
unsigned int c : 4;
unsigned int d : 4;
} bits;
unsigned short value;
} My_Value;
#define MY_UNION(A,B,C,D) /*lint -save -e708*/{{.a=(A),.b=(B),.c=(C),.d=(D)}}/*lint -restore*/
int main(void)
{
My_Value test[] =
{
MY_UNION(2, 3, 2, 1),
MY_UNION(1, 2, 3, 4)
};
return 0;
}
Ugly, but as you have nothing to make the lint commands to stick to as it's all anonymous, you ether have to put inline commands explicitly or via a macro.

Initializing structure by named members

I'm trying to wrap my head around the syntax provided in http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=%2Fcom.ibm.vacpp7l.doc%2Flanguage%2Fref%2Fclrc03strin.htm :
struct
{
int a[5], b;
} game[] =
{
[0].a = { 1 },
[1].a[0] = 2
};
Ideally, I'd find some way to do the following:
struct
{
int a, b;
} foo =
{
.a = 4,
.b = 5
};
My reason for wanting to have a by-name initialization of a structure is that my own stucture has many members, so I want better clarity. I shouldn't just initialize them in separate statements because this is a performance-sensitive embedded application where the members are actually bitfields, so a single struct init generates fewer instructions than multiple member initializations.
Which C standard allows for by-name member init like that?
It's not immediately clear what you're asking, but with a c99 compiler, your first attempt could be written as
struct
{
int a[5], b;
} game[] =
{
[0] = {.a = { 1 }},
[1] = {.a[0] = 2}
};
I'm doing something similar in an embedded app under C99. I have a variable called phaseInstill that is "assigned" to a struct:
phaseInstill = (PhaseVolumeStatus)
{
.complete = false,
.ticksInstilled = 0,
.volumeInstilled = 0,
.volumeRemaining = instillVolume
};
Where PhaseVolumeStatus is defined as:
typedef struct
{
Value volumeRemaining; /*!> ml */
Value volumeInstilled; /*!> ml */
Value ticksInstilled; /*!> ticks */
bool complete;
} PhaseVolumeStatus;
I don't have a bitfield example handy, but I don't recall it working any differently in any other of my uses.

Resources