代码之家  ›  专栏  ›  技术社区  ›  user206268

禁用GCC中字符串的NUL终止

  •  1
  • user206268  · 技术社区  · 16 年前

    是否可以全局禁用GCC中以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终止,以节省一些字节?

    7 回复  |  直到 16 年前
        1
  •  1
  •   Remo.D    16 年前

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

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

    而不是使用您分配的文本缓冲区 malloc() sizeof 不会帮你的。

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

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

        2
  •  1
  •   intgr    16 年前

    这非常糟糕,但您可以显式指定每个字符数组常量的长度:

    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));
    
        3
  •  0
  •   Matthew Farwell    16 年前

    我记不起细节了,但当我记得的时候

    char my_constant[5]
    

    几乎总是最好将这类事情留给编译器,让它为您处理optmization,除非有很好的理由这样做。

        4
  •  0
  •   pmg    16 年前

    任何 在处理字符串的标准库函数中,可以忽略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" */
    
        5
  •  0
  •   Roman Nikitchenko    16 年前

    事实上,这只是在你的记忆力真的很差的情况下。 否则我不建议这样做。

    • 以以下形式准备一些最小的“列表”文件:
        string1_constant_name "str1"
        string2_constant_name "str2"
        ...
    
    • 要构造处理文件并生成声明的实用程序,请执行以下操作:
        const char string1_constant[4] = "str1";
    

    由于固定的自动生成数组,现在您有了两个未终止的字符串,并且每个变量都有sizeof()。这个解决方案似乎可以接受。

    利益

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

        6
  •  0
  •   Fletch    16 年前

        7
  •  0
  •   Remember Monica    14 年前

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

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