4

関数

関数 uint32_t htonl(uint32_t hostlong) を使用して、uint32_t をネットワーク バイト オーダーに変換しています。

私がしたいこと

変数をネットワーク バイト オーダーに変換した後、変数を使用して計算を行う必要があります。

//Usually I do calculate with much more variables and copy them into a much
// larger buff - to keep it understandable and simple I broke it down 
// to one calculation

uint32_t var = 1;
void* buff;

buff = malloc(sizeof(uint32_t));

while(var < 5) {
    var = htonl(var);
    memcpy(buff, &var, sizeof(uint32_t));
    doSomethingWithBuff(buff);
    var++; // FAIL
}

私にできることは、しかし...

実際、私はすでにこの問題の解決策を見つけました:

uint32_t var = 1, nbo;
void* buff;

buff = malloc(sizeof(uint32_t));

while(var < 5) {
    nbo = htonl(var);
    memcpy(buff, &nbo, sizeof(uint32_t));
    doSomethingWithBuff(buff);
    var++;
}

問題は、nbo が単にバッファーとして使用されるため、このソリューションでメモリを浪費することです。

私がやりたいこと

memcpy() 関数内で htonl() 関数を使用できれば完璧です。memcpy() は、2 番目の値を void* にする必要があります。私の質問は: htonl() の戻り値のアドレスを取得するにはどうすればよいですか?

uint32_t var = 1;
void* buff;

buff = malloc(sizeof(uint32_t));

while(var < 5) {
    memcpy(buff, (GET ADDRESS)htonl(var), sizeof(uint32_t));
    doSomethingWithBuff(buff);
    var++;
}

そして、「この変数のアドレスがない」ためにそれが不可能な場合: 変数へのポインターではなく変数を返す関数はどのように機能しますか?

4

3 に答える 3

2

変数バッファーが 1 つだけの場合の説明


間違ったマイクロ最適化を行っていると思います。

Uchia Itachiが指摘するように、戻り値のアドレスを取得するのはバグです。

実際、効率を重視する場合、ボトルネックは静的ストレージです。malloc() にはメモリ オーバーヘッドがあります。静的メモリに格納するデータに加えて、メタデータが書き込まれます。たとえば、ここ ([実装の詳細] まで下にスクロール) では、巧妙な最小アルゴリズムのオーバーヘッドが割り当てごとに size_t だけであることが説明されています。そして、これは断片化さえ考慮していません。

memcpy() は高速な関数ですが、単一の数値ではやり過ぎです。

したがって、スタックのみを使用することをお勧めします。buff をグローバル整数変数にします。次に、バッファーを必要とするそれらにバッファーのアドレスを渡します。彼らは違いに気付かないでしょう。

変更された質問についてのディスカッション - ループ内で大量の書き込みと読み取りを行う大きなバッファー


関数が (何かを) 返すと、その値 (またはオブジェクトへのポインター) をレジスターまたはスタックにプッシュします。一方、変数が宣言、初期化、および使用されると、変数はレジスタまたはスタックに常駐します。

類似性に気づきましたか?最適化コンパイラは不要な変数を削除し、内部で使用する名前のない変数も作成します。たとえば、変数がこのスコープで参照されなくなったことを検出すると、変数のストレージが再利用されます。

したがって、単純で読みやすいコードを書くように努め、詳細はコンパイラーに任せるべきです。あなたの2番目の例は完全に問題ないことを意味します。

于 2013-08-17T09:35:25.020 に答える
0

関数の戻り値がどこに置かれるかはわかりません。値がスタックに返される場合もあれば、レジスタにある場合もあります。C では、何かを返すこととポインターを返すことの間に実際の違いはありません。しかし、別の関数でのみ定義され、アクセス可能なローカル変数をいじらないことをお勧めします。これを行うと、セグ フォールトの可能性が高くなります。また、&nbo の使用はメモリの無駄ではありません。

于 2013-08-17T09:36:00.993 に答える