繁体   English   中英

数组初始化之间的差异

[英]Difference between Array initializations

请参阅以下声明:

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”存在于静态位置吗? 既然它应该是只读/常数? 请澄清。

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

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

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

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

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

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

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

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

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

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

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

C-Literals始终是只读的。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM