尽管我喜欢C和C++,但我还是忍不住在选择空终止字符串时不知所措:
std::basic_string
模板进行了一些纠正,但是期望空终止字符串的普通字符数组仍然很普遍.这也是不完美的,因为它需要堆分配.这些事情中的一些最近比C更明显,因此C对于不了解它们是有意义的.然而,在C出现之前,有几个很平常.为什么选择空终止字符串而不是明显优越的长度前缀?
编辑:由于一些人在我的效率点上询问事实(并且不喜欢我已提供的事实),他们源于以下几点:
从下面的答案中,这些是空终止字符串更有效的一些情况:
以上都不像长度和连续那样常见.
在下面的答案中还有一个断言:
但这个不正确 - 它与null终止和长度前缀字符串的时间相同.(Null终止字符串只是在你希望新结束的地方粘贴一个空值,长度前缀只是从前缀中减去.)
在终止字符串时,在我看来逻辑上char c=0
等同于char c='\0'
,因为"null"(ASCII 0)字节是0
,但通常人们倾向于这样做'\0'
.这纯粹是出于偏好还是应该是一个更好的"实践"?
什么是首选?
编辑: K&R 说:"字符常量'\0'
表示值为零的字符,空字符.'\0'
经常编写而不是0
强调某些表达式的字符性质,但数值只是0
.
在他的网站2008年的一篇文章中,Herb Sutter声明如下:
由于与并发相关的原因,有一个积极的建议是在C++ 0x中进一步加强这一点并且需要空终止并且可能禁止写时复制实现.以下是该文件:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2534.html.我认为本文中的一个或两个提案很可能会被采纳,但我们将在下一个或两个会议上看到.
我知道C++ 11现在保证std :: string内容连续存储,但他们是否在最终草案中采用了上述内容?
现在使用类似的东西会安全&str[0]
吗?
如果数组是以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数组的情况下做到这一点?
谢谢你们.
所以我想知道命令行参数是否总是以空值终止?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字符串,空字符'\0'
表示数据的结尾.
那么std::string
,我可以使用嵌入空字符的字符串吗?
我正在用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结尾的字符串无法做到这一点.
字符串切片(注意:字符串在我的语言中是不可变的).显然,第二较慢(和更容易出错:考虑增加的错误检查begin
和end
对两种功能).
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 中对计数字符串(即非空终止)进行就地等效?strstr()
文件如何在用空终止字符串(即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!
?文件和字符串之间是否存在根本区别?