2011-10-04 110 views
2

我玩的指针和一个不能明白为什么这个声明是好的关于指针声明

char *ptr = "Hey" 

,但这是错误的

int *ptr = 10; 

任何一个能解释一下吗?

回答

7

正确的类比是,下面的两个是错误:

char * p = 'a'; // error 
int * q = 123; // error 

在这里,你正试图某种类型的值赋给一个变量,它是一个指针到的变量那种类型。

与此相反,以下是正确的:

int tmp_a[] = { 10, 20, 30 }; 
char tmp_b[] = { 'h', 'e', 'l', 'l', 'o', '\0' }; 

int * p = tmp_a; 
char * q = tmp_b; 

的字符串文字"hello"是字符的匿名,只读阵列的相同的​​内容,作为tmp_b,因此它可以被解释为一个指向其第一个元素。由于字符数据为只读,正确的定义应该是这样的:

const char * r = "hello"; // r[0] - r[5] have the same value as q[0] - q[5] 
+0

应该明确指出,字符串文字(在C中)是只读的,但是不是“const”。这可能是一件坏事,只存在于旧代码中,而C++则修复它。 –

+0

@ChrisLutz:你说得对,''hello''的*类型*只是C中的'char [6]'而不是'const char [6]',但是任何修改元素的尝试都是UB - 所以最好立即声明它为const。不过,我会将其编辑为“应该”。 –

+0

这个工具会自动生成C指针语法的解释(它对此有用):http://cdecl.org/ –

1

C中的字符串被定义为char *。否则,如果你想有一个单一的字符,你会使用char var = 'x';

int *ptr = 10;“错误”,它在法律上设置你的指针指向的地址“10”,这是在大多数(如果不是全部)的情况下,你的应用程序的内存界。

+0

这并不完全正确。 – Skizz

+0

这并不回答这个问题。 –

+0

不,将一个整型常量(0除外)隐式转换为指针类型是错误的。 –

4

简单地说10不是int*,而是它是int。你不能指定一个int指针,因为它们是不同的东西。

代码char *ptr = "Hey"成功,因为字符串文本与char*指针兼容。

但请注意,char *ptr = "Hey"会使ptr指向字符串文字。字符串文字通常存储在只读存储器中,所以任何修改它们的尝试都会失败。所以你最好写const char *ptr = "Hey"

0

在C,"Hey"被定义为字符的一个匿名数组,所以内存被分配以存储字符值(其中四个,还有一个空终止符)。

此外,你只能指向内存中的东西。所以char *可以指向匿名字符数组。

10只是一个值。它没有分配给它的内存。你不能得到不在内存中的东西的地址。所以int *失败。

要获得第二工作,你需要分配一些内存:

int value = 10; 
int *ptr = &value; // value is in memory so we can point to it 
0

在第一种情况下,"Hey"是一个字符串,它的类型是char *。因此,以这种方式初始化ptr即可。话虽如此,它真的应尽可能遵循字符串文字不能被写入:

char const * ptr = "Hey"; 

在另一方面,声明是这样的:

int * ptr = ...; 

你定义指向一个整数的指针。由于10是一个纯整数常量,它不是一个现有的int对象,所以不能指向它。

int intValue; 
int * ptr = &intValue; 

在这种情况下intValue是一个对象,你可以指向:但是,你可以像写些东西。

0

请记住像"Hey"这样的字符串文字很特别。它们存储在内存中的某个地方,并且是不变的。

指定一个指向"Hey"的指针实际上会在常量中创建该字符串,并将该常量的地址赋值给ptr

但是,当你有一个int* ptr,分配给10将分配地址10,而你的意思的价值10整数的地址。

0

说得很简单。当编译器看到的

char *ptr = "Hey" 

字符串“嘿”,编译器会保存字符嘿加内存中的一个零终止字节,然后它会用一个指针代替“嘿”字符串的第一个字符中串。

int *ptr = 10; 

也不会在10转换为指针。它会将10看作一个整数,并且抱怨它不是ptr的类型 - 一个指向int的指针。