C 语言入门级问题,指针问题

2015-08-17 05:49:16 +08:00
 qw7692336
#include <stdio.h>

void main(){
    int a = 5;
    int* b = &a;
    int* c = &b;
    printf("%d\n",&a==b);
    printf("%d\n",&b==c);
    printf("%d\n",a==*b);
    printf("%d\n",b==*c);
}

输出是
1
1
1
0

为何最后一个是0?

1817 次点击
所在节点    C
25 条回复
Andiry
2015-08-17 05:59:17 +08:00
int **c = &b
pimin
2015-08-17 08:14:45 +08:00
int* c = &b;
这句可以编译通过么
zhangchioulin
2015-08-17 08:32:27 +08:00
为什么我不能编译通过
Fulminit
2015-08-17 08:35:23 +08:00
b 是指向 a 的指针
b 的值是 a 的指针地址
c 是指向 b 的指针
c 的值是 b 的指针地址

那么 c 解引用之后就是 b 的指针地址,自然和 b 的值不相同。

(好久没写C了有错误请指出,谢谢)
colorsand
2015-08-17 08:41:47 +08:00
c里边的数组指针和指针数组比较难理解
ljbha007
2015-08-17 09:04:38 +08:00
1楼就给出了正解
c里存的是b的地址所以*取出来的值是b的值 也就是a的地址
b里存的是a的地址 所以*取出来的值是a的值 也就是5
lizhiqing1996
2015-08-17 09:06:17 +08:00
c是一个整型指针,怎么存进一个指针型指针的?
nozama
2015-08-17 09:19:35 +08:00
和平台有关吧,应该64位系统上就会出现这个结果。sizeof(int) != sizeof(int*),于是*c本来应该是一个64位的指针值,但是int只有32位,所以被截断了。
canautumn
2015-08-17 09:20:58 +08:00
无视warning的话可以编译通过。具体为啥不等你要查C标准是怎么规定的了,不过写这种不规范的代码有啥意义吗?
xiaocaibaozi
2015-08-17 09:22:08 +08:00
同新路过,不过我这里的GCC碉堡了,即没给我报c类型的错,还给我输出了四个一。
linux40
2015-08-17 09:45:53 +08:00
看一楼,别的不用看了。
DiamondY
2015-08-17 10:15:28 +08:00
用楼主的代码,使用 VC6 编译,有 3 个警告;
用 1 楼的方式替换掉代码后,有 0 个警告;
但我用 VC6 运行得出的结果,却两种方式都是 4 个 1 ……囧
也就是说,单从值上面说,(b==*c )这个判断条件是 true 的;
只不过,楼主把 c 定义成指向 int 的指针,*c 出来的是 int ,而 b 却是指向 int 的指针,两个数值类型不一样
DiamondY
2015-08-17 10:18:42 +08:00
贴出 VC6 下编译的警告:

int a = 5;
int* b = &a;
int* c = &b; (warning C4047: 'initializing' : 'int *' differs in levels of indirection from 'int ** ')
printf ("%d\n",&a==b );
printf ("%d\n",&b==c ); (warning C4047: '==' : 'int ** ' differs in levels of indirection from 'int *')
printf ("%d\n",a==*b );
printf ("%d\n",b==*c ); (warning C4047: '==' : 'int *' differs in levels of indirection from 'int ')
chensonglu
2015-08-17 10:37:28 +08:00
定义的时候得用 int **c = &b ,因为 c 是一个二级指针,否则编译不通过。改完之后你会发现最后结果就是 1 了。
weyou
2015-08-17 10:46:31 +08:00
楼主的程序肯定有警告,其他同意 @nozama , 楼主应该是在 64bit 系统上运行的程序。 *c 发生了截断,因为 int* 和 int 的 size 在 64bit 系统上是不同的。
w99wen
2015-08-17 11:04:53 +08:00
对于指针的问题。
你可以这么理解。

比如有一个仓库,里面有很多东西。
那么你想要用这个仓库,所以你需要知道这个仓库的地址是什么。

指针就是仓库的地址。因此指针的内存占用是很小的。因为他只是一个地址的标记(貌似是 4B ,好久没弄过 C/C++了)。
而真实的仓库内容可能非常大。可能有 1G 大小。

那么在你说的这个情况中,这个仓库就是那个 int a = 5 ,也就是 5 这个值。
而这个地址就是那个指针 int* b 。

