2011-06-22 10 views
2

私は任意のバッファをバイナリ表現の文字列に変換しようとしています。私はここからいくつかのコードを見ていた:http://snippets.dzone.com/posts/show/2076を開始するには。私はこのコードは任意のバッファを変換することはできませんが、intの特定の場合のみ変換することを認識しています。しかし、私は一度それが働いていればどのケースにも適応できると考えました。バッファをC++のバイナリ文字列に変換するにはどうすればよいですか?

問題は、それが(このように:왿」)いくつかの奇妙なシンボルを返すことである。代わりに、バイナリのいずれかのどちらかが、特にこのコードで間違っているものを知っているか、任意のバッファを変換する方法について説明してい

?私は、C++に新しいですのでご注意ください。

#include <stdio.h> 
#include <stdlib.h> 
#include <memory.h> 
#include <string.h> 

char *getBufferAsBinaryString(void *in) 
{ 
    int pos=0; 
    char result; 
    char bitstring[256]; 
    memset(bitstring, 0, 256); 
    unsigned int *input= (unsigned int *)in; 
    for(int i=31;i>=0;i--) 
    { 
      if (((*input >> i) & 1)) result = '1'; 
      else result = '0'; 
      bitstring[pos] = result; 
      if ((i>0) && ((i)%4)==0) 
      { 
        pos++; 
        bitstring[pos] = ' '; 
      } 
      pos++; 
    } 
    return bitstring; 
} 
int main(int argc, char* argv[]) 
{ 
    int i=53003; 
    char buffer[1024]; 
    char *s=getBufferAsBinaryString(&i); 
    strcpy(buffer, s); 
    printf("%s\n", buffer); 
} 
+3

戻り、スタック割り当てバッファへのポインタを使用しているため、このプログラムの動作は未定義です。あなたはコンピュータが魔法のようにワトログに変身していないことを喜んで喜ぶべきです。これはC++ではなくCでもあります。 –

+0

とりわけ、 'getBufferAsBinaryString'は、ローカルへのポインタを返すので、未定義の動作をします。 –

+0

バッファ 'char buf [N];があれば' std :: string s(buf、buf + N); 'で文字列を作ることができます。 –

答えて

2

配列のビットストリングには、自動継続時間と呼ばれるものがあります。これは、関数が呼び出されたときに存在し、関数が復帰すると消滅することを意味します。

したがって、getBufferAsBinaryStringのこのバージョンが返すポインタは、呼び出し元がポインタを受け取るまでに存在しない配列になります。 (でbitstring;の最初の文字へのポインタを返すreturn bitstring;声明「配列とポインタの等価性は、」この文脈で配列bitstringの言及は&bitstring[0]と同等であることを覚えておいてください。)

を呼び出し側が使用しようとするとポインタ、getBufferAsBinaryStringによって作成された文字列がまだ存在するか、メモリが他の機能によって再利用されている可能性があります。したがって、getBufferAsBinaryStringのこのバージョンは十分ではなく、受け入れられません。関数はローカルへのポインタ、自動継続時間配列を返してはなりません。ローカル配列へのポインタを返すの問題は、アレイは、デフォルトで自動継続時間を有することがあるので

getBufferAsBinaryStringの上記非機能バージョンへの最も簡単な修正ではなく、静的な配列を宣言することである。

char *getBufferAsBinaryString(void *in) 
{ 
    int pos=0; 
    char result; 
    static char bitstring[256]; 
    memset(bitstring, 0, 256); 
    unsigned int *input= (unsigned int *)in; 
    for(int i=31;i>=0;i--) 
    { 
      if (((*input >> i) & 1)) result = '1'; 
      else result = '0'; 
      bitstring[pos] = result; 
      if ((i>0) && ((i)%4)==0) 
      { 
        pos++; 
        bitstring[pos] = ' '; 
      } 
      pos++; 
    } 
    return bitstring; 
} 

が返されたときにbitstring配列が消えないため、呼び出し元がそれを使用するまでにポインタは有効です。

静的配列へのポインタを返すことは、配列を "返す"問題に対する実践的かつ一般的な解決策ですが、欠点が1つあります。関数を呼び出すたびに、同じ配列を再利用して同じポインタを返します。したがって、関数をもう一度呼び出すと、最後に返された情報が上書きされます。 (より正確には、関数がポインタを返す情報は上書きされます)

staticリターン配列のテクニックは機能しますが、呼び出し元は少し注意する必要があり、リターンポインタ1つの呼び出しから関数への後の呼び出しの後に使用可能な関数への呼び出し

しかし、私はカバーしていなかったvoid *を渡すことにまだ異なる問題があります。配列が\0で終わると仮定してはいけないので、バッファのサイズも渡す必要があります。

+0

バッファのサイズをどのように渡しますか? int size =(sizeof(* input))* 8;作業? –

+0

@放浪:あなたはそれを追跡する必要があります。 sizeof()の使用は保証されません。 –

0

あなたが関数からローカルに割り当てられた配列を返すことができません。とすぐに機能が終了すると、配列が存在しなくなったので、あなたがきたポインタ戻り値は有効なオブジェクトを指していません。

ビットストリングを表現するのにchar配列を使用する代わりに、効率的な値のセマンティクスを持つstd::stringを使用することを検討する必要があります(効率的な点を除いて、それを心配することなくコピーできます。 )。

+0

静的であれば可能です:)デフォルトでは、ローカルに割り当てられた配列は自動継続時間を持ちます。 –

1

メモリと安全性に関するその他の問題を無視しても、有効なヌル終了文字列は返されません。また、入力バッファのサイズを渡すこともないので、入力バッファの最初の32ビットの32ビットビット表現をプリントアウトするだけです。

charバッファを渡して、単にstd::stringに書き込むことに加えて、入力バッファのサイズを渡して、それをループする必要があります。

関連する問題