Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to modify this C++ struct assignment block to work in straight C

Tags:

c++

c

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: Innvalid 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.

}
like image 425
ryyker Avatar asked Aug 13 '13 20:08

ryyker


People also ask

Can we use assignment operator in structure in C?

Yes, you can assign one instance of a struct to another using a simple assignment statement. In the case of non-pointer or non pointer containing struct members, assignment means copy. In the case of pointer struct members, assignment means pointer will point to the same address of the other pointer.

Can you equate structures in C?

In C, the only operation that can be applied to struct variables is assignment. Any other operation (e.g. equality check) is not allowed on struct variables.

Can we assign one structure variable to another in C?

In C/C++, we can assign a struct (or class in C++ only) variable to another variable of same type. When we assign a struct variable to another, all members of the variable are copied to the other struct variable.

Can we copy one structure to another structure?

If the structures are of compatible types, yes, you can, with something like: memcpy (dest_struct, source_struct, sizeof (*dest_struct)); The only thing you need to be aware of is that this is a shallow copy.


1 Answers

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.

like image 132
jxh Avatar answered Sep 19 '22 23:09

jxh