#include<stdio.h>
#include<string.h>
int main()
{
char a[]="aaa";
char *b="bbb";
strcpy(a,"cc");
printf("%s",a);
strcpy(b,"dd");
printf("%s",b);
return 0;
}
我们无法修改数组的内容,但上述程序没有显示任何编译时错误。运行时打印cc并终止。我认为数组的内容将存储在数据段的只读段中,因此不可能将数组的值更改为const.But在上面的程序中,值已更改为cc和程序终于。价值在这里改变了为什么会这样。请帮助我理解。
答案 0 :(得分:3)
Array不是常量数据类型,而是像“aaa”这样的文字字符串。你不能修改它的内容。
答案 1 :(得分:1)
您的程序中有多个数组。其中一些是可修改的,另一些则不是。那么,你原来的问题(“是数组const数据类型吗?”)并没有真正以任何有意义的方式回答。
字符串文字(如"aaa"
)是数组,但它们不可修改。请注意,在C语言中,字符串文字实际上不是const
(例如数组"aaa"
,类型为char[4]
,而不是const char[4]
)。但是,语言仍然明确禁止尝试修改字符串文字。编译器不需要捕获此类尝试。此外,当您进行此类尝试时,不会发生运行时错误。行为只是 undefined 。当您执行strcpy(b,"dd")
时,您尝试修改不可修改的数组 - 行为未定义。任何事情都可能发生。
对于代码示例中的普通数组a
,它被声明为可修改的。因此,您可以根据需要进行修改。执行strcpy(a, "cc")
后,将字符串"cc"
复制到数组a
中。那么,这正是您在实验中观察到的a
内容。这里没什么不寻常的。
答案 2 :(得分:1)
char* != char[]
!
在这种情况下,a
是可写区域的缓冲区,该区域首先填充文字字符串的内容,该字符串存储在只读区域中,而b
是指针它直接指向只读区域!以下是帮助您了解的示例代码:
#include <stdio.h>
#include <string.h>
#define literal "test"
int main() {
char a[] = literal
char b[] = literal;
char* c = literal;
char* d = literal;
printf("%s (%p)\n", a, a);
printf("%s (%p)\n", b, b);
printf("%s (%p)\n", c, c);
printf("%s (%p)\n", d, d);
return 42;
}
通过执行此代码,您将看到即使打印的所有4个字符串相同,a
和b
也会解决内存中的不同区域,而c
和{{1指向一个独特的第三区域地址。此外,您应该看到前两个和最后一个之间的地址范围有很大差异:这里,内存的不同区域(读/写和只读)中的位置显而易见。
修改:只是为了坚持,第五个printf(d
)打印的内容与printf("%s (%p)\n", literal, literal);
和c
行相同。
答案 3 :(得分:1)
这是一个假设的内存映射,显示字符串文字,数组和指针是如何相互关联的:
Item Address 0x00 0x01 0x02 0x03 ---- ------- ---- ---- ---- ---- "aaa" 0x00040000 'a' 'a' 'a' 0x00 "bbb" 0x00040004 'b' 'b' 'b' 0x00 "cc" 0x00040008 'c' 'c' 0x00 ??? "dd" 0x0004000C 'd' 'd' 0x00 ??? ... a 0x08000000 'a' 'a' 'a' 0x00 b 0x08000004 0x00 0x04 0x00 0x00
在声明并初始化a
和b
之后,代码中第6行的情况就是如此。字符串文字"aaa"
,"bbb"
,"cc"
和"dd"
都驻留在内存中的某个位置,以便它们在程序的生命周期内存在。它们存储为char
(const char
在C ++中的数组)。试图修改字符串文字的内容(在这个假设的情况下,尝试写入以0x0004开头的任何内存位置)调用未定义的行为。有些平台将字符串文字存储在只读内存中,有些平台将它们存储在可写内存中,但在所有情况下,应该将它们视为,就好像它们是不可写的一样。
对象a
是char
的数组,并且已使用字符串文字"aaa"
的内容进行初始化。对象b
是指向char
的指针,它已使用字符串文字"bbb"
的地址进行初始化。在行
strcpy(a, "cc");
您正在将字符串文字"cc"
的内容复制到a
;在执行该行之后,您的内存映射如下所示:
Item Address 0x00 0x01 0x02 0x03 ---- ------- ---- ---- ---- ---- "aaa" 0x00040000 'a' 'a' 'a' 0x00 "bbb" 0x00040004 'b' 'b' 'b' 0x00 "cc" 0x00040008 'c' 'c' 0x00 ??? "dd" 0x0004000C 'd' 'd' 0x00 ??? ... a 0x08000000 'c' 'c' 0x00 0x00 b 0x08000004 0x00 0x04 0x00 0x00
因此,当您将a
打印到标准输出时,您应该会看到字符串cc
。注意:printf
是缓冲的,因此输出可能不会立即写入终端 - 在格式字符串(printf("%s\n", a);
)中添加换行符或在{之后调用fflush(stdout);
{1}}确保所有输出都显示出来。
在第9行中,您尝试将字符串文字printf
的内容复制到"dd"
指向的位置;不幸的是,b
指向另一个字符串文字,如上所述调用未定义的行为。在这一点上,你的程序可以完全做任何事情,从预期的运行到直接崩溃到两者之间的任何事情。这可能是您只看到b
输出的部分原因。
答案 4 :(得分:0)
数组不是const数据类型,但文字是。字符串文字“aaa”和“bbb”无法修改(或者可以修改,但结果未定义)。
正如Paul R所指出的,char a[] = "aaa";
很好,因为它将使用字符串文字初始化一个数组(正如我所提到的那样,它不是const数据类型)。这是问题char *b = "bbb";
,因为您稍后会尝试修改字符串文字本身的内容,而不是副本。
答案 5 :(得分:0)
b
指向一个字符串bbb
,该字符串存储在只读内存中。strcpy()
或其他内容无法更改。