数组是const数据类型

时间:2011-09-15 16:26:05

标签: c

#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和程序终于。价值在这里改变了为什么会这样。请帮助我理解。

6 个答案:

答案 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个字符串相同,ab也会解决内存中的不同区域,而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

在声明并初始化ab之后,代码中第6行的情况就是如此。字符串文字"aaa""bbb""cc""dd"都驻留在内存中的某个位置,以便它们在程序的生命周期内存在。它们存储为charconst char在C ++中的数组)。试图修改字符串文字的内容(在这个假设的情况下,尝试写入以0x0004开头的任何内存位置)调用未定义的行为。有些平台将字符串文字存储在只读内存中,有些平台将它们存储在可写内存中,但在所有情况下,应该将它们视为,就好像它们是不可写的一样。

对象achar的数组,并且已使用字符串文字"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()或其他内容无法更改。