I was using a flexible array member to define a USB-String descriptor:
// defined
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bString[];
} ATTR_PACKED USB_StringDescriptor;
// declared
#define STR_PRODUCT L"My Cool Product"
const USB_StringDescriptor __flash manufacturer_string = {
sizeof(STR_PRODUCT)+2,
USB_DTYPE_String, // 0x03
STR_PRODUCT
};
This worked great and allowed the actual string constants to be defined elsewhere for easy changes between projects. But I can no longer use flexible array members because of compiler restrictions. I would like to avoid hardcoding a char array, I basically just need to tack two bytes to the front of a wide character array. Is there any clever way of declaring an array or a pre-processor macro that could accomplish this?
I see no way to achieve a struct with flexible size without the use of dynamic memory allocation in a portable way.
However, one of the following two approaches with a fixed size struct might work for you as well:
bstring
is an array of fixed size; If you have only one STR_PRODUCT
in your program, you can use it's size. If you have more instances of the struct, define the array with the maximum size you want to allow. bstring
being a pointer; You can still initialize it with a pointer to a string literal. Note that an object will then not contain all the information in a continuous memory block. If you require continuous memory containing all the information, this approach 2 will not work.See the following program which demonstrates both approaches:
#define STR_PRODUCT_1 L"My Cool Product"
#define STR_PRODUCT_2 L"Another Cool Product"
#define MAX_PRODUCT_STR "012345678901234567890"
// Approach 1:
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
wchar_t bString[sizeof(MAX_PRODUCT_STR)];
} USB_StringDescriptor;
const USB_StringDescriptor manufacturer_string = {
sizeof(STR_PRODUCT_1)+2,
0x03,
STR_PRODUCT_1
};
const USB_StringDescriptor manufacturer_string2 = {
sizeof(STR_PRODUCT_2)+2,
0x03,
STR_PRODUCT_2
};
// Approach 2:
typedef struct {
uint8_t bLength;
uint8_t bDescriptorType;
wchar_t *bString;
} USB_StringDescriptor_V2;
const USB_StringDescriptor_V2 manufacturer_string_v2 = {
sizeof(STR_PRODUCT_1)+2,
0x03,
STR_PRODUCT_1
};
const USB_StringDescriptor_V2 manufacturer_string_v2_2 = {
sizeof(STR_PRODUCT_2)+2,
0x03,
STR_PRODUCT_2
};
int main() {
wprintf(L"1: %ls\n",manufacturer_string.bString);
wprintf(L"2: %ls\n",manufacturer_string2.bString);
wprintf(L"1 ptr: %ls\n",manufacturer_string_v2.bString);
wprintf(L"2 ptr: %ls\n",manufacturer_string_v2_2.bString);
}