假设我有一个数组(函数的本地)和指针
char a[]="aesdf"
和char *b="asdf"
我的问题是,在前一种情况下,字符串文字"aesdf"
是存储在只读部分中,然后复制到本地数组还是类似于
char a[]={'a','e','s','d','f','\0'};
?
我认为在这种情况下,字符直接在堆栈上创建,但在前面的情况下(char a[]="aesdf"
),字符将从只读部分复制到本地数组。
在可执行文件的整个生命周期中是否存在“aesdf”?
答案 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
被正确初始化,编译器就可以做任何它认为合适的事情。