理解C中的指针
我正在尝试学习C中的指针,但是它与以下概念混淆:
char *string = "hello" char *string2;
有什么区别:
A.) *string2 = string;
然后
B.) string2 = "bye";
一些图片可能有帮助。
假设以下内存映射(地址完全是任意的,并不反映任何已知的体系结构):
项目地址0x00 0x01 0x02 0x03 ---- ------- ---- ---- ---- ---- “你好”0x00501234'h''e''l''l' 0x00501238'o'0x00 “再见”0x0050123A'b''y' 0x0050123C'e'0x00 0x ?? 0X? ... 字符串0x80FF0000 0x00 0x50 0x12 0x34 string2 0x80FF0004 0x ?? 0X? 0X? 0X?
这显示了声明后的情况。 "hello"
和"bye"
是字符串文字,在内存中存储为char
“somewhere”的数组,以便它们在程序的生命周期内可用。 请注意,尝试修改字符串文字的内容会调用未定义的行为; 你不想传递字符串文字(或像string
那样计算字符串文字地址的指针表达式)作为scanf
, strtok
, fgets
等函数的参数。
string
是指向char
的指针,包含字符串文字"hello"
的地址。 string2
也是一个指向char
的指针,它的值是不确定的( 0x??
代表一个未知的字节值)。
当你写作
string2 = "bye";
你将"bye"
(0x0050123A)的地址分配给string2
,所以我们的内存映射现在看起来像这样:
项目地址0x00 0x01 0x02 0x03 ---- ------- ---- ---- ---- ---- “你好”0x00501234'h''e''l''l' 0x00501238'o'0x00 “再见”0x0050123A'b''y' 0x0050123C'e'0x00 0x ?? 0X? ... 字符串0x80FF0000 0x00 0x50 0x12 0x34 string2 0x80FF0004 0x00 0x50 0x12 0x3A
看起来很简单吧?
现在让我们来看看声明
*string2 = string;
这里有几个问题。
首先,C中的题外话 – 声明以表达式的类型为中心,而不是对象。 string2
是一个指向字符的指针; 要访问字符值,我们必须使用unary *
运算符取消引用 string2
:
char x = *string2;
表达式 *string2
的类型是char
,因此声明变为
char *string2;
通过扩展, 表达式 string2
的类型是char *
,或指向char
指针。
所以当你写作
*string2 = string;
您正在尝试将char *
( string
)类型的值赋给char
( *string2
)类型的表达式。 这不会起作用,因为char *
和char
不是兼容的类型。 此错误显示在转换(编译)时。 如果你写过
*string2 = *string;
然后两个表达式都有char
类型,并且赋值是合法的。
但是,如果尚未向string2
分配任何内容,则其值不确定; 它包含一个随机位字符串,可能对应于有效的可写地址,也可能不对应。 尝试遵循随机的,可能无效的指针值会调用未定义的行为; 它似乎工作正常,它可能彻底崩溃,它可能在两者之间做任何事情。 直到运行时才会显示此问题。 更好的是,如果你将字符串文字"bye"
分配给string2
,那么你会遇到上述问题; 您正在尝试修改字符串文字的内容。 同样,这是一个直到运行时才会出现的问题。
其他回答者做出了一些微妙的推论,错过了新手的POV。
char *string = "hello";
声明一个指针变量,它被初始化为指向一个字符数组(传统上一个好的类型匹配)。
该声明
*string = "hello";
取消引用应该是指针变量的内容并为指向的位置赋值。 (它不是变量声明;必须在某处完成。)但是,因为string
类型为char *
-so *string
类型为char
,而赋值的右侧是带有指针值的表达式,是一种类型不匹配。 这可以通过两种方式修复,具体取决于语句的意图:
string = "hello"; /* with "char *" expressions on both sides */
要么
*string = 'h'; /* with "char" expressions on both sides */
第一个重新指定string
以指向包含一系列字符的内存( hello\000
)。 第二个赋值将字符串指向的字符更改为char
值h
。
不可否认,这是一个有点令人困惑的主题, 所有 C
程序员都会经历一些有点痛苦的学习。 指针声明语法与语句中的相同文本具有略微不同(但相关)的效果。 获得更多的练习和经验,编写和编写涉及指针的表达式,最终我的话语将非常有意义。
*string
可以读作“任何string
指向”,这是一个char
。 为它分配"bye"
是没有意义的。
AC字符串只是一个字符数组。 上面的"hello"
类的C字符串文字可以被视为“返回”指向字符数组的第一个元素的指针, { 'h', 'e', 'l', 'l', 'o' }
。
因此, char *string = "bye"
是有意义的,而char string = "bye"
则没有。
char *
是指向字符的指针。 诸如"hello"
之类的文字返回指向字符串第一个字符的指针。 因此, string = "bye"
是有意义的,使string
指向字符串"bye"
的第一个字符。
另一方面, string
是string
指向的string
。 它不是指针而是8位整数。 这就是为什么赋值*string = "bye"
没有意义,并且可能会导致分段错误,因为"bye"
存储的内存段是只读的。
编辑后:
不同之处在于A)不会编译,如果确实如此,则它是未定义的行为 ,因为您正在取消引用未初始化的指针。
此外,发布后请不要大幅改变您的问题。