1

GCCでNULで終了する文字列をグローバルに無効にすることは可能ですか?

私は独自の文字列ライブラリを使用していますが、構造体の内部に適切な長さがすでに格納されているため、最後のNUL文字はまったく必要ありません。

ただし、10個の文字列を追加したい場合、これは10バイトがスタックに不必要に割り当てられることを意味します。幅の広い文字列の場合はさらに悪化します。x86の場合、40バイトが無駄になります。x86_64の場合、80バイト!

これらのスタック割り当て文字列を構造体に追加するマクロを定義しました。

#define AppendString(ppDest, pSource) \
  AppendSubString(ppDest, (*ppDest)->len + 1, pSource, 0, sizeof(pSource) - 1)

使用sizeof(...) - 1は非常にうまく機能しますが、数バイトを節約するためにNUL終了を取り除くことができるかどうか疑問に思っていますか?

4

7 に答える 7

1

これはかなりひどいですが、すべての文字配列定数の長さを明示的に指定できます。

char my_constant[6] = "foobar";
assert(sizeof my_constant == 6);

wchar_t wide_constant[6] = L"foobar";
assert(sizeof wide_constant == 6*sizeof(wchar_t));
于 2009-11-20T17:34:58.333 に答える
1

プログラムで宣言された文字列のみを扱っていることを理解しています。

 ....
 char str1[10];
 char str2[12];
 ....

そして、あなたが割り当てたテキストバッファmalloc()や友達と一緒でsizeofはなく、そうでなければあなたを助けるつもりはありません。

とにかく、最後に\0を削除することについて2度考えます。C標準ライブラリ関数との互換性が失われます。

ライブラリの単一の文字列関数(たとえば、sprintf)を書き直す場合を除いて、それを実行してもよろしいですか?

于 2009-11-20T17:46:35.890 に答える
0

詳細は思い出せませんが、覚えていると

char my_constant[5]

一部のマシンはワードの途中をアドレス指定できないため、とにかく8バイトを予約する可能性があります。

本当に本当に正当な理由がない限り、ほとんどの場合、この種のものをコンパイラーに任せて、コンパイラーに最適化を処理させるのが最善です。

于 2009-11-20T17:53:26.987 に答える
0

確かに、これはあなたが本当にメモリが少ない場合にのみです。そうでなければ、そうすることはお勧めしません。

あなたが話していることをするのに最も適切な方法は次のようです:

  • 最小限の「リスト」ファイルを次の形式で準備するには:
    string1_constant_name "str1"
    string2_constant_name "str2"
    ..。
  • ファイルを処理し、次のような宣言を生成するユーティリティを構築するには
    const char string1_constant [4] = "str1";

もちろん、これを手作業で行うことはお勧めしません。そうしないと、弦を変更した後に問題が発生する可能性があるためです。

これで、自動生成された配列が固定されているため、終了していない文字列と、すべての変数にsizeof()があります。この解決策は許容できるようです。

利点は、ローカリゼーションが容易であり、このソリューションのリスクを低くするためにある程度のチェックを追加できる可能性と、R/Oデータセグメントの節約です。

欠点は、すべてのモジュールにそのような文字列定数をすべて含める必要があります(sizeof()を既知に保つために含む)。したがって、これは、リンカーがそのようなシンボルをマージする場合にのみ意味があります(一部はマージしません)。

于 2009-11-20T18:03:38.853 に答える
0

文字列を処理する標準ライブラリ関数を使用していない場合は、NULの終了バイトを忘れることができます。

いいえstrlen()、いいえfgets()、いいえatoi()、いいえ、strtoul()いいえ、fopen()いいえprintf()%s変換指定子を使用して..。

必要なスペースだけで「C文字列ではない」と宣言します。

struct NotQuiteCString { /* ... */ };

struct NotQuiteCString variable;
variable.data = malloc(5);
data[0] = 'H'; /* ... */ data[4] = 'o'; /* "hello" */
于 2009-11-20T18:27:56.723 に答える
0

これらはパスカルスタイルの弦やホレリス弦に似ていませんか?これは、文字列データにNULLを保持させたい場合にのみ役立つと思います。この場合、「文字列」自体ではなく、実際に任意のメモリをプッシュします。

于 2009-11-25T00:45:59.617 に答える
0

この質問では、誤った仮定を使用しています。長さを格納することで(たとえば、関数に数値として渡すことで暗黙的に)オーバーヘッドが発生しないと仮定していますが、それは正しくありません。

0バイト(またはwchar)を格納しないことでスペースを節約できますが、サイズはどこかに格納する必要があります。この例は、コード内のどこかに定数引数として渡されることを示しています。これは、ほぼ確実により多くのスペースを必要とします。 。同じ文字列が複数回使用される場合、オーバーヘッドは文字列ごとではなく、使用ごとになります。

strlenを使用して文字列の長さを決定し、インライン化されていないラッパーを使用すると、ほぼ確実にスペースを節約できます。

于 2012-04-26T14:52:34.627 に答える