Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 关于空字符必要性的混淆?_C++ - Fatal编程技术网

C++ 关于空字符必要性的混淆?

C++ 关于空字符必要性的混淆?,c++,C++,我正在阅读关于为什么需要空字符的文章,然后我发现这对我来说是有意义的。它指出之所以需要它,是因为字符数组(对于C字符串)的分配通常比实际字符串大得多,因此需要一种符号化结束的方法 但是,为什么这些数组不只是使用基于初始值设定项的大小推断来构造(没有直接分配给字符串文本时实际隐式添加的空字符)。与此类似,如果包含字符串的数组是使用大小推断构造的,则不需要空字符,因为数组不比字符串大,因此当然,它将在该数组的末尾结束。历史上,字符串数组提供了终止符号。原因很简单:不需要发送两个值(数组头和数组长度)

我正在阅读关于为什么需要空字符的文章,然后我发现这对我来说是有意义的。它指出之所以需要它,是因为字符数组(对于C字符串)的分配通常比实际字符串大得多,因此需要一种符号化结束的方法


但是,为什么这些数组不只是使用基于初始值设定项的大小推断来构造(没有直接分配给字符串文本时实际隐式添加的空字符)。与此类似,如果包含字符串的数组是使用大小推断构造的,则不需要空字符,因为数组不比字符串大,因此当然,它将在该数组的末尾结束。

历史上,字符串数组提供了终止符号。原因很简单:不需要发送两个值(数组头和数组长度),只需要传递一个值,即数组头。这简化了调用签名,但对调用方提出了一些要求

在C/C++本身中,null字符是一个终止符号,所以所有运行时函数都会使用第一个null字符作为行尾。同时,在应用逻辑方面,终端符号可能不同:例如,在HTTP头中,有一个CR-LF-CR-LF序列标记头的结束,单个CR-LF序列只是下一行的开始

但为什么这些数组不只是用大小缩减来构造呢 基于初始值设定项(不包含实际为 直接指定给字符串文字时隐式添加)

我想你是说为什么你不能写:

char t[] = "abracadabra";
编译器会推断出11的大小

因为你有12个字符,而不是11个。如果数组的大小为11,则会丢失一些内容:用于包含NUL的字节将不会被引用,编译器也不会对以下内容产生影响:

char t[] = "abracadabra"; // an array deduced from a C-string literal

第一个必须在作用域末尾释放12个字节,第二个必须在作用域末尾释放11个字节

从历史上看,数组只是指针算术之上的一种语法糖

。。。因为那个字符数组。。。通常分配的字符串比实际字符串大得多

这个答案很糟糕

C字符串可以动态分配,这意味着您在运行之前不知道它们应该有多长。您可以只
malloc(required_size+1)
并在末尾粘贴一个nul字符,而不是预先分配一个大数组并用零填充大部分数组

相反,编译时已知的字符串文本肯定不会“分配的字符串比实际字符串大得多”。这没有任何意义,因为你事先知道需要多少空间

但为什么这些数组不只是基于初始值设定项的大小推断构建的呢

好了,一个动态大小的字符串。您的“尺码扣减”是多少?什么是“初始值设定项”

<>我本来可以用<代码> STD::String 写一个不太丑陋的例子,因为这个问题是用C++标记的,但是实际上是你问的C字符串,它没有任何真正的区别。 我正在阅读关于为什么需要空字符的文章,然后我发现这个答案对我来说有些道理。它指出之所以需要它,是因为字符数组(对于C字符串)的分配通常比实际字符串大得多,因此需要一种符号化结束的方法

答案是误导性的。这并不是为什么需要空终止的真正原因。投票越多,被接受的答案越好

不需要空字符,因为数组不比字符串大,所以它当然会在数组的末尾结束

让我们提醒自己,不能将数组用作函数参数。即使可以,我们也不想这样做,因为将整个数组复制到参数中会很慢

因此,需要间接引用数组。间接寻址通常使用指针(或引用)实现。现在,我们可以有一个“指向大小为42的字符数组的指针”,但这不是很有用,因为这样参数只能指向一个特定大小的字符串

相反,常用的方法是使用指向数组第一个元素的指针。这是一种非常常见的模式,以至于该语言有一条规则,允许数组的名称隐式地衰减到指向第一个元素的指针中

但是,基于指向数组元素的指针,你能说出数组有多大吗?你不能。你需要额外的信息。链接问题的公认答案解释了可用于表示大小的选项,并且C的设计者选择了使用终止字符的选项(这已经是C所基于的BCPL语言使用的约定)



TL;需要DR大小信息,因为需要间接引用字符串,而间接引用隐藏了有关数组大小的知识。空终止是编码字符串内容中大小信息的一种方法,也是C语言设计者选择的方法。

字符串通常通过创建
char
数组来保存中间结果并修改其内容来操作:

char buffer[128];
strcpy(buffer, "Hello, ");
strcat(buffer, "world");
std::cout << buffer << '\n';
char缓冲区[128];
strcpy(缓冲区,“你好,”);
strcat(缓冲区,“世界”);

std::cout-related和populary-dupe:如果没有数组,只有指针呢?你怎么知道它所指向的数据的大小呢?@EdChum谢谢,我能看到相似之处,但我不相信它真的回答了我的问题。。至少不是基于我对它的略读,请添加一些代码示例,展示一个您认为不需要终止null的情况。注意,te
size_t expected;
if (read(fd, &expected, sizeof(expected)) == sizeof(expected)) {
  char *buf = malloc(expected + 1);
  if (buf && read(fd, buf, expected) == expected) {
    buf[expected] = 0;
    /* now do something with buf */
  }
}
char buffer[128];
strcpy(buffer, "Hello, ");
strcat(buffer, "world");
std::cout << buffer << '\n';