C89には、ユニオンを引数として直接初期化して渡すための実質的な手段はありません。 C89では、共用体は変数または変数参照のみを使用して宣言でき、その変数を使用して初期化する必要があります。しかし、ポインタを使用せずにこれらの変数を値渡しして返すことができます。
返される構造体と共用体は、通常のリターンパラメータのようにレジスタに収まる必要はありません。この場合、コンパイラはあなたのために(スタック上で)すべてを行い、深く最適化され、インライン化されている場合は、通常、オーバーヘッドはほとんどありません(読んでください:注意深く手に最適化されたCコードは高速ですが、よくやった)。
以下はコード例です。
ユーティリティ関数create_GAIN_REG_st
とGAIN_REG_st_to_G_u
を使用すると、関数の呼び出し時に引数リストのstruct/unionをオンザフライで作成できます。これは、これらをパラメータとして受け入れます。
これは、ポインターがどこかを指している必要があるため、これは非ポインタータイプの場合にのみ有効です。ポインタを使用する場合は、malloc
/free
が必要です。しかし、データ型全体を返すと、その必要はありません。 1つの重要なことは、オンザフライで作成されたデータへのポインタを得ることができますが、データはコール中にスタック内の変数として通常通りに存続することです - これはすぐに "フリー後に使用"使用スタック領域。もちろん
void
spi(G_u u)
{
if (u.GAIN_st.rdwr_u8)
{
/* implement rdwr_u8==1 here */
}
else
{
/* implement rdwr_u8==1 here */
}
}
int
main()
{
spi(GAIN_REG_st_to_G_u(create_GAIN_REG_st(1,19,255)));
return 0;
}
:(。だから、常に返されたり一時的な変数である引数として渡される構造体/共用体へのポインタを避ける)
#define __inline__ /*if not using GCC*/
typedef struct {
uint8_t rdwr_u8: 1;
uint8_t not_used_u8: 3;
uint8_t address_u8: 4;
uint8_t reserved_u8: 8;
uint8_t data_u8: 8;
uint8_t padding_u8: 8;
} GAIN_REG_st;
typedef union {
GAIN_REG_st GAIN_st;
uint32_t G_32;
} G_u;
GAIN_REG_st __inline__
create_GAIN_REG_st(uint8_t rdwr, uint8_t address, uint8_t data)
{
GAIN_REG_st g = { 0 };
g.rdwr_u8 = rdwr;
g.address_u8 = address;
g.data_u8 = data;
return g;
}
G_u __inline__
GAIN_REG_st_to_G_u(GAIN_REG_st g)
{
G_u u = { 0 };
u.GAIN_st = g;
return u;
}
今、あなたは直接あなたの関数spi
を呼び出すことができますあなたは二重のコール平らできます。
G_u __inline__
create_G_u_bits(uint8_t rdwr, uint8_t address, uint8_t data)
{
return GAIN_REG_st_to_G_u(create_GAIN_REG_st(rdwr, address, data));
}
int
main()
{
spi(create_G_u_bits(1,19,255));
return 0;
}
をしたり、特殊な機能を作成することができます。
を
void
spi_bits(uint8_t rdwr, uint8_t address, uint8_t data)
{
spi(GAIN_REG_st_to_G_u(create_GAIN_REG_st(rdwr, address, data)));
}
int
main()
{
spi_bits(1,19,255);
return 0;
}
ここに遭遇した問題を回避しようとしていますか?http://stackoverflow.com/questions/5675299/how-to-pass-a-bitfield-by-reference-to-a-function? 32ビットintを持つ構造体の和集合を持つ必要があることを示すシステムに関するいくつかの情報を見つけましたか? –
_ビットフィールドを使用してデータプロトコルをマッピングしないでください。アライメント、ビットオーダー、エンディアンは分かりません。規格で定義されているものもありません。また、コンパイラは任意の数のパディングバイトをビットフィールドに自由に追加することができます。次に、任意の数のパディングバイトを自由にユニオンに追加できます。適切な解決方法は、単純なuint32_tをビットマスクとビットワイズ演算子で使用することです。あなたのコードは決定論的で100%移植可能になります。今のように、特定のコンパイラ実装の詳細がわからない限り、そのビットチャンクをSPIに送信するときに何が起こるかは誰にも分かりません。 – Lundin