为什么要编译?(无符号字符 *事物 = (无符号字符 *) "YELLOW SUBMARINE" ;)

Why does this compile? (unsigned char *thing = (unsigned char *) "YELLOW SUBMARINE";)

本文关键字:字符 无符号 YELLOW SUBMARINE 为什么 事物 编译      更新时间:2023-10-16

我正在努力理解为什么这行代码有意义:

unsigned char *thing = (unsigned char *)"YELLOW SUBMARINE";

unsigned char保存一个字节的数据(即"Y"),因此unsigned char*应该是指向该单个数据字节的指针。

如果我试图在里面放多个字符,在我看来,编译器应该生气。然而,我不介意我在这里放置 16 个字节并告诉编译器我只指向一个unsigned char。有人可以解释一下吗?

我的想法是编译器会为一个unsigned char分配内存,然后将整个字符串写入其中,覆盖相邻内存并造成严重破坏。但是,我稍后能够正确取消引用此指针并检索整个字符串,因此似乎没有问题。

上下文:我正在尝试将字符串转换为这种形式(unsigned char *)。

提前感谢!

首先,如果 C++ 中的指针类型是unsigned char *基本上只告诉编译器以下事情:

  • 取消引用指针时,编译器应该只从内存中读取一个字节,我们将该字节视为 0 到 255 之间的数字。 (如果您的系统非常不寻常,那么这些规则可能会有所不同。
  • 执行指针加法和减法时,指针指向的元素的大小为 1(或系统上的任何sizeof(unsigned char))。

如果您查找严格混叠和内存对齐的概念,指针的类型也会产生一些微妙的影响,但我不想详细介绍这一点。

接下来,指针的类型不会告知编译器指针是否具有可以取消引用的有效值。 指针可能未初始化。 它可能指向之前释放的内存。 它可能为空。 它可能指向数组的最后一个元素(标准明确允许的内容)。

指针的类型不会告诉编译器内存的整个布局。 您可以定义一个字符串,然后定义指向开头中间、结尾或超过结尾的指针,所有这些都是具有相同类型的有效指针。 C++中基本指针的类型系统根本不够复杂,无法对此类信息进行编码,因为这不是语言的设计方式。

const char * p = "James";  // valid pointer to the beginning of a string
const char * p1 = p + 1;   // pointer to 'a'
const char * p5 = p + 5;   // pointer to the null terminator (0) after 's'
const char * p6 = p + 6;   // pointer to the memory directly after the terminator

最后,您提供的代码中有一个强制转换,它允许您执行几乎任何您想要的转换,而无需编译器进行太多检查。 因此,当编译器允许您将一件事转换为另一件事时,您不应该感到惊讶。

我的想法是编译器会为一个...

如果我尝试在里面放多个字符..

实际上,你没有在里面放任何东西。这不是创造新的"字符串"来容纳"黄色潜艇"。你只是指向存储在静态内存中的字符串的开头。