这个问题在这里已有答案:
我想了解一个指向声明和初始化的字符数组的指针的格式与选择示例char *s = "Hello";
的数组之间的区别,并让它以更常见的方式声明数组char s[] = "Hello";
我重新创建了memset并尝试在第一个声明示例中使用它,导致总线错误。我不明白为什么因为我收集到的是在C中,第一种声明和初始化数组的方法应该与它们如何存储在堆栈内存和指针上的第二种方法相同通过引用我的函数传递数组时与数组地址交互。
问题是我无法改变数组的第一个版本,但我可以使用printf打印它,因此建议改变它应该是可能的,因为它存在于内存中的某个地方并且我可以访问它的地址。
我想对两种格式的内幕情况有一个明确的解释。是什么让一个人达到了目标而另一个没有。
我的目标是尽可能多地了解C,您的帮助将使我很快欣赏语言的美丽,并清楚地了解其所有组件如何协同工作以有效地解决问题。
以下是我的代码:
与我的ft memset.c函数一起使用的格式
格式不起作用,但能够打印数组
在char *s = “Hello"
中,”Hello"
是一个字符串文字,它导致创建一个char
数组并设置为包含“Hello”和终止空字符。因为它是一个字符串文字,C的规则说你不应该试着写它。
该语句还将s
定义为指向char
的指针,并将s
初始化为指向第一个字符。
声明char s[] = “Hello”
将s
定义为char
数组,并将其初始化为包含“Hello”和终止空字符。因为这是一个普通的数组,而不是字符串文字,所以你可以写入它。 (在本声明中,”Hello”
在技术上是一个字符串文字,但它仅用于初始化数组s
,就好像通过将其内容复制到s
中一样.s
不是字符串文字并且不指向字符串文字;它是一个单独的数组。)
允许编译器将字符串文字放在任何喜欢的位置。它不必在堆栈中。因为在尝试写入时出现错误,所以编译器似乎将它放在程序的只读常量部分。
当您将s
声明为数组时,如果s
具有自动存储持续时间(在没有static
,extern
或线程存储限定符的函数内声明),编译器通常会将数组放在堆栈上。 (使用堆栈不是C的要求。某些编译器可能会将数组放在别处,但这通常只在特殊情况下才会发生,例如在非常有限的环境中进行编译时。)
尝试修改字符串文字是undefined behavior。 §6.4.5¶7(这是你在第一种情况下所做的)。
存在一个问题是某些实现是否允许您对其进行更改。 c标准不强加任何东西。它只是说修改字符串文字是未定义的行为。
从我所说的,在大多数实现中,字符串文字被放在只读部分,使它们不可修改。在你的情况下,你看到了问题 - 因为你试图修改它,导致BUS错误。 (在你的情况下,你看到了这一点)。
第一个只是一个指向字符串文字的指针 - 所以一切都说明了它。
第二个是创建一个数组并用字符串文字的内容初始化它,这是可修改的。你可以随心所欲地做任何事。 §6.7.9¶14根据您放置的位置,它可能具有静态存储持续时间或自动存储持续时间。 (静态存储持续时间 - 放置在文件范围内时,放置在块范围内时自动)。
从之前引用的标准来看 - 它来自§6.4.5¶6(关于字符串文字的存储)
然后使用多字节字符序列初始化静态存储持续时间和长度的数组,该数组足以包含序列。
链接来自C11标准N1570