我正在尝试学习C中的指针,但是它与以下概念混淆:
char *string = "hello"
char *string2;
Run Code Online (Sandbox Code Playgroud)
以下是什么主要区别:
A.) *string2 = string;
Run Code Online (Sandbox Code Playgroud)
然后
B.) string2 = "bye";
Run Code Online (Sandbox Code Playgroud)
一些图片可能有帮助.
假设以下内存映射(地址完全是任意的,并不反映任何已知的体系结构):
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
"hello" 0x00501234 'h' 'e' 'l' 'l'
0x00501238 'o' 0x00
"bye" 0x0050123A 'b' 'y'
0x0050123C 'e' 0x00 0x?? 0x??
...
string 0x80FF0000 0x00 0x50 0x12 0x34
string2 0x80FF0004 0x?? 0x?? 0x?? 0x??
这显示了声明后的情况. "hello"并且"bye"是字符串文字,存储为char内存中"某处"的数组,以便它们在程序的生命周期内可用.请注意,尝试修改字符串文字的内容会调用未定义的行为; 你不希望传递字符串(或类似指针表达式string计算结果为字符串常量的地址)作为参数传递给像功能scanf,strtok,fgets,等.
string是一个指向char,包含字符串文字的地址"hello". string2也是一个指针char,它的值是不确定的(0x??代表一个未知的字节值).
当你写作
string2 = "bye";
Run Code Online (Sandbox Code Playgroud)
你将"bye"(0x0050123A)的地址分配给string2,所以我们的内存映射现在看起来像这样:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
"hello" 0x00501234 'h' 'e' 'l' 'l'
0x00501238 'o' 0x00
"bye" 0x0050123A 'b' 'y'
0x0050123C 'e' 0x00 0x?? 0x??
...
string 0x80FF0000 0x00 0x50 0x12 0x34
string2 0x80FF0004 0x00 0x50 0x12 0x3A
看起来很简单吧?
现在让我们来看看声明
*string2 = string;
Run Code Online (Sandbox Code Playgroud)
这里有几个问题.
首先,C中的题外话 - 声明以表达式的类型为中心,而不是对象. string2是指向角色的指针; 要访问字符值,我们必须使用一元运算符取消引用 :string2*
char x = *string2;
Run Code Online (Sandbox Code Playgroud)
表达式 的类型*string2是char,因此声明变为
char *string2;
Run Code Online (Sandbox Code Playgroud)
通过扩展,表达式 的类型string2是char *或指向char.
所以当你写作
*string2 = string;
Run Code Online (Sandbox Code Playgroud)
你尝试类型的值赋给char *(string)到类型的表达式char(*string2).这不会起作用,因为char *并且char不兼容类型.此错误在转换(编译)时出现.如果你写过
*string2 = *string;
Run Code Online (Sandbox Code Playgroud)
然后两个表达式都有类型char,并且赋值是合法的.
但是,如果您还没有分配任何东西string2,它的值是不确定的; 它包含一个随机位字符串,可能对应于有效的可写地址,也可能不对应.尝试遵循随机的,可能无效的指针值会调用未定义的行为; 它似乎工作正常,它可能彻底崩溃,它可能在两者之间做任何事情.直到运行时才会出现此问题.更好的是,如果您将字符串文字分配"bye"给string2,则会遇到上述问题; 您正在尝试修改字符串文字的内容.同样,这是一个直到运行时才会出现的问题.