我正在尝试学习 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 字符串2 0x80FF0004 0x?? 0x?? 0x?? 0x??
这显示了声明后的情况。 "hello"
并且"bye"
是字符串文字,存储为char
内存中“某处”的数组,以便它们在程序的生命周期内可用。请注意,尝试修改字符串文字的内容会调用未定义的行为;您不想将字符串文字(或类似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 字符串2 0x80FF0004 0x00 0x50 0x12 0x3A
看起来很简单,对吧?
现在让我们看一下声明
*string2 = string;
这里有几个问题。
首先,题外话 - C 中的声明以表达式的类型为中心,而不是对象。 string2
是指向字符的指针;要访问字符值,我们必须使用一元运算符取消引用 :string2
*
char x = *string2;
表达式 的类型*string2
是char
,所以声明变成
char *string2;
通过扩展,表达式 string2
的类型是char *
,或指向 的指针char
。
所以当你写
*string2 = string;
您正在尝试将 ( ) 类型的值分配给( char *
)类型string
的表达式。那是行不通的,因为and不是兼容的类型。此错误出现在翻译(编译)时。如果你写过char
*string2
char *
char
*string2 = *string;
那么两个表达式都有 type char
,并且赋值是合法的。
但是,如果您还没有分配任何东西string2
,它的值是不确定的;它包含一个随机位串,该位串可能对应于一个有效的可写地址,也可能不对应。尝试服从随机的、可能无效的指针值会调用未定义的行为;它可能看起来工作正常,它可能会彻底崩溃,它可能会在两者之间做任何事情。这个问题直到运行时才会出现。更好的是,如果您将字符串文字分配"bye"
给string2
,那么您会遇到上述问题;您正在尝试修改字符串文字的内容。同样,这是一个直到运行时才会出现的问题。
其他回答者做出了一些微妙的推论,错过了新手的 POV。
char *string = "hello";
声明一个指针变量,该变量被初始化为指向一个字符数组(传统上很好的类型匹配)。
该声明
*string = "hello";
取消引用应该是指针变量的内容并将值分配给指向的位置。(它不是一个变量声明;必须在它上面的某个地方完成。)但是,因为string
有类型——char *
所以*string
有类型char
——并且赋值的右侧是一个带有指针值的表达式,所以存在类型不匹配。这可以通过两种方式解决,具体取决于语句的意图:
string = "hello"; /* with "char *" expressions on both sides */
或者
*string = 'h'; /* with "char" expressions on both sides */
第一个重新分配string
以指向包含一系列字符 ( hello\000
) 的内存。第二个赋值将 指向的字符更改string
为char
value h
。
诚然,这是一个稍微令人困惑的主题,所有 C
程序员在学习掌握时都会经历一些痛苦。 指针声明语法与语句中的相同文本的效果略有不同(尽管相关)。 获得更多的练习和经验,编写和编译涉及指针的表达式,最终我的话会变得完全有意义。
AC字符串只是一个字符数组。像上面这样的 C 字符串文字"hello"
可以被视为“返回”指向字符数组第一个元素的指针,{ 'h', 'e', 'l', 'l', 'o' }
.
因此,char *string = "bye"
有意义而char string = "bye"
没有意义。
编辑后:
不同之处在于 A) 不会编译,如果编译,它是未定义的行为,因为您取消引用未初始化的指针。
另外,请不要在发布后大幅更改您的问题。
*string
可以读作“任何string
指向”,即char
. 分配"bye"
给它没有意义。
char *
是指向字符的指针。诸如此类"hello"
的文字返回指向字符串第一个字符的指针。因此, 指向 string 的第一个字符string = "bye"
是有意义的。string
"bye"
*string
另一方面, 是所指向的字符string
。它不是一个指针,而是一个 8 位整数。这就是为什么分配*string = "bye"
没有意义并且可能会导致分段错误,因为存储的内存段"bye"
是只读的。