2016-06-14 12 views
-1

のは、私は構造体と、次のような機能を持っているとしましょう:ヘッダファイル内(Cで)構造体の配列を逆参照

構造体:

typedef struct { 
uint8_t length; 
uint8_t data[8]; 
} simple_vector; 

機能:どのように

simple_vector* SD_cmd(uint8_t cmd, uint32_t arg, uint8_t crc, uint8_t read_cnt){ 

simple_vector vector; 

//stuff happens and the simple_vector is manipulated 

return &vector; 
} 

- >演算子を使用して配列の非ゼロ要素にアクセスする方法はありますか?

simple_vector *response; 
response = SD_cmd(8, 0x000001AA, 0x87, 5); 
uint8_t value = response->data[3]; 

上記のスニペットの最後の行が正しい値を返さない:

はの関数は、この構造体へのポインタを返すとしましょう。私は(mcu上で)デバッグし、関数内のデータ[3]が関数の外で逆参照するときのものと同じでないことを確認しました。何かご意見は?

+0

構文は正しいです。 「働かない」とはどういう意味ですか? –

+1

コンパイルされないスニペットの最初の行です。最後の行は問題ありません。決定的な回答を得るには、[最小完全な検証可能な例](http://stackoverflow.com/help/mcve)を投稿する必要があります。 – user3386109

+0

@ user3386109:残りのコードを追加する必要があります。最初の行は有効な構文はそのままです。 [ask]を見て、[mcve]を提供してください! – Olaf

答えて

0

ローカル変数のアドレスを返します。コントロールが変数定義(この場合は関数)を含むブロックを離れると、変数は破棄され、無効なポインタが残されます。

コードには未定義の動作があります。

また、コンパイラでこの場合の警告オプションがあるかどうかを確認する必要があります。例えば。 gccは-Wreturn-local-addrです(これはデフォルトで有効になっていると思います)。この状況について警告します。


この問題を解決するには、関数に構造体へのポインタを渡して結果を書き込ませることができます。これにより、構造体に関連付けられたメモリを管理するのは呼び出し元の責任になります。

structを返すこともできます。これは呼び出し元にコピーします(これはおそらくソリューション#1のようなものにコンパイルされます)。構造体を返す関数は通常、隠しポインタの引数をとることで実装されます) 。

またはmalloc構造体を動的に使用できます。その後、エラー(NULLの返品はmalloc)を確認する必要があり、返されたポインタfreeへの発信者の責任になります。

最後に、関数は何も返しません(void)、代わりにグローバル変数を使用して値を呼び出し元に返信することができます。これは通常、グローバル変数がプログラムロジックを理解しにくい(バグを見つけにくい)ことがあるため、お勧めできません。

+0

必ずしもそうであるとは限りません。彼は自分の関数の中で 'malloc'を呼び出して、新たに割り当てられた'構造体 'へのポインタを返すことができます。 – mw215

+0

@ mw215彼はできましたが、彼はできませんでした。質問のコードを見てください。 – melpomene

+0

あなたは正しいです...彼は、実際にはしませんでした! – mw215

0

- >演算子を使用して配列のゼロ以外の要素にアクセスするにはどうすればよいですか?

最初に変数にアクセスできるようにすることで可能です。 8要素の配列の中の "nonzeroth"と "tenth"要素がタイプミスであると仮定すると、呼び出し元関数からアクセスできるである有効メモリへのポインタを正しく作成して管理するのは簡単です。 1つの明らかな可能性は、を動的ににすることです。ここでは簡単なデモの修正はあなたのコードに基づいて、次のとおりです。

#include <stdlib.h> 
#include <stdint.h> 
#include <stdio.h> 

typedef struct { 
    uint8_t length; 
    uint8_t data[8]; 
} simple_vector; 

simple_vector* SD_cmd(uint8_t cmd, uint32_t arg, uint8_t crc, uint8_t read_cnt) 
{ 
    simple_vector *vector = malloc(sizeof(simple_vector)); // pointer to malloc'd memory 
    //stuff happens and the simple_vector is manipulated 
    vector->data[3] = 42; 
    return vector; //return the pointer 
} 

int main() 
{ 
    if((simple_vector *response = SD_cmd(8, 0x000001AA, 0x87, 5)) == NULL){ 
     printf("Memory allocation error\n"); 
     return(1); 
    } 
    uint8_t value = response->data[3]; //the "last" line in question 
    printf("%hhu\n", value); 
    free(response);  //free the memory once you don't need it ! 
    return 0; 
} 

上記のスニペットの最後の行が正しい値を返さない

> ./test 
    42 

どのようにエレガントで慣用的に注意してくださいこのような手順はCです。