理解C中的指针

时间:2012-04-17 08:12:29

标签: c pointers

我正在尝试学习C中的指针,但却与以下概念混淆:

char *string = "hello"
char *string2;

之间的主要区别是:

A.) *string2 = string;

然后

B.) string2 = "bye";

6 个答案:

答案 0 :(得分:8)

有些照片可能会有所帮助。

假设以下内存映射(地址完全是任意的,并且不反映任何已知的体系结构):

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这样的指针表达式计算为字符串文字的地址)作为scanfstrtokfgets等函数的参数传递等等。

string是指向char的指针,包含字符串文字"hello"的地址。 string2也是指向char的指针,其值不确定(0x??表示未知字节值)。

写作时

string2 = "bye";

您将"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;

这里有几个问题。

首先,C中的题外话 - 声明以表达式的类型为中心,而不是对象。 string2是指向角色的指针;要访问字符值,我们必须使用一元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,那么您会遇到上述问题;您正在尝试修改字符串文字的内容。同样,这是一个直到运行时才会出现的问题。

答案 1 :(得分:3)

其他回答者有一些微妙的推论,错过了新手的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指向的字符更改为charh

不可否认,这是一个有点令人困惑的主题,所有 C程序员都会经历一些痛苦的学习。 指针声明语法与声明中的相同文本具有稍微不同(虽然相关)的效果。获得更多练习并体验编写和编译涉及指针的表达式,最终我的单词将非常有意义。< / p>

答案 2 :(得分:0)

编辑后:

不同之处在于A)不会编译,如果确实如此,则是未定义的行为,因为您正在取消引用未初始化的指针。

此外,发布后请不要大幅改变您的问题。

答案 3 :(得分:0)

*string可以理解为“string指向的任何内容”,即char。将"bye"分配给它是没有意义的。

答案 4 :(得分:0)

C字符串只是一个字符数组。上面的"hello"之类的C字符串文字可以被视为“返回”指向字符数组的第一个元素{ 'h', 'e', 'l', 'l', 'o' }的指针。

因此,char *string = "bye"有意义而char string = "bye"没有。

答案 5 :(得分:0)

char *是指向角色的指针。 "hello"之类的文字返回指向字符串第一个字符的指针。因此,string = "bye"有意义,使string指向字符串"bye"的第一个字符。

另一方面,

*string string指向的字符。它不是指针而是8位整数。这就是为什么赋值*string = "bye"没有意义,并且可能会导致分段错误,因为"bye"存储的内存段是只读的。