双引号的属性
Posted
技术标签:
【中文标题】双引号的属性【英文标题】:Properties of double quotes 【发布时间】:2018-02-22 22:44:32 【问题描述】:我想知道双引号有什么属性,尤其是在初始化 char 指针方面。
char *ptr="hello";
char array[6]='h','e','l','l','o';
cout<<ptr<<endl<<array<<endl;
上面的代码打印 hello 两次。我知道使用双引号表示一个字符串,或者一个末尾带有空字符的 char 数组。由于 ptr 正在寻找要分配的内存地址 (char*),因此我猜测“hello”解析为“h”的内存地址,尽管您还填写了 char 值阵列的其余部分?如果是这样的话,是不是意味着在上面的代码中
char *ptr="hello";
双引号在内存中的某处创建一个字符串,然后将ptr分配给该字符串的第一个元素,而
char array[6]='h','e','l','l','o';
在内存中的某处创建一个数组,然后根据赋值运算符的右侧为每个索引分配值?
【问题讨论】:
您需要打开编译器警告。char *ptr="hello";
应该警告你或者错误提示它是不允许的。
@NathanOliver:尽管考虑到 C 字符串文字不是 const
(尽管修改内容是未定义的行为),char *ptr = "hello";
在 C 中是合法的,并且许多编译器在 C++ 中允许它(如只要你不分配它)除非警告被提高到迂腐的水平。
@ShadowRanger 该问题未标记为 C,并且该转换在 C++03(近 15 年前)中已弃用,此后已正式从该语言中删除。
【参考方案1】:
这里有两点需要注意。
char array[6]='h','e','l','l','o';
这将在堆栈上分配 6 个字节并将它们初始化为“hello\0”;以下是等价的:
char array[] = "hello";
char array[6] = "hello";
但是,以下情况有所不同。
char *ptr="hello";
这将在堆栈上分配一个指针,该指针指向常量字符串“hello\0”。这是一个重要的区别,如果您更改 ptr
指向的值,您将导致未定义的行为,因为您将更改它指向的常量值。
例子:
#include <stdio.h>
void testLocal()
char s[] = "local"; // locally allocated 6 bytes initialized to "local\0"
s[0] = 'L';
printf("%s\n", s);
void testPointer()
char *s = "pointer"; // locally allocated pointer, pointing to a constant
// This segfaults on my system, but really the behavior is undefined.
s[0] = 'P';
printf("%s\n", s);
int main(int argc, char * argv[])
testLocal();
testPointer();
【讨论】:
我很确定你错了。第一个数组只是一个数组,不需要以空值结尾。第二个不会编译,除非你把它改成char ptr[] = "foo";
。这仅在 GCC 上作为扩展 AFAIK 编译。
@razzorflame,Geoffrey 对array
的看法是正确的。第六个元素初始化为0
。
是的,它被初始化为 0 但它不需要。 char 数组并不意味着总是以零结尾。
@razzorflame,是的,但在这种情况下,数组中有一个额外的元素,语言要求将其初始化为零。
好吧,忽略我对第一个数组的部分评论,他是对的。但是,在 C++ 中将字符串文字分配给 char* 是无效的。【参考方案2】:
对于字符串,有一个特殊的终端字符\0
添加到末尾。这告诉它这是字符串的结尾。
所以,如果你有一个字符串“hello”,它会继续读取每个字符:“h”、“e”、“l”、“l”、“o”、“\0”,它告诉它停下来。
字符数组类似,但没有那个终结符。相反,数组本身的长度表示要读取多少个字符(不一定适用于所有方法)。
【讨论】:
问题在于变量在内存中的分配位置,而不是字符串终止符如何工作。以上是关于双引号的属性的主要内容,如果未能解决你的问题,请参考以下文章