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 str1[10];
 char str2[12];
 ....

而不是与您分配的文本缓冲区malloc()和朋友一起使用,否则sizeof对您没有帮助。

无论如何,我会在最后删除 \0 时三思而后行:您将失去与 C 标准库函数的兼容性。

除非您要为您的库重写任何单个字符串函数(例如 sprintf),否则您确定要这样做吗?

于 2009-11-20T17:46:35.890 回答
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 回答
0

这些不是类似于 Pascal 风格的弦乐或 Hollerith 弦乐吗?我认为这仅在您确实希望字符串数据保留 NULL 时才有用,在其中您实际上是在推动任意内存,而不是“字符串”本身。

于 2009-11-25T00:45:59.617 回答
0

我不记得细节,但当我记得

char my_constant[5]

无论如何,它可能会保留 8 个字节,因为有些机器无法寻址一个字的中间。

几乎总是最好把这种事情留给编译器,让它为你处理优化,除非有一个非常好的理由这样做。

于 2009-11-20T17:53:26.987 回答
0

这个问题使用了错误的假设——它假设存储长度(例如,通过将其作为数字隐式传递给函数)不会产生任何开销,但事实并非如此。

虽然可以通过不存储 0 字节(或 wchar)来节省空间,但大小必须存储在某处,并且该示例暗示它作为常量参数传递给某处的函数,这在代码中几乎肯定会占用更多空间. 如果多次使用相同的字符串,则开销是每次使用,而不是每个字符串。

拥有一个使用 strlen 确定字符串长度且未内联的包装器几乎肯定会节省更多空间。

于 2012-04-26T14:52:34.627 回答
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 终止字节。

No strlen(), no fgets(), no atoi(), no strtoul(), no fopen(), noprintf()%s转换说明符...

只用所需的空间声明你的“不是 C 字符串”;

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

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