为什么我可以将字符串存储在char的内存地址中?

San*_*ace 0 c string pointers char memory-address

我开始理解指针以及如何取消引用它们等等.我一直在用ints 练习,但我认为它char会表现得相似.使用*取消引用,使用&访问内存地址.

但在下面的示例中,使用相同的语法来设置a的地址char并将字符串保存到同一个变量中.这是如何运作的?我想我一般都很困惑,也许我正在思考它.

int main()
{
    char *myCharPointer;
    char charMemoryHolder = 'G';
    myCharPointer = &charMemoryHolder;
    printf("%s\n", myCharPointer);
    myCharPointer = "This is a string.";
    printf("%s\n", myCharPointer);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

pas*_*pkT 6

首先,您需要了解"字符串"如何在C中工作.

"字符串"存储为内存中的字符数组.由于无法确定字符串的长度,'\0'因此在字符串后面附加NUL字符,以便我们知道字符串的结束位置.

因此,例如,如果你有一个字符串"foo",它可能在内存中看起来像这样:

--------------------------------------------
| 'f' | 'o' | 'o' | '\0' | 'k' | 'b' | 'x' | ...
--------------------------------------------
Run Code Online (Sandbox Code Playgroud)

之后的事情'\0'只是恰好放在字符串之后的东西,可能会也可能不会被初始化.

当您为类型变量分配"字符串"时char *,会发生变量将指向字符串的开头,因此在上面的示例中它将指向'f'.(换句话说,如果你有一个字符串str,那么str == &str[0]总是如此.)当你将一个字符串赋给一个类型的变量时char *,你实际上是将该字符串的第0个字符的地址赋给变量.

当您将此变量传递给printf()它时,它从指向的地址开始,然后逐个遍历每个字符,直到它看到'\0'并停止.例如,如果我们有:

char *str = "foo";
Run Code Online (Sandbox Code Playgroud)

你传递给它printf(),它会做以下事情:

  1. 取消引用str(给出'f')
  2. 取消引用(str+1)(给出'o')
  3. 取消引用(str+2)(给另一个'o')
  4. 取消引用(str+3)(这使得'\0'流程停止).

这也可以得出结论,你目前所做的事实上是错误的.在您的代码中,您有:

char charMemoryHolder = 'G';
myCharPointer = &charMemoryHolder;
printf("%s\n", myCharPointer);
Run Code Online (Sandbox Code Playgroud)

printf()看到说明%s符时,它会转到指向的地址myCharPointer,在这种情况下它包含'G'.然后它会尝试获取下一个字符'G',这是未定义的行为.它可能会偶尔给你正确的结果(如果下一个内存位置碰巧包含'\0'),但一般情况下你永远不应该这样做.