2016-03-26 14 views
-1

配列を持つ既存の構造体へのポインタを返そうとすると、互換性のない型エラーが発生します。ここで既存の構造体の配列から構造体へのポインタを検索して返します

は、関連する構造の定義です:

typedef struct cust_t* Customer; 
typedef struct item_t* Item; 

struct item_t { 
    int id; 
    char *label; 
}; 


struct cust_t { 
    int id; 
    int basket_size; 
    Item basket; 
}; 

あなたが見ることができるように、構造体は、アイテムのバスケットを持っている顧客を定義します。だからbasketItemの配列です。

は、私はその後、以下の2つの機能を持っている:

/* 
Add data to the item with id item_id in the basket of cust 
*/ 
void add_item_data(Customer cust, int item_id, void* data) { 
    Item *v; 
    v = find_item(cust, item_id); 

    //Use the pointer to the item, v, and attribute data to it (unimplemented) 
} 

/* 
Find the item with id id in the basket of cust, and return a pointer to it. 

Assumes that the id of all items have been previously defined. 
*/ 
Item *find_item(Customer cust, int id){ 

    Item *v; 

    //Iterate over the length of basket looking for a match in the id's... 
    for (int i = 0; i < cust->basket_size; i++){ 
     if (cust->basket[i].id == id){ 
      v = cust->basket[i]; 
      return v; 
     } 
    } 
    //if the item is not in the basket, return null. program should not reach here 
    return NULL; 
} 

あなたは第二の機能は、バスケットは、すでに自分のIDがすでに設定されていた、すでにそこにあるアイテムの数を持っていることを前提として見ることができます。 void* dataには、labelなどの情報が含まれます。

私の問題は、私はそれがそうadd_item_dataはそれを使用することができ、basketに既存のItem構造体へのポインタを返すようにしたい、find_item機能です。

私はコンパイルするとき、私は次のエラーを取得する:

error: incompatible types when assigning to type 'struct item_t **' from type 'struct item_t' 
v = cust->basket[i]; 

私は私のポインタの構文を推測しているが、どこかオフになっているが、私は場所を確認することはできません。

+0

Emisorは実際の問題点を強調しています。私はスキミングする時間がありますが、あなたはこれを奇妙な方法でやったと思います。ポインタを持たない構造体をtypedefし、cust_tにItemを保持させる* - ポインタを隠すためにtypedefを使用しない - これらのtypedefに名前をつけた場合CustomerPtrとItemPtr - それを実現する –

+1

ポインタを 'typedef'しないでください。それは意味論を難読化し、最終的には混乱を招く。 – Olaf

答えて

1

ポインタからitem_t構造体としてtypedef'd Itemがあります。 Customerのtypedefにも同様の状況があります。これは意味的には厄介です。 Item *は、Itemの配列、特に配列内の最初のItemのアドレスへのポインタとして、よりよく解釈されます。その配列とポインタの考え方に慣れていない場合は、ここではスターター(C++ではコンセプトは同じですが、C++固有の唯一の部分はstd::cout <<をコンソールに出力することです):http://www.learncpp.com/cpp-tutorial/6-8-pointers-and-arrays/これと次のもの、特に[]演算子の部分)

あなたの関数find_itemはItemへのポインタを返します。 Itemはitem_tへのポインタなので、最終的にitem_t **の型になります。 item_tへのポインタへのポインタ。

vは、上記のようにitem_t **です。 custはcust_t *です。 ifステートメントでは、実際にリンク内のコンセプトを正しく使用しています。cust->basket[i].id

basketはitem_tを指しています。 []演算子を使用して、ポインタをiだけオフセットしてから、THATポインタを逆参照します。つまり、basket[i]

と同じです。つまり、ポインタではなく実際のitem_tを取得します。それからすぐ下にあなたはそのコンセプトを誤って適用します。 basket[i]は実際のitem_tを返し、item_t **に割り当てようとしています(したがって、あなたのエラーです)。キャストが助けにならない、それはあなたの問題ではない。あなたはリンゴをチーズのブロックに変えようとしています。

まず、先頭から始めて、typedef内のポインタを隠さないことをお勧めします。それはこのことを読むのを混乱させます。あなたの言葉に基づいて、"私はそれが既に存在するItem構造体へのポインタを返すようにしたい"あなたはあなたがしたことを誤解したと思います。アイテム構造体へのポインタを返さず、ポインタをアイテム構造体へのポインタに返します。

とにかく、何らかの理由で型定義を変更することはできないと言います。だから、おそらくあなたが少なくとも働いていると思いますが(実際にあなたが思っていることはわかりませんが)、ただ項目の機能、そしてあなたは、Vへの配列の撤退何のアドレスを割り当て、このように:。(検証、うまくいけば、あなたがポイントを取得できません)

Item find_item(Customer cust, int id){ 

    Item v; 
    //snip snip 
      v = &(cust->basket[i]); //using & as address-of operator here 
      return v; 
    //snip snip 

編集:あなたのコメントを見て、私はあなたは "アドレスの"演算子に慣れていないかもしれないと思う。それはあなたが存在するものへのポインタを得る方法です。 cust->basket[i]はitem_tで、&はitem_tのアドレスを取得します。このアドレスはitem_tポインターに割り当てることができます。これはItemとしてtypedefされています。

1

vは、Item*の変数であり、item_t**です。

cust->basketitem_t*、したがって、任意のcust->basket[i]あるタイプItem、である今、あなたがこれを行うにしようとしているitem_t

です:私はエラーが見ることが明確であると考えてい

v = cust->basket[i];

既に:あなたのエラーメッセージが指摘するように、タイプitem_tの値をitem_t**変数に代入しようとしています。

typedefを使用してそのようなポインタをマスクしないようにしてください。そうすれば、変数がポインタであるかどうかを一目で把握できます。

+0

これは 'v 'を'(item_t **)'などにキャストする必要があるのでしょうか? – JavascriptLoser

+0

'v'は既に' item_t ** 'です。代わりに 'basket'は' Item'自体ではなく 'Item'の配列でなければならないので、おそらく' cust_t'宣言を変更したいと思っています。 – Dleep

+0

また、 'v'と' find_item'の戻り値は 'Item'ではなく' Item'でなければなりません。少なくとも、それを行うとコンパイルされるでしょうが、それが本来意図していたものなのかどうかはわかりません。 – Dleep

関連する問題