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
对字符串相同类型的结构,即使语法必须略有不同。