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

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

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

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

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

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

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

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

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

第一:

 char a[]="aesdf"; 

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

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

下一个:

 char *b="asdf"; 

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

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

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

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

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

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

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

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