0

質問は以前から尋​​ねられていましたが、最善の方法についてはまだ少し迷っています。整数があり、構造体のメンバーとして使用する char* を取得したいと考えています。

同様の質問は、たとえば hereまたはhereです。stringstream や lexical_cast は使いたくありません。私が見る限り、基本的にはitoa、sprintf、snprintfを残しています。

私の問題の一部は、char ポインターがどのように機能するのかよくわからないことだと思います。

  1. をリクエストするchar str[12]と、12 文字が予約されますか?
  2. メモリが割り当てられたと思いますか?
  3. では、ヌル終了はどのように機能するのでしょうか?
  4. それは 12 文字の最後ですか (スペースが埋め込まれていますか?)、または数字が 2 文字しか使用されていない場合、2 文字の後に発生しますか?
  5. バッファサイズは重要ですか、それとも最大値(32ビットの場合は30程度)を使用する必要がありますか?
  6. また、単純な構造体で後でポインターを使用すると、メモリは自動的にクリアされますか、それともデストラクタが必要ですか?
  7. デストラクタは初期化バッファ サイズを知る必要がありますか?
  8. 実際の数値からバッファ長を計算しようとする人がいないのはなぜですか?
  9. snprintf は itoa よりも推奨されますか?

ありがとう

4

2 に答える 2

2

char str [12]を要求した場合、12文字が予約されますか?

はい、これはスタックに12文字(バイト)を予約します。

その後、メモリが割り当てられたと思いますか?

strスタックに割り当てられた12バイトの連続メモリの先頭を指すようになりました。

では、ヌル終了はどのように機能しますか?それは12文字の終わり(スペースが埋め込まれていますか?)ですか、それとも数字が2文字しか使用していない場合、2文字の後に発生しますか?

この場合、文字列を自分でnullで終了する必要があります(このタイプの宣言では自動的に発生しません)。

したがって、str(nullで終了する)文字列値を保持したい場合は、次のようにします。

str[0] = 'c';
str[1] = 'a';
str[2] = 't';
str[3] = '\0';

nullで終了する文字列を取得する別の方法は、次のことを行うことです。

char *str = "cat"; // this is null-terminated

スペースによる自動パディングはありません。

また、後で単純な構造体でポインタを使用した場合、メモリは自動的にクリアされますか、それともデストラクタが必要ですか?

ポインタがスタックに割り当てられたメモリの一部を指している場合、スタックがポップされたときにメモリが回復されます。それ以外の場合、次のようにヒープにメモリを割り当てる場合:

char *newStr    = new char[12];
char *mallocStr = (char*) malloc(sizeof(char) * 12);

delete次に、またはを使用してメモリの割り当てを解除する必要がありますfree(使用した方法によって異なります)。

デストラクタは初期化バッファサイズを知る必要がありますか?

このコンテキストでは、ヒープに割り当てられたメモリについて話しているため、答えはノーです。システムは、割り当てられたメモリの量を認識しています。そのため、サイズを指定する必要はなく、ポインタを指定するだけですdeletefree

実際の数からバッファ長を計算する必要がないのはなぜですか?

数が特定の量(たとえば4桁)を超えることは決してないことがわかっている場合は可能ですが、最終的には文字列ごとに数バイトしか無駄にしないため、通常は可能な最大長を指定する方が簡単です。非常に厳しいメモリ制約がない限り、大したことではありません。

snprintfはitoaよりも推奨されていますか?

snprintf与えられたバッファサイズを尊重するので「安全」と見なされるので、「はい」と言いますがitoa、サイズをチェックせずにバッファを問題なくいっぱいにします(割り当てられたスペースを超えて実行され、他のメモリを上書きする可能性があります)。

int   num = 12345;
char *str = new char[4];

// this is bad because str is not big enough to hold the number
// itoa does not check buffer size and will overrun the buffer (overwriting other data)
str = itoa(num, str);

// snprintf takes the buffer size as one of it's arguments
// in this case the whole number will not fit, but at least we don't overrun the buffer
snprintf(str, 4, "%i", num);

snprintfとは両方ともitoa、文字列をnullで終了します。

于 2011-07-29T13:40:09.253 に答える
0

std::stringstream本当にまたはを使用したくない場合は、バッファサイズの引数があるためlexical_cast、を使用する必要があります。ISOC関数ではありません。snprintfitoa

ヌル(文字'\ 0'、値0)は、バッファー内の任意のポイントに表示される可能性があります。文字列を処理するほとんどの関数は、そのポイント以降のバッファー内のすべてを無視するため、一種の「無駄な」スペースです。

あなたが次のようなものを持っていたとしましょう

char str[] = { 'a', 'b', 'c', '\0', 'd' };

printf最後の要素は、0に遭遇するとデータの処理を停止するような関数であっても、まだ存在しています。ただし、すべての関数がこれを実行するわけではありません。

配列(またはその他のプリミティブデータ型)のコンストラクタまたはデストラクタはありません。new、、または同様のものnew[]を使用して自分で割り当てた場合にのみ、割り当てられたメモリを解放することを心配する必要があります。malloc

バッファサイズはもちろん重要です。小さすぎると数値のすべての文字を保持できず、大きすぎるとメモリが無駄になります。22文字は、64ビット整数ごとに保持できる必要があります(ただし、float / doublesは保持できません!)。

最良のオプションは、std::stringstreamまたはstd/boost::lexical_castを使用std::stringすることです。これにより、これらすべての問題が処理されます。

非常に有益なMartinhoからのリンクを読むことをお勧めします。(配列はポインタではありません!)

于 2011-07-29T13:39:39.513 に答える