2012-04-17 77 views
0

我想学习C指针,但得到夹杂了以下概念:理解指针

char *string = "hello" 
char *string2; 

之间的主要区别是什么:

A.) *string2 = string; 

然后

B.) string2 = "bye"; 
+0

第二个错误。与指针无关,类型不匹配。 – littleadv 2012-04-17 08:14:19

+1

那么,只要你学习指针,你可能会看到它:http://cslibrary.stanford.edu/104/ – dranxo 2012-04-17 08:28:34

+0

@diesel:我的答案(下面)更适用于编辑前提出的问题,但我因为它涵盖了现在被问得相当简洁的概念。 – wallyk 2012-04-17 08:32:20

回答

0

编辑后:

不同之处在于A)不会编译,如果是这样的话,那么它是未定义的行为,因为您要解引用未初始化的指针。

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

+0

@SteveJessop谢谢你。 – 2012-04-17 08:32:55

0

*string可以理解为“无论string指向”,这是一个char。将"bye"分配给它是没有意义的。

0

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

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

0

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

*string,在另一方面,是字符通过string指出。它不是一个指针,而是一个8位整数。这就是为什么赋值*string = "bye"没有意义,并且可能导致段错误,因为"bye"存储的内存段是只读的。

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程序员经历了一点点痛苦学习掌握。 指针声明语法与语句中的相同文本略有不同(但相关)的效果。获得更多的练习和体验写作和编译涉及指针的表达式,最终我的话将是完美的。

7

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

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

 
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)字符串文字作为参数传递给函数一样scanfstrtokfgets

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; 

的类型表达*string2char,所以声明变得

char *string2; 

通过扩展, 表达式的类型string2char *或指向char的指针。

所以,当你写

*string2 = string; 

你试图型char *string)的值赋给char类型(*string2)的表达。这是行不通的,因为char *char是不兼容的类型。这个错误出现在翻译(编译)时间。如果你写了

*string2 = *string; 

那么这两个表达式的类型都是char,而赋值是合法的。

但是,如果您还没有为string2分配任何东西,它的值是不确定的;它包含一个随机位串,它可能对应或不对应有效的可写地址。试图推断随机的,可能无效的指针值会引发未定义的行为;它可能看起来工作正常,它可能会崩溃,它可能会做任何事情之间。这个问题直到运行时才会显示出来。更好的是,如果您将字符串文字"bye"指定为string2,则会遇到上述问题;你试图修改字符串文字的内容。再次,这是一个问题,直到运行时才会显示出来。