地址是内存单元的编号 指针就是地址
# include <stdio.h>
int main(void)
{
int * p;
// 定义了一个变量叫P,
//int * 是变量类型 ,p是变量名
//所谓 int * 数据类型,就是存放整型变量地址的数据类型,
//其中 int 也叫基类型,指定此指针变量可以指向的变量的类型。
//表示p只能存放 int型 变量的地址。
//为什么要指定基类型? 因为不同类型数据所占用的内存单元大小和存放方式不一致。
int i =3;
p = &i; //正确
p=i; //Error 类型不一致,P 只能存放整形变量的 “地址” ;而 i 是一个整型变量。
p = 55; //Error 同上
return 0;
}
1. P 保存了i 的地址,因此P指向了i
2. P不是i , i 也不是P。
3. 更准确的说,修改P的值不影响i的值,修改 i 的值,也不影响P的值
4. P是指针变量(能存放其他变量的地址)
i 是一个普通变量(只能存放值)
5. 如果一个指针指向了某个普通变量,则 *指针变量 就完全等同于 普通变量
例子: 如果 P 是一个指针变量,并且P存放了普通变量 i 的地址,
则P指向了普通变量 i ; * P 就完全等同于普通变量i
或者说: 在所有出现 * P 的地方都可以替换成i; 在所有出现 i 的地方都可以替换成 * P
6. * P就是以P的内容(P的内容是 i 的地址)为地址的变量
总结:指针是C语言的灵魂
一、地址
① 内存单元的编号
② 从0开始的非负整数
③ 范围: 和内存大小、地址总线的条数(CPU)、操作系统等因素有关。[这段写得可能有错,因为没学过组成原理!!!]
例如:
4G 内存,32位CPU
物理地址:0——(2^32-1)
二、指针 ① 指针就是地址,地址就是指针 ② 指针变量就是存放内存单元的编号,或者说指针变量就是存放地址的变量。 ③ 指针和指针变量是两个不同的概念,但是要注意,通常我们叙述时,会把指针变量简称为指针,实际他们含义并不一样。 ④ 指针的本质就是一个操作首先的非负整数。(指针不能相加,相乘,相除;只能进行想减)
int * P;
int i=3;
p = & i;
一、
int main (void)
{
int *P;
/*
定义P,没初始化,给P分配了一块空间,里边是垃圾值
但是垃圾值也是有指向的,指向一处未知空间,暂且把这个记为X
*/
int i =5;
*P=i;
/*
* P 以 P 的内容为地址的值。
现在P的内容为一个垃圾地址,这个地址指向X,
*P 等同于X,但是系统没给分配修改X的权限,这句却要修改人家,必然是错的。
*/
printf("%d\n",*P);
return 0;
}
二、
int main (void)
{
int *P;
int *q;
int i =5;
P=&i;
*P=*q;//语法上没错,但是没实际意义,输出结果,每次运行基本都不一样
printf("%d\n",*P);
return 0;
}
三、
int main (void)
{
int *P;
int *q;
int i =5;
P=&i;
P=q; // q 是垃圾值,q 赋给P,P也变成垃圾值
printf("%d\n",*P); //error
/*
q的空间是属于本程序的,所以本程序可以读写q的内容,
但是如果q的内部是垃圾值,则本程序不能读写*q的内容
因为此时*q所代表的内存单元的控制权限并没有分配给本程序
*/
return 0;
}
见动态内存部分
int main(void)
{
int a = 5;
int b = 3;
int c;
c = a;
a = b;
b = c;
printf("a=%d;b=%d\n",a,b);
return 0;
}
void huhuan (int a ,int b)
{
int t;
t=a;
a=b;
b=t;
printf("函数内:a=%d;b=%d\n",a,b);
return;
}
int main(void)
{
int a=5;
int b=3;
huhuan(a,b);
printf("函数调用完:a=%d;b=%d\n",a,b);
return 0;
}
//输出
函数内:a=3;b=5
函数调用完:a=5;b=3
可见,这样的函数,互换操作的是形参,对真正的实参不起作用。
程序运行,从主函数main开始,当遇到huhuan这个函数时,转到函数huhuan执行,
主函数调用huhuan,将两个实参a,b具体的值传到huhuan函数的形参部分,huhuan拿到形参具体的值(5,3),此时,系统自动为形参a,b分配内存空间,现在函数形参a=5,b=3;
函数体语句是对形参a,b进行的操作。
一旦huhuan函数执行完毕,系统为形参开辟的内存空间将被自动释放,对实参不起任何作用。
①.错误写法
void change(int *p,int*q)
{
int *t; // 必须是 int * 类型,否则类型不一致报错
t=p;
p=q;
q=t;
/*
此函数交换的是p,q的内容,
a,b 的值并没有换。
p,q是代表a,b地址的值。
注意 a,b的地址是固定的,不能说交换a,b的地址。
因为a,b是静态局部变量,一旦分配好空间,就一直是在一个地方,一个地址。
*/
return;
}
int main(void)
{
int a=3;
int b=5;
change(&a,&b);
printf("函数调用完:a=%d;b=%d\n",a,b);
return 0;
}
//输出
change函数调用完:a=3;b=5
改变的是p,q里面存放的地址,并不能改变a,b的地址;任何语言都不可能改变静态变量已经分配好的地址。
② 正确写法
void ZZhuhuan(int *p,int *q)
{
int t;
t=*p;
*p=*q;
*q=t;
return;
}
int main(void)
{
int a = 3;
int b = 5;
ZZhuhuan(&a,&b);
printf("ZZhuhuan函数调用完:a=%d;b=%d\n",a,b);
return 0;
}
//输出:
ZZhuhuan函数调用完:a=5;b=3
星号*的含义:
不用指针,函数只能返回一个值。 通过指针,可以使函数返回一个以上的值。
如何通过被调函数修改主调函数普通变量的值?
见 8.2 指针和数组
见 8.3 指针和函数
本文章使用limfx的vsocde插件快速发布