标签: null-terminated

null终止字符串的基本原理是什么?

尽管我喜欢C和C++,但我还是忍不住在选择空终止字符串时不知所措:

  • 在C之前存在长度前缀(即Pascal)字符串
  • 通过允许恒定时间长度查找,长度前缀字符串使得几种算法更快.
  • 长度前缀字符串使得更容易导致缓冲区溢出错误.
  • 即使在32位机器上,如果允许字符串为可用内存的大小,则长度前缀字符串仅比空终止字符串宽三个字节.在16位机器上,这是一个字节.在64位机器上,4GB是一个合理的字符串长度限制,但即使你想将它扩展到机器字的大小,64位机器通常有足够的内存使额外的七个字节排序为null参数.我知道最初的C标准是针对极其糟糕的机器(就内存而言)而写的,但效率论证并没有把我卖给我.
  • 几乎所有其他语言(即Perl,Pascal,Python,Java,C#等)都使用长度前缀字符串.这些语言通常在字符串操作基准测试中胜过C,因为它们对字符串更有效.
  • C++对std::basic_string模板进行了一些纠正,但是期望空终止字符串的普通字符数组仍然很普遍.这也是不完美的,因为它需要堆分配.
  • 空终止字符串必须保留一个字符(即null),该字符不能存在于字符串中,而长度前缀字符串可以包含嵌入的空值.

这些事情中的一些最近比C更明显,因此C对于不了解它们是有意义的.然而,在C出现之前,有几个很平常.为什么选择空终止字符串而不是明显优越的长度前缀?

编辑:由于一些人在我的效率点上询问事实(并且不喜欢我已提供的事实),他们源于以下几点:

  • 使用空终止字符串的Concat需要O(n + m)时间复杂度.长度前缀通常只需要O(m).
  • 使用空终止字符串的长度需要O(n)时间复杂度.长度前缀为O(1).
  • length和concat是迄今为止最常见的字符串操作.在某些情况下,空终止字符串可以更有效,但这些情况发生得更少.

从下面的答案中,这些是空终止字符串更有效的一些情况:

  • 当你需要切断字符串的开头并需要将它传递给某个方法时.即使您被允许销毁原始字符串,也无法在长度前缀的常量时间内执行此操作,因为长度前缀可能需要遵循对齐规则.
  • 在某些情况下,您只需按字符循环字符串,就可以保存CPU寄存器.请注意,这仅适用于您尚未动态分配字符串的情况(因为您必须释放它,因此必须使用您保存的CPU寄存器来保存您最初从malloc和朋友那里获得的指针).

以上都不像长度和连续那样常见.

在下面的答案中还有一个断言:

  • 你需要切断字符串的结尾

但这个不正确 - 它与null终止和长度前缀字符串的时间相同.(Null终止字符串只是在你希望新结束的地方粘贴一个空值,长度前缀只是从前缀中减去.)

c c++ string null-terminated

272
推荐指数
12
解决办法
2万
查看次数

字符串终止 - char c = 0 vs char c ='\ 0'

在终止字符串时,在我看来逻辑上char c=0等同于char c='\0',因为"null"(ASCII 0)字节是0,但通常人们倾向于这样做'\0'.这纯粹是出于偏好还是应该是一个更好的"实践"?

什么是首选?


编辑: K&R :"字符常量'\0'表示值为零的字符,空字符.'\0'经常编写而不是0强调某些表达式的字符性质,但数值只是0.

c string c-strings null-terminated ansi-c

45
推荐指数
3
解决办法
9万
查看次数

在C++ 11中,std :: string总是以null结尾吗?

在他的网站2008年的一篇文章中,Herb Sutter声明如下:

由于与并发相关的原因,有一个积极的建议是在C++ 0x中进一步加强这一点并且需要空终止并且可能禁止写时复制实现.以下是该文件:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2534.html.我认为本文中的一个或两个提案很可能会被采纳,但我们将在下一个或两个会议上看到.

我知道C++ 11现在保证std :: string内容连续存储,但他们是否在最终草案中采用了上述内容?

现在使用类似的东西会安全&str[0]吗?

c++ string null-terminated language-lawyer c++11

44
推荐指数
1
解决办法
7517
查看次数

将非null终止的unsigned char数组复制到std :: string

如果数组是以null结尾的,那么这将非常简单:

unsigned char u_array[4] = { 'a', 's', 'd', '\0' };
std::string str = reinterpret_cast<char*>(u_array);
std::cout << "-> " << str << std::endl;
Run Code Online (Sandbox Code Playgroud)

但是,我想知道复制非null终止的 unsigned char数组的最合适方法是什么,如下所示:

unsigned char u_array[4] = { 'a', 's', 'd', 'f' };
Run Code Online (Sandbox Code Playgroud)

进入std::string.

有没有办法在没有迭代unsigned char数组的情况下做到这一点?

谢谢你们.

c++ arrays string copy null-terminated

41
推荐指数
3
解决办法
4万
查看次数

main null中的char*argv []参数是否终止?

所以我想知道命令行参数是否总是以空值终止?Google似乎是肯定的,并且在GCC上进行编译表明情况确实如此,但我可以保证这一切始终是真的吗?

int main(int argc, char** argv)
{
    char *p;

    for(int cnt=1; cnt < argc; ++cnt)
    {
        p = argv[cnt];
        printf("%d = [%s]\n", cnt, p);
    }
    return 0;
}

$ MyProgram -arg1 -arg2 -arg3
1 = -arg1
2 = -arg2
3 = -arg3
Run Code Online (Sandbox Code Playgroud)

c null-terminated argv

41
推荐指数
1
解决办法
2万
查看次数

std :: string是否可以包含嵌入的空值?

对于常规C字符串,空字符'\0'表示数据的结尾.

那么std::string,我可以使用嵌入空字符的字符串吗?

c++ c-strings stdstring null-terminated

37
推荐指数
2
解决办法
2万
查看次数

为什么以null结尾的字符串?或者:以空值终止与字符+长度存储

我正在用C编写语言解释器,我的string类型包含一个length属性,如下所示:

struct String
{
    char* characters;
    size_t length;
};
Run Code Online (Sandbox Code Playgroud)

因此,我必须花费大量时间在我的解释器中手动处理这种字符串,因为C不包含对它的内置支持.我考虑过切换到简单的以null结尾的字符串只是为了符合底层C,但似乎有很多理由不:

如果使用"length"而不是查找null,则内置边界检查.

您必须遍历整个字符串才能找到它的长度.

你必须做额外的事情来处理以null结尾的字符串中间的空字符.

以空值终止的字符串与Unicode处理不佳.

非空终止字符串可以实习更多,即"Hello,world"和"Hello"的字符可以存储在同一个地方,只是具有不同的长度.使用以null结尾的字符串无法做到这一点.

字符串切片(注意:字符串在我的语言中是不可变的).显然,第二较慢(和更容易出错:考虑增加的错误检查beginend对两种功能).

struct String slice(struct String in, size_t begin, size_t end)
{
    struct String out;
    out.characters = in.characters + begin;
    out.length = end - begin;

    return out;
}

char* slice(char* in, size_t begin, size_t end)
{
    char* out = malloc(end - begin + 1);

    for(int i = 0; i < end - begin; i++)
        out[i] = in[i + …
Run Code Online (Sandbox Code Playgroud)

c string algorithm performance null-terminated

29
推荐指数
6
解决办法
1万
查看次数

strstr()表示非null终止的字符串

如何在C 中对计数字符串(即空终止)进行就地等效?strstr()

c string indexof null-terminated

27
推荐指数
3
解决办法
1万
查看次数

文件如何包含空字节?

文件如何在用空终止字符串(即C)的语言编写的操作系统中包含空字节?

例如,如果我运行此shell代码:

$ printf "Hello\00, World!" > test.txt
$ xxd test.txt
0000000: 4865 6c6c 6f00 2c20 576f 726c 6421       Hello., World!
Run Code Online (Sandbox Code Playgroud)

我看到一个空字节test.txt(至少在OS X中).如果C使用空终止字符串,并且OS X是用C语言编写的,那么为什么文件不会在空字节处终止,从而导致文件包含Hello而不是Hello\00, World!?文件和字符串之间是否存在根本区别?

c macos null-terminated

26
推荐指数
4
解决办法
9853
查看次数

23
推荐指数
4
解决办法
7万
查看次数