10

unsigned charポインターの用途は何ですか? ポインターがポインターに型キャストされていることを多くの場所で見てきましたunsinged char。なぜそうするのですか?

へのポインタを受け取り、intそれを に型キャストしunsigned char*ます。しかし、cout を使用してその配列の要素を出力しようとすると、何も出力されません。なぜ?理解できません。私はc ++が初めてです。

以下のサンプルコードを編集

int Stash::add(void* element)
{
    if(next >= quantity)
    // Enough space left?
        inflate(increment);

    // Copy element into storage, starting at next empty space:
    int startBytes = next * size; 
    unsigned char* e = (unsigned char*)element;
    for(int i = 0; i < size; i++)
        storage[startBytes + i] = e[i];
    next++;
    return(next - 1); // Index number
}
4

4 に答える 4

10

あなたは実際にポインタ演算を探しています:

unsigned char* bytes = (unsigned char*)ptr;
for(int i = 0; i < size; i++)
    // work with bytes[i]

この例でbytes[i]は、 は と等しく*(bytes + i)、アドレス: のメモリにアクセスするために使用されますbytes + (i* sizeof(*bytes))。言い換えれば: を持っていてint* intPtrにアクセスしようとするとintPtr[1]、実際にはバイト 4 から 7 に格納されている整数にアクセスしています。

0  1  2  3
4  5  6  7 <-- 

ポインターが指す型のサイズは、インクリメント/デクリメント後のポインターの指す場所に影響します。したがって、データをバイトごとに反復処理する場合は、サイズが 1 バイトの型へのポインターが必要です (これが理由unsigned char*です)。


unsigned char0通常、有効な値であり、データの一部であるバイナリデータを保持するために使用されます。「裸」で作業している間、unsigned char*おそらくバッファの長さを保持する必要があります。

char通常、文字列を表す文字を保持するために使用され、(終了文字)0と等しくなります。'\0'文字のバッファが常に で終了する場合'\0'、終端文字はデータの終わりを正確に指定するため、その長さを知る必要はありません。

どちらの場合も、データの内部表現を隠し、メモリ管理を処理するオブジェクトを使用する方がよいことに注意してください ( RAII idiomを参照)。したがって、std::vector<unsigned char>(バイナリ データの場合) またはstd::string(文字列の場合) のいずれかを使用することをお勧めします。

于 2013-02-08T10:04:59.440 に答える
8

C では、unsigned charトラップ値がないことが保証されている唯一の型であり、コピーによって正確なビット単位のイメージが得られることが保証されています。(C++ はこの保証をcharにも拡張します。) このため、これは伝統的に「生のメモリ」に使用されます (たとえば、 のセマンティクスは のmemcpy観点から定義されますunsigned char)。

さらに、ビット演算 ( 、&など) を使用する場合は、一般に符号なし整数型が使用されます。 最小の符号なし整数型であり、ビット演算が使用される小さな値の配列を操作するときに使用できます。場合によっては、オーバーフローの場合にモジュロ動作が必要になるためにも使用されますが、これはより大きな型 (ハッシュ値の計算など) でより頻繁に使用されます。これらの理由は両方とも、一般に unsigned 型に当てはまります。通常、メモリ使用量を減らす必要がある場合にのみ使用されます。|>>unsigned charunsigned char

于 2013-02-08T10:06:25.760 に答える
2

このunsinged char型は通常、単一byteのバイナリ データの表現として使用されます。したがって、配列は、各要素が 1 バイトであるバイナリ データ バッファーとしてよく使用されます。

コンストラクトは、バイナリ データ バッファー (またはその最初の要素) へのunsigned char*ポインターになります。

8ビットに固定されているかどうかにかかわらず、c++のサイズについて標準が正確に何を言っているのか100%確信が持てません。通常はそうです。探して投稿してみます。unsigned char

あなたのコードを見た後

のようなものvoid* inputを関数のパラメーターとして使用すると、入力の元の型に関する情報が意図的に取り除かれます。これは、入力が非常に一般的な方法で処理されることを強く示唆しています。つまり、任意のバイト文字列として。int* input一方、それは符号付き整数の「文字列」として扱われることを示唆しています。

void*その内容について結論を出すことができないため、何らかの理由で入力がエンコードされたり、処理bit/賢明になったりする場合に主に使用されます。byte

次に、関数では、入力をバイトの文字列として扱いたいようです。ただし、オブジェクトを操作するには、たとえばoperator=(代入) を実行するために、コンパイラは何をすべきかを知る必要があります。入力をvoid*代入として宣言するので、型*input = somethingであるため意味がありません。要素を「最小の生メモリの断片」として扱うようにコンパイラを作成するには、要素を適切な型にキャストします。*inputvoidinputunsigned int

間違った、または意図しない型変換が原因で、coutおそらく機能しませんでした。char*ヌルで終了する文字列と見なされ、混乱singedしやすく、コードでunsignedバージョン化されます。に を渡すunsinged char*と、入力は通常の ASCII 文字としてostream::operator<<扱われchar*、期待されます。メモリの内容を出力したいときは、ポインタを明示的にキャストするのが最善です。byte00

また、バッファのメモリ内容を出力するには、ループを使用する必要があることに注意してください。

于 2013-02-08T10:05:39.817 に答える
0

unsigned charポインターは、データにバイト単位でアクセスする場合に役立ちます。たとえば、ある領域から別の領域にデータをコピーする関数では、次のことが必要になる可能性があります。

void memcpy (unsigned char* dest, unsigned char* source, unsigned count)
{
    for (unsigned i = 0; i < count; i++)
        dest[i] = source[i];
}

また、バイトがメモリのアドレス可能な最小単位であるという事実とも関係があります。メモリから1バイトよりも小さいものを読み取りたい場合は、その情報を含むバイトを取得してから、ビット演算を使用して情報を選択する必要があります。

ポインタを使用して上記の関数のデータをコピーすることもできますがint、4バイトのチャンクがコピーされるため、状況によっては正しく動作しない場合があります。

を使おうとすると画面に何も表示されないのcoutは、データがゼロ文字で始まっていることが原因である可能性があります。これは、C++では文字列の終わりを示します。

于 2013-02-08T10:06:40.240 に答える