数组初始化之间的差异

时间:2010-08-06 20:54:59

标签: c++ c

请参阅以下声明:

char a[5]="jgkl"; // let's call this Statement A
char *b="jhdfjnfnsfnnkjdf"; // let's call this Statement B , and yes i know this is not an Array
char c[5]={'j','g','k','l','\0'}; // let's call this Statement C

现在,陈述A和C之间有什么区别吗? 我的意思是两个都应该在Stack上吗?只有b将位于静态位置。


所以不会让“jgkl”存在于程序的整个生命周期的静态位置吗?既然它应该是只读/常数? 请澄清。

5 个答案:

答案 0 :(得分:5)

不,因为语句A中的字符“jgkl”用于初始化a,它不会在可执行文件中为字符串创建存储(除了您创建的存储之外)通过声明a)。此声明在读写内存中创建一个包含字节{'j','g','k','l','\0'}的字符数组,但用于初始化它的字符串在可执行结果中不存在。

在语句B中,字符串文字的地址用作初始化程序。变量char *b是存储在读写存储器中的指针。它指向字符串"jhdfjnfnsfnnkjdf"。此字符串存在于可执行映像中通常称为“.sdata”的段中,表示“静态数据”。该字符串通常存储在只读存储器中,如C标准所允许的那样。

这是声明一个字符数组和一个字符串常量之间的一个关键区别:即使你有一个指向字符串常量的指针,你也不应该修改内容。

在初始化时,根据ANSI C标准第6.5.7节,尝试修改字符串常量是“未定义的行为”。

答案 1 :(得分:2)

如果[]是静态的那么c [] - 两者是等价的,也不是字符串文字。这两个同样可以被声明,以便它们在堆栈中 - 它取决于它们的声明位置和方式,而不是用于指定其内容的语法。

答案 2 :(得分:2)

值“jgkl”可能永远不会加载到工作内存中。在调用main之前,运行一个函数(通常称为cinit)。此函数执行的操作之一是初始化静态和文件范围变量。在我使用的DSP编译器上,初始值存储在一个表中,该表是程序映像的一部分。表格的格式与正在初始化的变量的格式无关。初始化程序表仍然是程序映像的一部分,永远不会复制到RAM。简单地说,内存中无处可以访问“jgkl”。

a这样的小字符串可能根本不存储在该表中。优化器可以将其减少到等效(伪指令)store reg const(152<<24|167<<16|153<<8|154)

我怀疑大多数编译器是相似的。

答案 3 :(得分:1)

A和C完全相同。 A中使用的语法是C语法的缩写。

名为ac的每个对象都是长度为5的字节数组,存储在内存中的某个位置,该位置在执行期间是固定的。程序可以随时更改元素字节。编译器负责决定如何初始化对象。编译器可能生成类似于a[0] = 'j'; a[1] = 'g'; ...的东西,或类似于memcpy(a, static_read_only_initialization_data[1729], 5)的东西,或者它选择的任何东西。如果声明发生在函数中,则数组位于(概念)堆栈上;如果声明发生在文件范围内,则数组位于全局可写内存中。

名为b的对象是指向字节的指针。它的初始值是一个指向字符串文字内存的指针,它在许多具有只读内存的实现上是只读的,但不是全部。 b的值可能会更改(例如,指向不同的字符串,或指向NULL)。该程序不允许更改jhdfjnfnsfnnkjdf"的内容,尽管通常在C中实现可能不会强制执行此操作。

答案 4 :(得分:0)

C-Literals始终是只读的。

  • a)分配5个字节的内存并存储 来自文字的内容包括'\ 0'在里面
  • b)分配sizeof(size_t)个字节 内存并将文字地址存储在其中
  • c)分配5个字节的内存和 将5个字符值存储在其中