Is there a way to modify this C++ struct assignment block to work in straight C
c, c++
Solution
Remove the parentheses around the string literal. The parentheses make the macro expand into an expression that will decay into a pointer type, which makes it not compile in your C compiler. A pointer type cannot be used to initialize an array. Without the parentheses, the string literal is used to initialize the array.
#define PROD_FAMILY_NAME "product name goes here"
The C standard states that a parenthesized expression takes on the same type as the unparenthesized expression, C.99 §6.5.1 ¶5:
A parenthesized expression is a primary expression. Its type and value are identical to those of the unparenthesized expression. It is an lvalue, a function designator, or a void expression if the unparenthesized expression is, respectively, an lvalue, a function designator, or a void expression.
However, while a string literal is an expression, the converse is not true. Specifically, a string literal in of itself is not a type, but a defined entity. The initialization of arrays makes a specific allowance for a string literal, C.99 §6.7.8 ¶14:
An array of character type may be initialized by a character string literal, optionally enclosed in braces.
The other allowed initializers for an array are described in C.99 §6.7.8 ¶16:
Otherwise, the initializer for an object that has aggregate or union type shall be a brace enclosed list of initializers for the elements or named members.
A parenthesized expression is not a string literal, nor a brace enclosed list of initializers.
Problem
The following code resides in a device that will issue a deviceId (LXdeviceInfo) when enumerated through an IrDA sockets connection. This is only important to explain why I would like to keep the data types as similar as possible, but be able to compile using ansi C With #includes of windows.h and af_irda.h, the following code compiles with no errors in a C++ compiler, but breaks in a C compiler just below the struct assignment (see ERROR here). Ideally I would like to initialize the struct member 'ID' to be an array of characters while keeping it typed just as it is in the original code so I can test the value of LXdeviceInfo just as it would appear when querying it from a call to the device from a PC socket connection. Is there some way to modify this assignment block to work in straight C? ``` #include <windows.h> #include <af_irda.h> #define IR_HINT_COMPUTER 0x04 #define IR_HINT_EXT 0x80 #define IR_HINT_OBEX 0x20 #define IR_HINT_IRCOMM 0x04 #define IR_CHAR_ASCII 0 #define PROD_FAMILY_NAME ("product name goes here") #define uint8_t unsigned char const struct { uint8_t hint1; uint8_t hint2; uint8_t charset; uint8_t ID[sizeof(PROD_FAMILY_NAME)]; } devInfoStorage = { IR_HINT_COMPUTER | IR_HINT_EXT, // hint1 IR_HINT_OBEX | IR_HINT_IRCOMM, // hint2 IR_CHAR_ASCII, // charset PROD_FAMILY_NAME // Prod ID string }; // ERROR here: Invalid initialization type: found 'pointer to char' expected 'unsigned char' const uint8_t *LXdeviceInfo = (uint8_t *) &devInfoStorage; /* The size of the device info */ const uint8_t LXdeviceInfoLen = sizeof(devInfoStorage); void main(void) { #define DEVICE_LIST_LEN 10 unsigned char DevListBuff[sizeof (DEVICELIST) - sizeof (IRDA_DEVICE_INFO) + (sizeof (IRDA_DEVICE_INFO) * DEVICE_LIST_LEN)]; int DevListLen = sizeof (DevListBuff); PDEVICELIST pDevList; pDevList = (PDEVICELIST) & DevListBuff; //code continues. } ```