6

次のコードは、IrDA ソケット接続を介して列挙されたときに deviceId (LXdeviceInfo) を発行するデバイスに存在します。これは、データ型を可能な限り同じに保ちたいが、ansi C を使用してコンパイルできるようにしたい理由を説明するためにのみ重要です。

windows.h と af_irda.h の #includes を使用すると、次のコードは C++ コンパイラではエラーなしでコンパイルされますが、C コンパイラでは構造体割り当てのすぐ下で中断します (こちらのエラーを参照)。理想的には、構造体メンバー'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.

}
4

2 に答える 2

11

文字列リテラルを囲む括弧を削除します。括弧により、マクロはポインター型に崩壊する式に展開され、C コンパイラーでコンパイルされなくなります。ポインター型を使用して配列を初期化することはできません。かっこがない場合、文字列リテラルを使用して配列を初期化します。

#define PROD_FAMILY_NAME "product name goes here"

C 標準では、括弧で囲まれた式は、括弧で囲まれていない式と同じ型を取ると規定されています (C.99 §6.5.1 ¶5)。

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

ただし、文字列リテラルは式ですが、その逆は当てはまりません。具体的には、文字列リテラル自体は型ではなく、定義されたエンティティです。配列の初期化では、文字列リテラル、C.99 §6.7.8 ¶14 に特定の許可が与えられます。

文字型の配列は、必要に応じて中括弧で囲まれた文字列リテラルによって初期化できます。

配列に許可されているその他の初期化子は、C.99 §6.7.8 ¶16 で説明されています。

それ以外の場合、集約型または共用体型を持つオブジェクトの初期化子は、要素または名前付きメンバーの初期化子の中かっこで囲まれたリストでなければなりません。

括弧で囲まれた式は、文字列リテラルでも、中括弧で囲まれた初期化子のリストでもありません。

于 2013-08-13T20:06:46.290 に答える
0

PROD_FAMILY_NAME(定数) 文字列と同様に、コンパイラは、文字列が一般に C のメモリ内の文字へのポインターとして表されるように、次のようなものとして宣言されることを期待しています。ここで私の例を参照してくださいID: http://ideone.com/m5ZZl0uint8_t *ID;

あなたが持っているように文字配列でこれを行うには、私が知る限り、Cは直接配列割り当てをサポートしていないため、製品ファミリ名からバイト配列にstrcpyorを実行する必要があります。製品名が変数になるが変更されず、範囲外にならない場合は、 -typedを使用することをお勧めしますが、名前のコピーが必要で動的に割り当てたくない場合配列に固執したいかもしれません(ただし、C標準の古いバージョンは非静的長配列もサポートしていないことに注意してください[ただし、可変長配列を最後に使用して回避する方法があります構造体ですが、そのような配列に対して 0 を返すような場合には、多くの場合、構造体のサイズを手動で追跡する必要があります。memcpyIDuint8_t*IDsizeof()strlen()それでも問題なく動作するはずです。)


忘れていたようですが、配列の割り当ては許可されていませんが、char array[] = "literal string";まだ許可されているようなものです。(http://ideone.com/vilDOahttp://ideone.com/gEC2k2)したがって、上記は少し無意味でしたが、構造体の動的なサイズ変更は、必要に応じてそれほど良いアイデアではないと思いますそのような構造体の配列を持つ場合、char*メソッドはより良いアイデアになる可能性があります (たとえそれが他の場所の配列へのポインターであっても)。

于 2013-08-13T20:07:55.720 に答える