2013-08-13 16 views
6

次のコードは、IrDAソケット接続で列挙されたときにdeviceId(LXdeviceInfo)を発行するデバイスに存在します。これは、データ型を可能な限り似ているが、ANSI Cを使用してコンパイルできる理由を説明するためにのみ重要です。このC++構造体割り当てブロックを直接的に変更する方法はありますか?

windows.hとaf_irda.hを#includeすると、次のコードはno C++コンパイラではエラーが発生しますが、Cコンパイラは構造体割り当てのすぐ下にあります(ここではERRORを参照)。理想的には、構造体メンバを 'ID'に初期化したいのですが、元のコードと同じように型のままにしておくと、LXdeviceInfoの値をテストすることができます。 PCソケット接続からデバイスを呼び出します。

ストレート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. 

} 
+2

PROD_FAMILY_NAMEからカッコを削除してみます。 –

+2

私が知る限り、有効なCでなければなりません。おそらくそれを台無しにする文字列の周りのかっこですか?あるいは、配列の代入が取られていないかもしれません。なぜなら、unsigned charとcharがまったくマッチしていないからです。 –

+0

@ryykerそれらを 'const'と' typedef'に相当するもので置き換えるのはどうですか? – greatwolf

答えて

11

文字列リテラルの周りに括弧を削除します。かっこは、マクロをポインタ型に崩壊する式に展開します。これにより、Cコンパイラではコンパイルされません。配列を初期化するためにポインタ型を使用することはできません。かっこなしでは、文字列リテラルが配列の初期化に使用されます。括弧内の式はunparenthesized式と同じ型をとる

#define PROD_FAMILY_NAME "product name goes here" 

C標準状態、C.99 § 6.5.1 ¶ 5:

括弧内の式は一次式です。 その型と値は、カッコで囲まれていない式のものと同じです。括弧で囲まれていない式がそれぞれ左辺値、関数指定子、または空白式である場合は、左辺値、関数指定子、または空白式です。

ただし、文字列リテラルは式ですが、逆は真ではありません。具体的には、それ自体の文字列リテラルは型ではなく、定義されたエンティティです。文字型の配列は、任意 括弧で囲まれ、リテラル文字列で初期化されてもよい

:アレイの初期化は、リテラル文字列の特定引当金、C.99 § 6.7.8 ¶ 14を作ります。

アレイのための他の許容イニシャライザをC.99 § 6.7.8 ¶ 16に記載されている:

そうでなければ、凝集または共用型を持つオブジェクトの初期化子は、囲まれたブレースでなければなりません要素または名前付きメンバの初期化子のリスト。

括弧で囲まれた式は、文字列リテラルでも、イニシャライザの中括弧で囲まれたリストでもありません。行うにはhttp://ideone.com/m5ZZl0

を:PROD_FAMILY_NAMEとして

+0

ありがとうございました! – ryyker

+3

実際には、Cコンパイラのバグのように見えます。カッコはイニシャライザで完全に正当なものなので、コンパイラに強制的に式として扱わせるべきではありません。比較のため、gcc(mingw)でうまく動作します –

+0

@ChrisDodd:ありがとうございます。 – jxh

0

は(一定の)文字列で、コンパイラは、ここに私の例を参照してください文字列は、通常の文字へのポインタとして表現されているようIDはC.でメモリにuint8_t *ID;のようなものとして宣言されることを想定していこれはあなたが持っている文字配列で、私が知る限り直接配列割り当てをサポートしていないので、バイト配列にstrcpyまたはmemcpyを製品ファミリ名から行う必要があります。製品名が変数になりますが、変更されず範囲外にならない場合は、uint8_t*タイプのIDを使用することをおすすめしますが、名前のコピーが必要な場合は配列に固定したいかもしれないメモリを動的に割り当てます(ただし、古いバージョンのC標準では非静的な長さの配列はサポートされていません)。構造体の終わり、しかし、あなたは、多くの場合、そのようなアレイの場合は0を返しますsizeof()ような場合には、手動で構造体のサイズを追跡しなければならない;。strlen()のようなものはまだかかわらず、正常に動作する必要があります)


は、私が忘れてしまったようです配列の代入は許可されていませんが、のようなものですはまだです。 (http://ideone.com/vilDOahttp://ideone.com/gEC2k2)私の上記は少し意味がありませんでしたが、私は、動的なサイジング構造体は、そのような構造体の配列を持っている場合は、すべてのアイデアの良いとは思わない場合は、char*メソッド他の場所の配列へのポインタであっても良いアイデアです。

関連する問題