字符串初始化程序和只读部分

时间:2010-08-07 03:55:11

标签: c++ c arrays

假设我有一个数组(函数的本地)和指针

char a[]="aesdf"char *b="asdf"

我的问题是,在前一种情况下,字符串文字"aesdf"是存储在只读部分中,然后复制到本地数组还是类似于

char a[]={'a','e','s','d','f','\0'};

我认为在这种情况下,字符直接在堆栈上创建,但在前面的情况下(char a[]="aesdf"),字符将从只读部分复制到本地数组。

在可执行文件的整个生命周期中是否存在“aesdf”?

4 个答案:

答案 0 :(得分:5)

从抽象和形式的角度来看,每个字符串文字都是一个具有静态存储持续时间的独立无名对象。这意味着,初始化char a[] = "aesdf"正式创建了文本对象"aesdf",然后使用它初始化独立数组a,即它不等同于char *a = "aesdf",其中一个指针使其直接指向字符串文字。

但是,由于字符串文字是无名对象,因此在char a[] = "aesdf"变体中,无法在初始化之前或之后访问独立的"aesdf"对象。这意味着您无法“检测”此对象是否确实存在。该对象的存在(或不存在)不会影响程序的可观察行为。出于这个原因,实现可以自由地消除独立的"aesdf"对象,并以任何其他方式初始化a数组,从而产生预期的正确结果,即char a[] = { 'a', 'e', 's', 'd', 'f', '\0' }char a[] = { 'a', 'e', "sdf" }或其他内容。

答案 1 :(得分:2)

首先:

char a[]="aesdf";

假设这是一个自动局部变量,它将在堆栈上分配6个字节并使用给定的字符初始化它们。它是如何做到的(无论是通过字符串文字中的memcpy还是一次使用内联存储指令加载一个字节,或者其他方式)都是完全实现定义的。请注意,每次变量进入范围时都必须进行初始化,因此如果它不会改变,那么这是一个非常浪费的构造。

如果这是一个静态/全局变量,它将产生一个6字节的字符串数组,其中包含唯一的地址/存储,其初始内容是给定的字符,并且是可写的。

下一步:

char *b="asdf";

这会将指针b初始化为指向字符串文字"asdf",它可能会或可能不会与其他字符串文字共享存储,如果您写入它会产生未定义的行为。

答案 2 :(得分:0)

a [] =“aesdf”和char a [] = {'a','e','s','d','f','\ 0'}都将存储在函数的运行时间中函数返回时将释放堆栈和内存。但是对于char * b =“asdf”,asdf存储在readonly节中,并从那里引用。

答案 3 :(得分:0)

char a[] = "aesdf";
char a[] = {'a','e','s','d','f','\0'};

这两行代码具有相同的效果。编译器可以选择以相同的方式实现它们,或者它可以选择以不同的方式实现它们。

从程序员用C编写代码的角度来看,这应该不重要。您可以使用其中之一,并确保最终得到初始化为指定内容的六元素数组char

  

可执行文件的整个生命周期中是否存在"aesdf"

从语义上讲,是的。字符串文字是具有静态存储持续时间char个数组。具有静态存储持续时间的对象具有执行程序的生命周期:它在程序启动之前初始化,并且一直存在直到程序终止。

但是,这在你的程序中根本不重要。该字符串文字用于初始化数组a。由于您没有获得指向字符串文字本身的指针,因此该字符串文字的实际生命周期或实际存储方式无关紧要。只要数组a被正确初始化,编译器就可以做任何它认为合适的事情。