6

こんにちは、私は C を使用しています。ポインターの割り当てについて質問があります。

struct foo
{
   int _bar;
   char * _car[SOME_NUMBER]; // this is meant to be an array of char * so that it can hold pointers to names of cars
}

int foofunc (void * arg)
{
   int bar;
   char * car[SOME_NUMBER];

   struct foo * thing = (struct foo *) arg;

   bar = thing->_bar; // this works fine
   car = thing->_car; // this gives compiler errors of incompatible types in assignment
}

car と _car は同じ宣言を持っているのに、互換性のない型に関するエラーが発生するのはなぜですか? 私の推測では、それらがポインターであることと関係があると思います (それらは char * の配列へのポインターであるためですよね?) が、なぜそれが問題なのかわかりません。

char * car;代わりに宣言すると、char * car[MAXINT];正常にコンパイルされます。しかし、後でインデックスを使用して特定の情報にアクセスする必要があるときに、それがどのように役立つかわかりません。後でその情報にアクセスするのは非常に面倒です。実際、正しい方法で行っているかどうかさえわかりません。char * の配列を使用する代わりに、一連の文字列を格納するためのより良い方法があるかもしれません。

編集: INT_MAX (int の最大値) を使用するつもりはありませんでした。これは他の int であり、約 20 です。

4

4 に答える 4

5

car_carは両方とも配列であり、C で配列を割り当てることはできません (配列が構造体 (または共用体) に埋め込まれていて、構造体の割り当てを行う場合を除く)。

これらは、char の配列へのポインターではなく、char へのポインターの配列でもあります。あなたがコードに書いたものはおそらくあなたが望むものです.MAXINT名までのポインタを配列に格納することができます. ただし、タイプを正しく記述する必要があります - char または char ポインターへのポインターの配列として。

文字の配列へのポインターは次のようになります。

char (*car)[MAXINT];

文字ポインターの配列へのポイント (ありがとう、ブライアン) は次のようになります。

char *(*car)[MAXINT];

MAXINT には注意してください。これは非常に大きな配列になる可能性があります (Linux では、少なくとも 2 31 -1である として<values.h>定義MAXINTされます)。INT_MAX


コードは次のようになります。

struct foo
{
   int _bar;
   char * _car[MAXINT];
}

int foofunc (void * arg)
{
   int bar;
   char * car[MAXINT];
   struct foo thing = (struct foo *) arg;
   bar = arg->_bar; // this works fine
   car = arg->_car; // this gives compiler errors of incompatible types in assignment
}

bar と car への代入はまったくコンパイルされるべきではありません -argvoid *. おそらくthing、何らかの形で使用するつもりだったのでしょう。ブライアンが指摘したように、そこにも問題があります。

次のいずれかが必要です。

int foofunc(void *arg)
{
    int bar;
    char *car[MAXINT];
    struct foo thing = *(struct foo *)arg;
    bar = thing._bar; // this works fine
    car = thing._car; // this is still an array assignment
    ...other code using bar and car...
}

またはあなたがしたい:

int foofunc(void *arg)
{
    int bar;
    char *car[MAXINT];
    struct foo *thing = (struct foo *) arg;
    bar = thing->_bar; // this works fine
    car = thing->_car; // this is still an array assignment
    ...other code using bar and car...
}

または、確かに:

int foofunc(void *arg)
{
    struct foo *thing = (struct foo *) arg;
    int bar           = thing->_bar; // this works fine
    char *car[MAXINT] = thing->_car; // this is still an array assignment
    ...other code using bar and car...
}

最後に、配列の割り当てを扱います。C では、memmove()これを行うために合理的に使用できます。

int foofunc(void *arg)
{
    struct foo *thing = (struct foo *) arg;
    int bar           = thing->_bar; // this works fine
    char *car[MAXINT];
    memmove(car, thing->_car, sizeof(car));
    ...other code using bar and car...
}

同様の関数memcpy()は、コピーされる領域が重なっている場合、信頼できるセマンティクスを持っていませんが、memmove()そうです。memmove()常に正しく機能するため、常に使用する方が簡単です。memmove()C++ では、 (または) の使用に注意する必要がありますmemcpy()。このコードでは十分に安全ですが、その理由を理解するのは簡単ではありません。

ここではポインターをコピーしているだけであることに注意する必要があります。ポインターが指す文字列をコピーしているわけではありません。他の何かがこれらの文字列を変更するcarと、呼び出し元のコードの変数と経由で表示される値の両方に影響します。

最後のポイント - 今のところ: 関数の引数が ? として必要void *ですか? struct foo *関数が代わりに ' ' (または ' ')を取るように宣言されている場合、コードをあらゆる種類の悪用にさらす可能性がありますconst struct foo *

于 2010-04-05T02:08:20.653 に答える
3

サイズMAXINTの新しい配列を作成しています。MAXINTサイズの配列へのポインタを作成したいと思います。

char *の配列へのポインタの作成:

以下は、MAXINTからchar*要素までのサイズの配列です。

char * car[MAXINT]; 

以下はへのポインタです:char*要素へのサイズMAXINTの配列:

char* (*car)[MAXINT];

ポインタを次のように設定する方法は次のとおりです。サイズMAXINTからchar*要素への配列:

char* (*car)[MAXINT];
car = &arg->_car;

質問の他の構文エラー:

  • 構造体定義の後にセミコロンを付ける必要があります。
  • foo*notを使用する必要がありfooます。したがって、次のようになります。
    struct foo* thing = (struct foo *) arg;
  • 使用しthingないでargください:
    bar = thing->_bar;
    car = thing->_car;
于 2010-04-05T02:10:50.237 に答える
2

自分が行っている方法で配列に割り当てることはできません。要素ごとのコピーを行うことができます。

for(int i = 0; i < MAXINT; i++)
{
  car[i] = (arg->_car)[i]
}

文字列が一定でない場合は、を使用する必要がある場合があることに注意してくださいstrcpy

于 2010-04-05T02:08:50.253 に答える
0

C の配列表記は、紛らわしいものです。あなたのコードは、あなたが思っていることを意味していません。

arg->_car「配列のアドレス」を意味します_car。同様に、car「配列のアドレス」を意味しますcar。_car の内容を car にコピーしようとしている場合は、次のようになります。

memcpy(car, _car, MAXINT);

しかし、あなたの本当の質問は、「文字列のリストを保存する最良の方法は何ですか?」だと思います。この答えは: 動的リスト (項目を追加すると自動的に拡大するリスト) です。

次のように宣言します。

#define CARSIZE 65
int numCars = 0;
char **car; /* a list of addresses, each one will point to a string */

車を追加するには:

char *newCar = malloc(CARSIZE); /* make room */
strncpy(newCar, "Mercedes", CARSIZE); /* newCar has the address of the string */
car[numCars++] = newCar; /* store it */

車を一覧表示するには:

int n;
for (n = 0; n < numCars; ++n)
    printf("%s\n", car[n]);

位置 n で車を削除するには:

free(car[n]); /* release the memory */
/* condense the list of pointers */
for ( ; n < numCars - 1; ++n)
    car[n] = car[n+1];

これは C では完全に日常的なものです。注:上記は私の頭から離れたものであり、動作中のプログラムからコピーしたものではないため、すべての * が正しい場所にあるとは約束できません。これは宿題だと思うので、全部あげたくないのですが...

于 2010-04-05T02:44:20.460 に答える