我们都可以用这个仓库的地址去找到仓库。然后对仓库进行改动。
然而怎么通过地址(也就是指针 b )找到仓库的真实内容(也就是 a 实际里面存了什么值)那。就是通过*符号。类似的,也可以用&得到仓库的地址。

在你的代码中:
你先用&a ,把仓库 a (也就是 int 值 5 )的地址给了 b 去存储。那么你*b 得到的自然是仓库 a 的内容。

你又用&b ,把 b 的地址给了 c ,那么*c 地址对应的应该是 b 的内容。也就是 a 仓库的地址。( a 仓库的地址 b 也看做是一个仓库)

所以你要是想从 c ,得到 a 的内容。你应该是**c ,这才是 a 仓库的内容。

应该明白的点:
指针就像是个地址。我们能通过这个地址得到我们想要的东西。得到一个东西的地址的方法是用&,而由一个地址拿到那个东西的方法是用*。
比如一个 int 值 5 ,他在内存中, 5 可以用&得到 5 的地址。我们把 5 的地址存起来,放在指针 b 里面。注意, b 也是在内存中, b 存储的是 5 的地址, b 也是有一个地址的,随意我们还可以用&得到 b 的地址。然后存储到另一个指针 c 里面。

这时候。我们用*c ,得到的是 c 存储的地址对应的内容,也就是 b 指针的内容,也就是 5 这个值的地址。因为*c 是 b 的内容, 5 的地址。所以要再用一次*,也就是**c ,才能得到 5 这个值。

我是不是蛋疼。
wlee1991
2015-08-17 11:10:02 +08:00
正确写法应该是这样的:

{% codeblock lang:c %}
#include <stdio.h>

int main (int argc, const char * argv[]) {

int a = 5; //a is int
int * b = &a; //b is a pointer to int
int * * c = &b; //c is a pointer to int *
int * * * d = &c; //d is a pointer to int * *

printf ("a = %d, &a = %p\n", a, &a );
printf ("b = %p, &b = %p\n", b, &b );
printf ("c = %p, &c = %p\n", c, &c );
printf ("d = %p, &d = %p\n", d, &d );

printf ("*b = %d\n", *b );
printf ("**c = %d\n", **c );
printf ("***d = %d\n", ***d );

printf ("%d\n", &a == b );
printf ("%d\n", &b == c );
printf ("%d\n", &c == d );

printf ("%d\n", a == *b );
printf ("%d\n", b == *c );
printf ("%d\n", c == *d );

return 0;
}
{% endcodeblock %}
wlee1991
2015-08-17 11:11:48 +08:00
`#include <stdio.h>
`
`int main (int argc, const char * argv[]) {
`
` int a = 5; //a is int
` int * b = &a; //b is a pointer to int
` int * * c = &b; //c is a pointer to int *
` int * * * d = &c; //d is a pointer to int * *
`
` printf ("a = %d, &a = %p\n", a, &a );
` printf ("b = %p, &b = %p\n", b, &b );
` printf ("c = %p, &c = %p\n", c, &c );
` printf ("d = %p, &d = %p\n", d, &d );
`
` printf ("*b = %d\n", *b );
` printf ("**c = %d\n", **c );
` printf ("***d = %d\n", ***d );
`
` printf ("%d\n", &a == b );
` printf ("%d\n", &b == c );
` printf ("%d\n", &c == d );
`
` printf ("%d\n", a == *b );
` printf ("%d\n", b == *c );
` printf ("%d\n", c == *d );
`
` return 0;
`}
kokutou
2015-08-17 11:12:31 +08:00
@w99wen 是的。
wlee1991
2015-08-17 11:14:19 +08:00
```c
#include <stdio.h>

int main (int argc, const char * argv[]) {

int a = 5; //a is int
int * b = &a; //b is a pointer to int
int * * c = &b; //c is a pointer to int *
int * * * d = &c; //d is a pointer to int * *

printf ("a = %d, &a = %p\n", a, &a );
printf ("b = %p, &b = %p\n", b, &b );
printf ("c = %p, &c = %p\n", c, &c );
printf ("d = %p, &d = %p\n", d, &d );

printf ("*b = %d\n", *b );
printf ("**c = %d\n", **c );
printf ("***d = %d\n", ***d );

printf ("%d\n", &a == b );
printf ("%d\n", &b == c );
printf ("%d\n", &c == d );

printf ("%d\n", a == *b );
printf ("%d\n", b == *c );
printf ("%d\n", c == *d );

return 0;
}
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/213658

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX