0

我愿意

char ch = 'c';

进而

char *char_ptr = &ch;
*(char_ptr+1) = 'h';
*(char_ptr+2) = '\0';

当我使用打印它时,这可以正常工作

printf("char_ptr as string = %s\n", char_ptr);

但是当我这样做时

char *char_ptr = 'c';
*(char_ptr+1) = 'h';
*(char_ptr+2) = '\0';

然后它会导致分段错误。这背后的原因是什么?

4

4 回答 4

4

'c'是一个整数常数,在 ASCII 系统下,计算结果为0x63.

那个,以及紧随其后的地址,几乎可以肯定是无效的地址,开始戳信息。

事实上,即使是第一个也是未定义的行为,因为ch只分配了一个字符,而您正试图更改除此之外的信息。它可能会根据您的编译器如何布置内存和堆栈帧而起作用,但这仍然是一个非常糟糕的主意。

更正确的做法是:

char char_ptr[3] = "c";    // Allocate three bytes to ensure room.
*(char_ptr+1) = 'h';       // or char_ptr[1] = 'h';
*(char_ptr+2) = '\0';      // or char_ptr[2] = '\0';
于 2013-10-30T03:39:44.093 回答
0
char *char_ptr = 'c'; 

那是一个指针,它需要指向一个地址,即 &ch 是什么。

于 2013-10-30T03:41:44.117 回答
0

赋值char *char_ptr = addr将指针指向char_ptr内存地址addr。在您的示例中,&ch是的地址ch,而'c'只是一个char值,因此不是有效的内存地址。

于 2013-10-30T03:50:14.720 回答
0
char ch = 'c';

这是一个 C 命令,它(内部)保留 1 个字节来在其中存储/保存字符“c”,在(对于用户)未知的内存位置(如果应用程序正在运行,那么在内存中的一个位置,应用程序在执行之前保留)。

char *char_ptr = &ch;

这是一个命令,即:

  1. 声明一个字符(char)的“数组”,用星号指示为指针,1a。此“指针”变量的大小具有用户 CPU 带宽的大小(32 位操作系统下的用户长度为 4 字节,64 位操作系统下的用户长度为 8 字节。这是默认大小.

  2. 使用 ampsign &,您引用了一个内存位置 - 它将指向“ch”,您通过char ch = 'c' 给出的命令; 注意:这是一个参考,没有指针!因此,内存值“c”不会改变。因此,您可以获得未定义的易碎/行为,因为您“保留”了 ch 仅一个字节,并且应用程序愿意在良好的操作系统上记住这一点,应用程序崩溃。这有背景,您引用“内存”位置,这部分内存将受到应用程序操作系统的保护。如果运气好的话,_ptr 的大小与你的计算机 cpu 拱门相同。如果运气好,操作系统会将ch的一个字节复制到_ptr地址的位置。

    *(char_ptr+1) = 'h';

使用此命令,您“获取” _ptr 的地址,左 1 字节(从 0 开始计数),并将字符“h”分配给该位置,并覆盖 4 字节大小的 _ptr(32 位 cpu )。这使得结果“cxxx”变为“chxx” - xxx 代表随机字节。

*(char_ptr+2) = '\0';

这里也一样:你“获取”_ptr 的地址,然后向右跳 2 个字节(从 0 开始计数),并将字符 'h' 分配到这个位置,并覆盖 4 字节大小的 _ptr 的内容(32-位CPU)。这使得结果“chxx”变为“ch\0x”。这意味着,您形成了一个文字/字符串,即以空字符结尾的字符表示,用于将字符串标记为在该位置结束。

printf("char_ptr as string = %s\n", char_ptr);

这会在屏幕上的内存地址打印 char_ptr 中的 _ptr(字符串)值。因为你有文字“ch\0x”;您将看到提供了命令序列 \n 的字符串“ch”,并以“换行符”作为结果开始。

于 2021-09-09T09:26:15.087 回答