2013-08-13 7 views
6

Il seguente codice risiede in un dispositivo che emetterà un deviceId (LXdeviceInfo) quando viene enumerato tramite una connessione socket IrDA. Questo è importante solo per spiegare perché vorrei mantenere i tipi di dati il ​​più simili possibile, ma essere in grado di compilare usando ansi CC'è un modo per modificare questo blocco di assegnazione struct C++ per lavorare in modo diretto C

Con #inclusi di windows.h e af_irda.h, il seguente codice viene compilato senza errori in un compilatore C++, ma si rompono in un compilatore C appena sotto l'assegnazione della struttura (vedi ERRORE qui). Idealmente, vorrei inizializzare il membro della struct 'ID' in modo che fosse una matrice di caratteri mantenendolo digitato esattamente come nel codice originale in modo da poter verificare il valore di LXdeviceInfo così come apparirebbe quando lo si interroga da un chiamare il dispositivo da una connessione socket PC.

C'è un modo per modificare questo blocco di assegnazione in modo che funzioni in C corretto?

#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. 

} 
+2

Prova a rimuovere le parentesi da PROD_FAMILY_NAME. –

+2

Per quanto posso dire che dovrebbe essere valido anche C. Forse la parentesi attorno alla stringa lo incasina? O forse l'assegnazione dell'array non sta prendendo perché un char non firmato e un char non sono abbastanza corrispondenti. –

+0

@ryyker, che ne dici di sostituire quelli che definiscono con i loro equivalenti 'const' e' typedef'? – greatwolf

risposta

11

rimuovere le parentesi intorno alla stringa letterale. Le parentesi rendono la macro espandibile in un'espressione che decadrà in un tipo di puntatore, che lo rende non compilabile nel compilatore C. Non è possibile utilizzare un tipo di puntatore per inizializzare una matrice. Senza le parentesi, la stringa letterale viene utilizzata per inizializzare la matrice.

#define PROD_FAMILY_NAME "product name goes here" 

Lo standard C che un'espressione tra parentesi assume lo stesso tipo come l'espressione unparenthesized, C.99 § 6.5.1 ¶ 5:

Un'espressione parentesi è un'espressione primaria. Il tipo e il valore sono identici a quelli dell'espressione non interattiva. È un lvalue, un designatore di funzione o un'espressione void se l'espressione non parodizzata è, rispettivamente, un lvalue, un designatore di funzione o un'espressione void.

Tuttavia, mentre una stringa letterale è un'espressione, il contrario non è vero. Nello specifico, una stringa letterale in sé non è un tipo, ma un'entità definita. L'inizializzazione degli array rende uno specifico fondo per una stringa letterale, C.99 § 6.7.8 ¶ 14:

Matrice di tipo carattere può essere inizializzato da una stringa di caratteri letterale, opzionalmente racchiuso tra parentesi .

Gli altri inizializzatori consentiti per un array sono descritti in C.99 § 6.7.8 ¶ 16:

Altrimenti, l'inizializzatore per un oggetto che è di tipo globale o unione è racchiuso un tutore elenco di inizializzatori per gli elementi o membri con nome.

Un'espressione tra parentesi non è una stringa letterale, né un elenco di catalizzatori racchiuso tra gli inizializzatori.

+0

Grazie - l'ha fatto! – ryyker

+3

In realtà, sembra un bug nel compilatore C - le parentesi sono perfettamente legali in un inizializzatore, quindi non dovrebbe forzare il compilatore a considerarlo come un'espressione. Per confronto, funziona bene con gcc (mingw) –

+0

@ChrisDodd: Grazie, notato. – jxh

0

Come PROD_FAMILY_NAME è una (costante) della stringa, il compilatore si aspetta ID essere dichiarati come qualcosa di simile uint8_t *ID; come stringhe sono generalmente rappresentati come puntatori a caratteri in memoria in C. Vedere mio esempio qui: http://ideone.com/m5ZZl0

Per fare questo con un array di caratteri come quello che hai, devi fare un strcpy o memcpy dal nome della famiglia del prodotto all'array di ID byte poiché C non supporta l'assegnazione diretta dell'array per quanto ne so. Se il nome del prodotto sarà una variabile ma non cambierà e non uscirà dall'ambito, ti consigliamo di utilizzare uno uint8_t* di tipo ID, ma se hai bisogno di una copia del nome e non vuoi allocare dinamicamente la memoria che si desidera attaccare con un array (ma si noti che le versioni precedenti dello standard C non supportano gli array di lunghezza non statica, anche [sebbene ci siano modi per aggirare il problema con un array a lunghezza variabile fine della struct, ma spesso si devono tenere traccia delle dimensioni struct manualmente in questi casi come sizeof() restituirà 0 per tali matrici;. le cose come strlen() dovrebbe ancora funzionare bene, però)


Sembra ho dimenticato che, mentre l'assegnazione dell'array non è consentita, qualcosa comeLo è ancora. (http://ideone.com/vilDOa rispetto a http://ideone.com/gEC2k2) Quindi il mio sopra era un po 'inutile, ma penso che il dimensionamento dinamico delle strutture non sia il massimo di un'idea se si vuole avere una matrice di tali strutture, nel qual caso il metodo char* può essere un'idea migliore (anche se è solo un puntatore a un array altrove).

Problemi correlati