字符指针初始化与非指针初始化相比?发生了什么

char pointer initialization compared to non pointer? What happens

本文关键字:指针 初始化 发生了 什么 字符      更新时间:2023-10-16

我知道用普通字符无法做到这一点。

    char line1 = "hello";

但是你可以用一个指向字符类型的指针来完成

    char* line2 = "hello";

我想知道为什么会这样,在第二行代码中会发生什么?为什么第二次初始化是可能的?第2行是否指向hello的第一个索引?它是否创建了某种数组并用hello填充?我在一个编程类的c字符串类中使用了这个,但我仍然对第二行代码中发生的事情感到困惑。

编译器确保您指定的以null结尾的字符串"hello"存在于内存中的某个位置,并初始化指针以指向该字符串的开头。

当您编写时

char *line1 = "something";

line1被创建为堆栈上的指针(如果在自动作用域中(,并被初始化为指向文字字符串"something"(带有null终止符(。确切地说,"something"字符串具有包括空终止符的类型char[10],并且数组衰减到指向该特定实例中的第一个元素的指针。

存储该字符串的数据是已编译的可执行文件的数据部分,并且它是只读的(即写入它可能会触发访问冲突(。

在C和C++中,当您制作字符串文字时,会隐式创建一个类型为char[]的变量,该变量具有静态存储持续时间。字符串将以null结尾,这与C风格一致。

线路

char* line2 = "hello";

大致相当于

static char __string_literal_line2[] = "hello";
// At top of program or something
...
char * line2 = __string_literal_line2;

因此,当你这样做时,char[]隐式地衰减为char*

这方面的一个问题是,数组在某种意义上确实是"const",尝试修改它是未定义的行为,但C标准明确允许您无论如何将其分配给char *,因此不正确的遗留代码仍将编译,并且兼容C++也允许这样做。

如果您在进行编译时编程以利用字符串文字的"真实形式",有时会非常方便。例如,在这个代码示例中:

在周围传递constexpr对象

class str_const {
    const char * const p_;
    const std::size_t sz_;
public:
    template <std::size_t N>
    constexpr str_const( const char( & a )[ N ] )
    : p_( a ), sz_( N - 1 ) {}
    ...
};

str_const对象现在可以在编译时根据字符串文字构造为constexpr,它将知道字符串文字的大小,即使通常需要迭代或使用C库函数来确定。这是因为它接收的字符串文字是char[],而不是char *,并且它可以绑定到数组的长度,作为模板推导的一部分。因此,这些表达式是合法的,并且str_const对象在编译时知道字符串的长度:

str_const("foo");
str_const("foobar");
str_const("foobarbaz");
char test[] = "Hello" // adds H e l l o  in the stack 

当你做一些像f("你好"(这样的事情时,它会保留内存来存储H e l l O\0当你做

char *test = "Hello";

它也将Hello存储在某个地方,并将测试初始化为存储"H"的内存情况。

指针基本上是4字节的整数。你应该尝试一个程序询问密码并像这样验证:

if(password == "mypassword")

您的工作是在生成的二进制文件中查找"mypassword"。