在GCC中禁用NUL终止字符串

时间:2009-11-20 17:32:40

标签: c gcc null-terminated

是否可以在GCC中全局禁用NUL终止的字符串?

我正在使用自己的字符串库,我完全不需要最终的NUL字符,因为它已经在结构内部存储了适当的长度。

但是,如果我想追加10个字符串,这意味着在堆栈上不必要地分配了10个字节。使用宽字符串甚至更糟:对于x86,浪费了40个字节;对于x86_64,80字节!

我定义了一个宏来将这些堆栈分配的字符串添加到我的struct:

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

使用sizeof(...) - 1效果很好,但我想知道是否可以摆脱NUL终止以节省几个字节?

7 个答案:

答案 0 :(得分: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));

答案 1 :(得分:1)

我知道你只处理程序中声明的字符串:

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

而不是您使用malloc()分配的文字缓冲区,而其他sizeof的朋友不会帮助您。

无论如何,我会考虑最后删除\ 0:你会失去与C标准库函数的兼容性。

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

答案 2 :(得分:0)

我不记得细节,但是当我做的时候

char my_constant[5]

它可能会保留8个字节,因为有些机器无法处理单词的中间位置。

将这类事情留给编译器并让它为您处理选择几乎总是最好的,除非有一个非常合理的理由这样做。

答案 3 :(得分:0)

事实上,这只是在内存非常低的情况下。否则我不建议这样做。

你正在谈论的事情似乎最恰当的方式是:

  • 以下列形式准备一些最小的'列表'文件:
    string1_constant_name "str1"
    string2_constant_name "str2"
    ...
  • 构建处理文件的实用程序并生成声明,例如
    const char string1_constant[4] = "str1";

当然我不建议用手做这件事,因为否则你会在任何字符串改变后遇到麻烦。

所以现在你有两个非终止字符串,因为固定的自动生成数组,你也有每个变量的sizeof()。这个解决方案似乎是可以接受的。

优势易于本地化,可以添加一定程度的检查以降低此解决方案的风险并节省R / O数据段。

缺点需要在每个模块中包含所有这些字符串常量(包括以保持sizeof()已知)。所以这只有你的链接器合并这些符号(有些没有)才有意义。

答案 4 :(得分:0)

如果您没有使用处理字符串的任何标准库函数,您可以忘记NUL终止字节。

没有strlen(),没有fgets(),没有atoi(),没有strtoul(),没有fopen(),没有printf()与{ {1}}转化说明符......

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

%s

答案 5 :(得分:0)

这些与Pascal风格的字符串或Hollerith字符串不相似吗?我认为这只有在您真正希望String数据保留NULL时才有用,在这种情况下,您实际上是在推动任意内存,而不是“字符串”本身。

答案 6 :(得分:0)

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

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

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