我想学习C指针,但得到夹杂了以下概念:理解指针
char *string = "hello"
char *string2;
之间的主要区别是什么:
A.) *string2 = string;
然后
B.) string2 = "bye";
我想学习C指针,但得到夹杂了以下概念:理解指针
char *string = "hello"
char *string2;
之间的主要区别是什么:
A.) *string2 = string;
然后
B.) string2 = "bye";
编辑后:
不同之处在于A)不会编译,如果是这样的话,那么它是未定义的行为,因为您要解引用未初始化的指针。
此外,发布后请不要急于改变您的问题。
@SteveJessop谢谢你。 – 2012-04-17 08:32:55
*string
可以理解为“无论string
指向”,这是一个char
。将"bye"
分配给它是没有意义的。
C字符串只是一个字符数组。 C字符串文字如上面的"hello"
可以被看作是“返回”指向字符数组的第一个元素{ 'h', 'e', 'l', 'l', 'o' }
的指针。
因此,char *string = "bye"
是有意义的,而char string = "bye"
没有。
char *
是指向一个字符的指针。文字如"hello"
返回一个指向字符串第一个字符的指针。因此,string = "bye"
是有意义的,使string
指向字符串"bye"
的第一个字符。
*string
,在另一方面,是字符通过string
指出。它不是一个指针,而是一个8位整数。这就是为什么赋值*string = "bye"
没有意义,并且可能导致段错误,因为"bye"
存储的内存段是只读的。
其他回答者有一些微妙的推论,错过了新手的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
值h
。
无可否认,这是一个有点令人迷惑的科目,其中全部C
程序员经历了一点点痛苦学习掌握。 指针声明语法与语句中的相同文本略有不同(但相关)的效果。获得更多的练习和体验写作和编译涉及指针的表达式,最终我的话将是完美的。
有些图片可能会有所帮助。
假定以下的存储器映射(地址是完全任意的,并不反映任何已知的体系结构):
Item Address 0x00 0x01 0x02 0x03 ---- ------- ---- ---- ---- ---- "hello" 0x005'h' 'e' 'l' 'l' 0x005'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";
你"bye"
(0x0050123A)的地址分配给string2
,所以我们的内存映射现在看起来是这样的:
Item Address 0x00 0x01 0x02 0x03 ---- ------- ---- ---- ---- ---- "hello" 0x005'h' 'e' 'l' 'l' 0x005'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
,则会遇到上述问题;你试图修改字符串文字的内容。再次,这是一个问题,直到运行时才会显示出来。
第二个错误。与指针无关,类型不匹配。 – littleadv 2012-04-17 08:14:19
那么,只要你学习指针,你可能会看到它:http://cslibrary.stanford.edu/104/ – dranxo 2012-04-17 08:28:34
@diesel:我的答案(下面)更适用于编辑前提出的问题,但我因为它涵盖了现在被问得相当简洁的概念。 – wallyk 2012-04-17 08:32:20