2017-07-13 11 views
0

私はこのように、デバイスからの32ビット値のバイナリ配列を受け取り、vsprintfのでそれらを印刷コードを有する:変数のリストを移植性の高い方法でvprintfに渡すには?

void print_stuff(int32_t *p, const char *format) 
{ 
    vprintf(format, (va_list)p); 
} 

(これは単純化され、値がフォーマットと一致することを保証だ、等)

これは、通常、x86 x86ではva_listが単なるポインタ(または配列)であることに依存しています。これは警告なしでコンパイルします。

これをARM(arm-linux-gnueabihf)とx64に移植する必要があります。コンパイルもしません。 ARMのGCC 4-somethingは「エラー:非スカラー型への変換要求」

バイナリ配列から移植可能な方法でva_listを作る方法は?または、少なくとも32ビットと64ビットのアーチを別々にすることは可能ですか? "ネイティブ・コール・インタフェース"ライブラリなしで可能ですか? これが不可能な場合は、このタスクに適した他の標準またはGNUライブラリ関数がありますか?これを呼び出すコードの

例:

#include <stdio.h> 
#include <stdarg.h> 
#include <stdint.h> 
#ifndef __GNUC__ 
#error Only Linux, other platforms/compilers not needed 
#endif 

int main() { 
uint32_t data[10]; 
int i; 
const char *fmt = "%x %x %x %x\n"; 
// Simulation of reading the data 
for(i = 0; i < 10, i++) data[i] = 0x100 + i; 
print_stuff(data, fmt); 
return 0; 
} 
+4

なぜあなたも、あなたが明確に行うことになっていない何かをしますか?誰がこのコードを最初に書きましたか?その人は非常に厳しい言葉に値する! –

+0

親愛なる人なので、実際には締め切りなどがあります。そして、これを正しくコーディングする方法を正確に尋ねています。 – ddbug

+4

締め切り?私はあなたがミスを間違えたと思います。あなたがとても賢いと思って、すべてが分かったと思うときは、ティーンエイジャーとしてこれを行うのは楽しいことです。その後、最初の移植性の問題にぶつかり、賢明にならなくなります。 – Art

答えて

3

答えに近似に顕著なコメントを転送します。

ジョブを正しく実行するには、呼び出しコードを確認して改訂する必要があります。または、あなたは​​へのあなたの簡単な呼び出しをあきらめて、もっと大変な作業をします。

印刷機能に配列を渡す場合は、を渡すことはありません。すべての実装で動作しない特定の実装では、何らかの作業が行われます。あなたが探しているのは、現在のシステムがニッチな生息環境で働いていたことですが、今はニッチから移動する必要があります。それ以上は機能しません。 「未定義の行動」の世界へようこそ。定義されていない動作を使用するコードは動作する必要はありません。どちらも失敗する必要はありません。

あなたの改訂された質問でも、それを行う(ポータブル)方法はありません。期間。配列にはいくつのエントリがありますか?書式文字列はどのように見えますか?印刷するアイテムの数は固定されていますか?ポータブルかつ信頼性の高いです

int n_fields = count_fields(format); 
switch (n_fields) 
{ 
case 1: printf(format, p[0]); break; 
case 2: printf(format, p[0], p[1]); break; 
… 
} 

:基本的に、あなたはに低減することができます。配列内のアイテムの数が固定されている(コードでは4つのエントリが使用されていると表示されます)場合は、もちろんカウントやスイッチを行う必要はありません。

libffiを参照することがあります。それはあなたを助けることができるかもしれません。

+0

ありがとう、このソリューションは私のために動作します。パラメータの数は可変である(簡略化のために図示せず)。私のシステムでは制限されているスタック上のパラメータをプッシュする必要がありますが、少数のパラメータでうまくいくでしょう。 - dd – ddbug

4

フォーマットは事前定義されているので、渡すパラメータの数は正確です。したがって、配列を渡す代わりに必要なパラメータを関数に渡します。次に、パラメータとして...を使用するように関数を変更し、va_listを取得します。

だからあなたの関数は次のようになります。

void print_stuff(const char *format, ...) 
{ 
    va_list args; 

    va_start(args, format); 
    vprintf(format, args); 
    va_end(args); 
} 

そして、あなたはこのようにそれを呼び出します。

const char *fmt = "%x %x %x %x\n"; 
... 
print_stuff(fmt, data[0], data[1], data[2], data[3]); 
+0

この解決策は、コメントの前にJonathan Lefflerによって与えられました。私は答えとしてマークします。ありがとう! - dd – ddbug

関連する問題