声明:本文是基于征服C指针总结。
什么是指针?
“指针”也是一种数据类型(在C语言中,数组也是一种类型),而指针类型的值就是内存的地址,为了更快理解这一概念,实际编程理解一下:
#include <stdio.h>
int main(void)
{
int a = 5;
int b = 10;
int *c;
/* 输出各变量的地址 */
printf("&a %p\n", (void*)&a);
printf("&b %p\n", (void*)&b);
printf("&c %p\n", (void*)&c);
/* 把 a 的地址赋给指针变量 c */
c = &a;
printf("c %p\n", (void*)c);
/* 通过 c 输出 a 的值 */
printf("*c %d\n", *c);
/* 通过 c 更改 a 的值 */
*c = 10;
printf("a %d\n", a);
return 0;
}
结果:
在该程序中,第4~6行声明了 int 类型的变量 a 和 b 以及“指向 int 的指针”类型的变量 c 。
其中, int *c;
声明的是变量 c ,类型为“指向 int 的指针”。
c = &a;
是将 a 的地址赋给指针变量 c (即 c 中保存的是 a 的地址),当指针变量 c 保存了另一个变量 a 的地址时,称为“ c 指向 a ”。
第18行代码printf("*c %d\n", *c);
,因为前面已经 c 指向 a ,所以 *c 和 a 表示同样的内容,所以也可以通过给 *c 赋值改变 a 的值。
-
关于声明:
通常,C语言的声明是这种的:类型 变量名;
但是在声明指针时,却不是按照此逻辑进行int* c;
,即将*写在靠近类型的一侧。
虽然说这样符合了类型 变量名;
的形式,但是在声明多个变量会出现漏洞。 -
变量不一定按照声明的顺序保存在内存中
-
void*
是可以指向任何类型的指针类型。(关于详解点击此) -
对变量使用 & 运算符,可以获取该变量地址,这个地址称为指向该变量的指针。
指针运算
#include <stdio.h>
int main(void)
{
int x;
int *y;
/* 将指向 x 的指针赋给 y */
y = &x;
/* 输出 y 的值*/
printf("y %p\n", (void*)y);
/* y 加1 */
y++;
printf("y %p\n", (void*)y);
printf("y %p\n", (void*)(y+3));
return 0;
}
- 对于指针的加减运算,标准只允许指针指向数组元素
- 对指针加 n ,则指针前进“该指针所指向的类型的长度 × n ”
从函数返回多个值
下列程序将main()函数的变量x和y的地址传递给函数get()函数,然后get()将值保存在这两个地址中。
#include <stdio.h>
void get(double* x, double* y)
{
/* 输出形参x和y的值和地址 */
printf("x %p,y %p\n", (void*)x, (void*)y);
printf("&x %p,&y %p\n", (void*)&x, (void*)&y);
/* 将值保存到参数传递进来的地址中 */
*x = 1.0;
*y = 2.0;
}
int main()
{
double x;
double y;
/* 输出变量x和y的地址 */
printf("&x %p,&y %p\n", (void*)&x, (void*)&y);
/* 将变量x和y的地址作为参数进行传递 */
/* get()函数将值保存在该地址中 */
get(&x, &y);
/* 输出接收到的值 */
printf("x %f,y %f\n", x,y);
return 0;
}
- 第18行代码
printf("&x %p,&y %p\n", (void*)&x, (void*)&y);
,输出的是变量 x、y 地址 - 第5行代码
printf("x %p,y %p\n", (void*)x, (void*)y);
,输出的是形参x、y 的值 - 第6行代码
printf("&x %p,&y %p\n", (void*)&x, (void*)&y);
,输出形参x、y 地址
但是,下列代码却不能实现 x、y 的赋值:
#include <stdio.h>
void get(double x, double y)
{
/* 输出形参x和y的值和地址 */
printf("x %f,y %f\n", x,y);
printf("&x %p,&y %p\n", (void*)&x, (void*)&y);
x = 1.0;
y = 2.0;
}
int main()
{
double x = 3.0;
double y = 4.0;
printf("&x %p,&y %p\n", (void*)&x, (void*)&y);
get(x, y);
printf("x %f,y %f\n", x,y);
return 0;
}
结果如图:
- 根据结果可以发现,main()函数中 x、y 的地址与get()函数中 x、y 地址不同,所以是不同的变量,无论怎样修改get()函数中 x、y 的值都无法改变main()中的值。、
- 补充:
实参:调用函数时实际传输的参数
形参:接收实参的一方。