web-dev-qa-db-ja.com

typedef固定長配列

24ビットデータ型を定義する必要があります。char[3]を使用して型を表します。 char[3]type24にtypedefできますか?コードサンプルで試してみました。ヘッダーファイルにtypedef char[3] type24;を配置します。コンパイラはそれについて文句を言いませんでした。しかし、Cファイルでvoid foo(type24 val) {}という関数を定義すると、文句を言いました。 type24_to_int32(type24 val)の代わりにtype24_to_int32(char value[3])のような関数を定義できるようにしたいと思います。

187
341008

Typedefは

typedef char type24[3];

ただし、結果の型は配列型であるため、これはおそらく非常に悪い考えですが、そのユーザーはそれが配列型であることを認識しません。関数の引数として使用される場合、値ではなく参照によって渡され、そのためのsizeofは間違っています。

より良い解決策は

typedef struct type24 { char x[3]; } type24;

また、おそらくcharの代わりにunsigned charを使用する必要があります。後者は実装定義の符号付きであるためです。

276
R..

あなたが欲しい

typedef char type24[3];

Cの型宣言はそのように奇妙です。その型の変数を宣言する場合、変数名が行くところに正確に型を置きます。

41
ysth

R ..の答え から:

ただし、結果の型は配列型であるため、これはおそらく非常に悪い考えですが、そのユーザーはそれが配列型であることを認識しません。関数の引数として使用する場合、値ではなく参照によって渡され、そのためのsizeofは間違ったものになります。

配列であることが分からないユーザーは、おそらく次のようなものを書くでしょう(失敗します):

#include <stdio.h>

typedef int twoInts[2];

void print(twoInts *twoIntsPtr);
void intermediate (twoInts twoIntsAppearsByValue);

int main () {
    twoInts a;
    a[0] = 0;
    a[1] = 1;
    print(&a);
    intermediate(a);
    return 0;
}
void intermediate(twoInts b) {
    print(&b);
}

void print(twoInts *c){
    printf("%d\n%d\n", (*c)[0], (*c)[1]);
}

次の警告とともにコンパイルされます。

In function ‘intermediate’:
warning: passing argument 1 of ‘print’ from incompatible pointer type [enabled by default]
    print(&b);
     ^
note: expected ‘int (*)[2]’ but argument is of type ‘int **’
    void print(twoInts *twoIntsPtr);
         ^

そして、次の出力を生成します。

0
1
-453308976
32767
27
Gerhard Burger

Cの値では、配列を関数パラメーターとして渡すことはできません。

配列を構造体に入れることができます。

typedef struct type24 {
    char byte[3];
} type24;

値で渡しますが、もちろん、x.byte[0]の代わりにx[0]を使用するのはあまり便利ではありません。

関数type24_to_int32(char value[3])は、実際には値ではなくポインターによって渡されます。 type24_to_int32(char *value)とまったく同じであり、3は無視されます。

ポインタを渡すことに満足している場合は、could配列を使い続けてください:

type24_to_int32(const type24 *value);

これは、最初の要素へのポインタではなく、配列へのポインタを渡すため、次のように使用します。

(*value)[0]

あなたが誤ってvalue[1]を書いた場合、何か愚かなことが起こるので、私はそれが本当に利益であるかどうかわかりません。

11
Steve Jessop

配列型を関数の引数またはテンプレートパラメータとして適切に使用するには、typedefの代わりに構造体を作成し、その構造体にoperator[]を追加して、次のような機能のように配列を保持します。

typedef struct type24 {
  char& operator[](int i) { return byte[i]; }
  char byte[3];
} type24;

type24 x;
x[2] = 'r';
char c = x[2];
11
Geronimo