在C语言中,printf(“Hello”)如何输出;“大提琴”;在任何情况下?
它完全想念我怎么能在C语言中,printf(“Hello”)如何输出;“大提琴”;在任何情况下?,c,string,C,String,它完全想念我怎么能printf(“Hello”)打印Cello。这挑战了我对C的基本理解。但是从下面关于堆栈溢出的问题的最上面的答案(由Carson Myers)来看,这似乎是可能的。你能简单地解释一下这是怎么可能的吗?答案是这样的: 无论何时在源代码中写入字符串,该字符串都是只读的 (否则,您可能会更改 可执行文件——想象一下,如果您编写了char*a=“hello”,然后进行了更改 a[0]到“c”。然后其他地方写了printf(“你好”);。如果你是 允许更改“hello”的第一个字符和编
printf(“Hello”)
打印Cello
。这挑战了我对C的基本理解。但是从下面关于堆栈溢出的问题的最上面的答案(由Carson Myers)来看,这似乎是可能的。你能简单地解释一下这是怎么可能的吗?答案是这样的:
无论何时在源代码中写入字符串,该字符串都是只读的
(否则,您可能会更改
可执行文件——想象一下,如果您编写了char*a=“hello”,然后进行了更改
a[0]到“c”。然后其他地方写了printf(“你好”);。如果你是
允许更改“hello”的第一个字符和编译器
只存储一次(应该),然后printf(“hello”);将输出
大提琴
前面提到的问题:a指向的“Hello”与您传递给printf的“Hello”不同。(系统中有2个“hello”) 如果您要求printf在a处打印字符串,它将起作用 原因:
char*a=“hello”中的字符串文本
和在printf(“hello”)
中可以位于同一个内存位置a
引用的字符串时,printf
的值也会更改这是一个实用的解释(即不受C语言标准的约束): 首先,在代码中的某个地方声明
char*a=“hello”
因此,编译器:
- 生成一个常量字符串
,并将其放置在可执行映像中的只读内存部分(通常在RO数据部分中),但前提是它尚未执行此操作“hello”
- 将
替换为char*a=“hello”
char*a=内存中“hello”的地址
printf(“hello”)
因此,编译器:
- 生成一个常量字符串
,并将其放置在可执行映像中的只读内存部分(通常在RO数据部分中),但前提是它尚未执行此操作“hello”
- 将
替换为printf(“hello”)
printf(内存中“hello”的地址)
“hello”
中的任何字符,那么它将影响任何引用位于内存中该字符串地址的数据的结果
实际上,由于编译器将所有常量字符串放在只读内存段中,因此这是不可行的。如果您在源代码中的某个位置具有字符串文字“Hello”,则该字符串最终作为代码/数据段的一部分出现在可执行文件中。这在任何时候都应该被认为是只读的,因为编译器可以自由地将同一文本的多次出现优化为单个实体。您的源代码中可能有多个“Hello”,以及多个指向它们的指针,但它们可能都指向同一个地址 ISO/IEC 9899“编程语言-C”,第6.4.5章“字符串文字”,第6段: 如果这些数组的元素具有 适当的值。如果程序试图修改这样的数组,则该行为是 未定义 因此,任何指向此类字符串文字的指针都将被声明为指向常量内容的指针,以在源代码级别明确这一点:
char const * a = "Hello";
根据这个定义,a[0]=“C”代码>不是有效的操作:无法更改常量值,编译器将发出错误
然而,有多种方式可以“欺骗”语言。首先,您可以投射指针:
char const * a = "Hello";
char * b = (char *)a;
b[0] = 'C';
正如上述标准中的代码片段所述,这虽然在语法上是正确的,但在语义上是未定义的行为。它甚至可能在某些平台上“正确”工作(主要是出于历史原因),并实际打印“大提琴”。这可能会影响到其他人
考虑一下,如果您的可执行文件被烧录到ROM芯片中,并从那里执行,会发生什么
我说的是“历史原因”。开始时,没有常量
。这就是为什么C将字符串文本的类型定义为char[]
(noconst
)
请注意:
- C++98将字符串文本定义为
const
,但允许转换为char*
- C++03仍然允许转换,但不支持转换
- C++11不再允许在没有强制转换的情况下进行转换
你理解错了。答案基本上是:如果可以修改字符串文字,printf(“Hello”)
将输出Cello
,这显然不是人们所期望的。如果,你自己试过吗?在我演示和运行C应用程序的近100次中,我从来没有得到过大提琴!!!你收到这个问题了吗?还是你在问它是否会发生?因为在第一种情况下,那是。。。非常奇怪,在第二种情况下,你引用的答案并没有说它发生了——它实际上是在讨论为什么它没有发生。请写const
char
,请。。。这正是这种邪恶的根源所在:太懒了,无法正确地限定字符串文本const
…编译器通常只存储一个相同字符串文本的副本,这与