C:分配给指针时数组的行为

#include  main() { char * ptr; ptr = "hello"; printf("%p %s" ,"hello",ptr ); getchar(); } 

嗨,我试图清楚地理解如何将数组分配给指针。 当你将一个字符数组分配给chars ptr="hello";的指针时,我会注意到ptr="hello"; 数组衰减到指针,但在这种情况下,我分配一个不在变量内的数组的字符,而不是包含它们的变量“,这种赋值方式是否专门为"Hello"采用内存地址(显然是发生),是否可以修改存储该数组的内存地址中包含的“Hello”中每个元素的值。作为比较,我可以分配一个带有数组的指针,例如像int_ptr = 5,3,4,3;这样含糊不清的东西int_ptr = 5,3,4,3;并且值5,3,4,3位于内存地址中,就像“Hello”一样。如果不是,为什么只能用字符串?谢谢在先进。

"hello"是一个字符串文字。 它是char [6]类型的无名不可修改对象。 它是一个数组,其行为与任何其他数组的行为相同。 它无名的事实并没有真正改变任何事情。 您可以将它与[]运算符一起使用,例如"hello"[3]等。 就像任何其他数组一样,它可以并且会在大多数情况下衰减到指针。

您无法修改字符串文字的内容,因为它根据定义是不可修改的。 它可以物理存储在只读存储器中。 如果它们包含公共的字符子序列,它可以与其他字符串文字重叠。

通过复合文字语法存在其他数组类型的类似function

 int *p = (int []) { 1, 2, 3, 4, 5 }; 

在这种情况下,右侧是int [5]类型的无名对象,它衰减为int *指针。 复合文字是可修改的,这意味着你可以执行p[3] = 8 ,从而将4替换为8

您还可以将复合文字语法与char数组一起使用

 char *p = (char []) { "hello" }; 

在这种情况下,右侧是char [6]类型的可修改无名对象。

您应该做的第一件事是阅读comp.lang.c FAQ的第6部分。

字符串文字"hello"char[6]类型的表达式(“hello”为5个字符,终止'\0'为1个字符)。 它指的是具有静态存储持续时间的匿名数组对象,在程序启动时初始化以包含这6个字符值。

在大多数情况下,数组类型的表达式被隐式转换为指向数组第一个元素的指针; 例外是:

  • 当它是sizeof的参数时( sizeof "hello"产生6,而不是指针的大小);
  • 当它是_Alignof (C11中的一个新特征)的参数时;
  • 当它是一元&的参数时( &arr产生整个数组的地址,而不是它的第一个元素;相同的内存位置,不同的类型); 和
  • 当它是初始化器中用于初始化数组对象的字符串文字时( char s[6] = "hello";复制整个数组,而不仅仅是指针)。

这些例外都不适用于您的代码:

 char *ptr; ptr = "hello"; 

因此,表达式"hello"被转换为(“衰减”)指向我上面提到的匿名数组对象的第一个元素( 'h' )的指针。

所以*ptr == 'h' ,你可以通过内存推进ptr来访问其他字符: 'e''l''l''o''\0' 。 当你给它一个"%s"格式时,这就是printf()所做的。

与字符串文字相关联的匿名数组对象是只读的,但不是const 。 这意味着任何修改该数组或其任何元素的尝试都有未定义的行为(因为标准明确说明了这一点) – 但编译器不一定会警告你。 (C ++使字符串文字成为const ;在C中做同样的事情会破坏在将const添加到语言之前编写的现有代码。)所以不,你不能修改"hello"的元素 – 或者至少你不应该试试。 如果您尝试编译器警告您,您应该将指针声明为const

 const char *ptr; /* pointer to const char, not const pointer to char */ ptr = "hello"; 

(gcc有一个选项-Wwrite-strings ,导致它将字符串文字视为const 。这将使它警告某些C代码,就标准而言是合法的,但是这些代码应该被修改为使用const 。)

 #include  main() { char * ptr; ptr = "hello"; //instead of above tow lines you can write char *ptr = "hello" printf("%p %s" ,"hello",ptr ); getchar(); } 

在这里你已经为ptr分配了字符串文字"hello" ,这意味着字符串文字存储在只读内存中,因此你无法修改它。 如果你声明char ptr[] = "hello"; ,然后你可以修改数组。

说什么?

您的代码分配6个字节的内存,并使用值“h”,“e”,“l”,“l”,“o”和“\ 0”对其进行初始化。

然后它分配一个指针(指针的字节数取决于实现),并将指针的值设置为前面提到的5个字节的开头。

您可以使用诸如ptr[1] = 'a'语法修改数组的值。

从语法上讲,字符串是一种特殊情况。 由于C没有特定的字符串类型,它确实提供了一些快捷方式来声明它们等等。 但是您可以轻松地创建与使用int对字符串相同类型的结构,即使语法必须略有不同。