文章目录
指针基本概念详解
8.1.1 前提知识
对于静态存储区、动态存储区、 不同变量会保存在不同的存储区中
a) 有些变量的内存,是在编译的时候分配的;
b) 有些变量的内存,是在程序运行时分配的;
不管怎样,变量都会占用一段内存空间。
eg:
int ,float,double, char, short … 都占用一定的内存空间。使用 sizeof()函数就可以得到其占用的字节数。
8.1.2 地址的概念
在生活中,我们表示一个地址,可以用文字概述:
例如: xx市xx区xx县xx镇 ......
我们如果按照这个地址去找的话,是可以找到一个实际的地理位置的。
那在计算机中的地址其实也差不多,只是需要我们使用数组概述。
例如:
0x3e8;
0x...; //表示的是16进制
按照10禁止或其他进制一定会找到这个地址。
总结: 地址在计算机中,其实就是个数字,这个数字代表一个内存位置。
我们要严格区分地址和地址中内容的区别
例如:
int i=5,j=6; //int占用4个字节
int z = i+j;
假如从1000开始存储,程序内部会维持着一张表;
1000 指向 i
1004 则指向 j
z的地址又是另外一个数字。
8.1.3 直接访问和间接访问
直接访问: 按变量地址存取变量值,这个就叫直接访问。
间接访问: 将变量i的地址,存放在另一个内存单元中。在c语言中,我们一般定义int,char,float,double 这些变量,一般用来存值。
我们也可以定义一种特殊的变量,用来保存地址。
eg: 定义一个变量 mypoint 来存放整型变量的地址,虽然这种特殊变量也是保存地址的,但也分保存什么类型的地址。
mypoint = &i; //把变量i的地址保存到了mypoint
// 理解为mypoint 指向了i
这里所谓指向,就是通过地址体现。
虽然这个mypoint 用来存放整型变量 i 的地址,但是mypoint 这种特殊变量本身在内存中也是有地址的。所以它也是要占内存的。
//这种特殊变量 mypoint 一般占4个字节内存。
如果现在要存取i的值:
是间接访问
需要先找到存放i的地址的这个内存位置
mypoint中保存的是整形变量i的地址。整形变量占用4个字节,这表示1000这个地址开始的4个字节里边是个整形数据。 也就是1000-1003地址里边是整形数据。那我们就从1000开始取得4个字节数据,也就是5,这就是i的值。这个就是所谓的间接访问。
概念:
指针变量 : 如果一个变量,比如 mypoint ,专门用来存放另外一个变量的地址,则称这个变量为指针变量。mypoint就是一个指针变量
指针变量的值: 这个值是个地址(指针)。
区别好”指针变量“和”地址/指针“两者的区别。
-
指针就是个地址(地址就是个数字);
-
指针变量是存放其他变量地址的变量,也叫该指针变量指向某某变量
8.2变量的指针和指向变量的指针变量
8.2.1指针变量的定义
变量的指针 就是变量的地址。
我们可以定义一个指向变量的指针变量,这种指针变量,我们在定义的时候,会引入一个 ***** 在定义的语句中,表示这是一个 “ 指针变量”
指针变量的一般形式:
类型标识符 *标识符 // 标识符就是指针变量的名字
指针变量定义时,变量名前面有个*号,这个是和普通变量最明显的区别;
int i,j;
float k; //普通变量
int *point1,*point2; //**指针变量, 指向同类型的普通变量**
float *pm2; //表示此指针变量是指向实型变量的指针。
如何让整形指针变量指向一个整型变量
可以用赋值语句使一个整形指针变量指向一个整形变量(普通变量)
point1 = &i; // &地址符,等价于 point1 指向了 i .
说明:
定义指针变量的时候(int *point1; ) ,指针变量前是有 * 的,表示这是正在定义一个指针变量。 但是我用指针变量的时候,指针变量名前是没有 * 的,
指针变量的名称是 point1, point2 ,而不是 *point1, *ponit2
我们在这里有个技巧:
- 定义 用 *
- 使用 用 名称
- 取其他地址 &
一个指针变量只能指向同一个类型的变量(普通变量);
float *pm3;
float *pm4;
float i;
pm3 = &i;
1. 每个变量都有地址。
point = &i;
// point本身是有地址的,&i表示取出i的地址。point = &i 表示将 i的地址给到point ,此时point就是个指针变量。
8.2.2指针变量的引用
指针变量中只存放地址,不要将一个整型变量赋值给一个指针变量。
int *point;
point = 4; //这是错的 , point是个指针变量,只能存放地址,不能存放常量。
和指针变量相关的运算符两个:
- & 取地址运算符,
-
* 指针运算符,也叫间接访问运算符,也可以用于定义指针变量
但是若这个 * 不出现在指针变量定义的场合,而且也不是个乘法运算符,那么这个 * 是啥意思? * 依旧是指针运算符。 只不过代表的是该指针变量所指向的变量。
int a,b;
int *p1,*p2; //这里这个 * 表示这变量是个指针变量。
a = 100;
b = 200;
p1 = &a; //表示把变量a的地址赋给了p1, 现在p1指向了a;
p2 = &b; //表示把变量b的地址赋给了p2, 现在p2指向了b;
printf("%d\n",a,b);
printf("%d,%d\",*p1,*p2); // *p1 == a ; *p2 == b;
- * 指针运算符, 不用于 定义指针变量的场合时,代表的是它所指向的变量。
8.2.3指针变量作为函数参数
函数的参数可以说指针类型,作用是将一个变量的地址传送到一个函数中去;
#include <stdio.h>
void swap(int *p,int *q) { //此时p 指向a,q指向了b
int temp;
temp = *p; // *p -> a
*p = *q;
*q = temp;
}
int main() {
int a = 5,b = 6;
int *p1,*p2;
p1 = &a; //p1指向a
p2 = &b; //p2指向b
printf("a=%d,b=%d\n",a,b);
printf("%d,%d\n",p1,p2);
if(a < b)
{
swap(p1,p2);
}
printf("a=%d,b=%d\n",a,b);
return 0;
}
注意:
-
实参传递到形参是”值传递“,单向传递;
-
实参变量和形参变量之间传递是单向的值传递,指针变量作为函数参数也要遵循这个原则
-
调用函数swap( ) 不能改变实参指针变量的值的,也就是说,我p1还是指向a ,p2还是指向b。但可以改变实参指针变量p1,p2所指向的变量的值。 也就是说在swap()中改变了a , b中的值。 a和b就是实参变量p1 , p2所指向的变量。
- 不能企图通过改变指针形参的值而使指针实参的值改变。
只有通过变量来收取地址中的变量才能够改变其地址中的数据。
#include <stdio.h>
void swap(int * p1,int * p2); //函数声明
int main()
{
void swap(int * p1, int * p2);
int a,b;
int *pointer_1,*pointer_2;
a=5,b=6;
pointer_1 = &a;
pointer_2 = &b;
if(a<b)
{
swap(pointer_1,pointer_2);
}
printf("max = %d,min=%d\n",*pointer_1,*pointer_2);
return 0;
}
void swap(int *p1,int *p2){ //函数定义
int *p;
p=p1;
p1 = p2;
p2 = p;
}
- 不交换整型变量的值,而交换两个指针变量的值。
此处虽然交换了地址,但是里面存放的内容没变。
#include <stdio.h>
int main()
{
int *p1,*p2,*p,a,b;
scanf(%d,%d",&a,&b);
p1= &a;
p2= &b;
if(a<b)
{ //调换地址
p=p1;
p1=p2;
p2=p;
}
printf("a=%d,b=%d\n",a,b);
printf("max=%d,min=%d\n",*p1,*p2);
return0;
}