C指针2
指针是什么
若在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。编译系统根据程序中定义的变量类型,分配一定长度的空间。
内存去的的每一个字节有一个变量即地址,相当于旅馆中的房间号。在地址所标志的内存单元中存放的数据则相当于旅馆房间中居住的旅客。
由于通过地址能找到所需的变量单元,可以说地址指向该变量单元。因此,将地址形象化地称为指针。意思是通过它能找到以它为地址的内存单元。
请务必弄清楚存储单元的地址和存储单元的内容,直接按变量名进行的访问称为“直接访问”方式。另一种称为“间接访问”,即将变量的地址存放在另一个变量中,然后通过该变量来找到变量的地址,从而访问变量。
指向是通过地址来体现的,由于通过地址能找到所需的变量单元,因此说,地址指向该变量单元。将地址形象化地称为指针。意思是通过它能够找到以它为地址的内存单元。
一个变量的地址称为该变量的指针,如果有一个变量专门用来存放另一变量的地址(指针),则称为“指针变量”。指针变量就是地址变量,用来存放地址,指针变量的值是地址即指针。
指针变量
存放地址的变量是指针变量,用来指向另一个对象。
例:通过指针变量访问整型变量
#include <stdio.h>
int main()
{
int x = 100, y = 200;
int *px, *py;//定义指向整型数据的指针变量
px = &x;//将变量x的地址赋给指针变量px
py = &y;//将变量y的地址赋给指针变量py
printf("x = %d, y = %d\n", x, y);
printf("*px = %d, *py = %d\n", *px, *py);
return 0;
}
定义指针变量:类型名 *指针变量名
int *px, *py;//左端int是在定义指针变量时必须指定的基类型,指针变量的基类型用来指定此指针变量可指向的变量的类型。
定义指针变量时同时对其初始化
int *px=&x, *py=&y;
在定义指针变量时必须指定基类型,不同类型的数据在内存中所占的字节数和存放方式是不同的。如果想通过指针引用一个变量,只知道地址是不够的,因为无法判定是从地址取出数据。必须知道该数据的类型,才能按存储单元的长度以及数据的存储形式正确地取出该数据。
一个变量的指针的含义包括两个方面:一是以存储单元编号表示的地址,一是指向的存储单元的数据类型。
如何表示指针类型,指向整型数据的指针类型表示为 int *
,读作“指向int的指针”或简称“int指针”。
指针变量中值能存放地址(指针),不要将一个整数赋给一个指针变量。
怎么引用指针变量
在引用指针变量时,可能有3种情况:
- 给指针变量赋值
- 引用指针变量指向的变量
- 引用指针变量的值
注意两种不同的运算符
- & 取地址运算符,&a是变量a的地址。
- * 指针运算符/间接访问运算符,*p代表指针变量p指向的对象的值。
例:输入两个整数,按先大后小的顺序输出。
#include <stdio.h>
int main()
{
int x = 100, y = 200;
int *px, *py, *p;
printf("please enter two integer numbers:");
scanf("%d %d", &x, &y);
px = &x;
py = &y;
if(x < y){
p = px;
px = py;
py = p;
}
printf("x = %d, y = %d\n", x, y);
printf("max = %d, min = %d\n", *px, *py);
return 0;
}
指针变量作为函数参数
函数的参数不仅可以是整型、浮点型、字符型等数据,还可以是指针类型。它的作用将一个变量的地址传送到另一个函数中。
例:对输入的两个整数按大小顺序输出
#include <stdio.h>
int main()
{
void swap(int *px, int *py);
int x,y;
int *px,*py;
printf("please enter two integer:");
scanf("%d %d", &x, &y);
px = &x;
py = &y;
if(x < y){
swap(px, py);
}
printf("max=%d, min=%d\n", x, y);
return 0;
}
void swap(int *x, int *y)
{
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
不能企图通过改变指针形参的值而使指针实参的值改变
例:输入三个整型按由大到小的顺序将其输出
#include <stdio.h>
int main()
{
void exchange(int *px, int *py, int *pz);
int x,y,z;
int *px,*py,*pz;
printf("please enter three integer:");
scanf("%d %d %d", &x, &y, &z);
px = &x;
py = &y;
pz = &z;
exchange(px, py, pz);
printf("the order is %d, %d, %d\n", x, y, z);
return 0;
}
void exchange(int *px, int *py, int *pz)
{
void swap(int *px, int *py);
if(*px < *py){
swap(px, py);
}
if(*px < *pz){
swap(px, pz);
}
if(*py < *pz){
swap(py, pz);
}
}
void swap(int *x, int *y)
{
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
通过指针引用数组
一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元素(把某一元素的地址放到一个指针变量中)。所谓数组元素的指针就是数组元素的地址。
引用数组元素可用下标法,也可用指针法,即通过指向数组元素的指针找到所需的元素。使用指针法能够使目标程序质量高,占内存少,运行速度快。
在C语言中,数组名不包括形参数组名,形参数组并不占据实际的内存地址,代表数组中首元素,即序号为0的元素的地址。
p = &a[0]; // p的值是a[0]的地址
p = a;//p的值是数组a首元素,即a[0]的地址。
数组名不代表整个数组,只代表数组首元素的地址。在定义指针变量时可对其初始化:
int *p = &a[0];// 将a数组首元素的地址赋给指针变量p
// 等效写法
int *p;
p = &a[0];
// 等效写法
int *p = a;
在引用数组元素时指针的运算
在指针指向数组元素时,可对指针进行一下运算:
- 加整数:p+1,若指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素。
- 减整数:p-1,p-1指向同一数组中的上一个 元素。
- 自加运算:p++
- 自减运算:p--
通过指针引用数组元素
引用一个数组元素,可使用两种方法:
- 下标法:a[i]
- 指针法:(arr+i)或(point+i)
例:整型数组10个元素要求输出数组中的元素
#include <stdio.h>
int main()
{
int size = 3;
int i,arr[size];
printf("please enter 3 integer:\n");
for(i=0; i<size; i++){
scanf("%d", &arr[i]);
}
for(i=0; i<size; i++){
printf("%d ", arr[i]);
}
return 0;
}
通过数组名计算数组元素地址再找出元素的值
#include <stdio.h>
int main()
{
int size = 3;
int i,arr[size];
printf("please enter 3 integer:\n");
for(i=0; i<size; i++){
scanf("%d", &arr[i]);
}
for(i=0; i<size; i++){
printf("%d ", *(arr+i));//通过数组名和元素序号计算元素地址再找到该元素
}
return 0;
}
用指针变量指向数组元素
#include <stdio.h>
int main()
{
int size = 3;
int i,*p,arr[size];
printf("please enter 3 integer:\n");
for(i=0; i<size; i++){
scanf("%d", &arr[i]);
}
for(p=arr; p<(arr+size); p++){
printf("%d ", *p);//用指针指向当前的数组元素
}
return 0;
}
在使用指针变量指向数组元素时,需注意的是
- 可通过改变指针变量的值指向不同的元素
- 要注意指针变量的当前值
#include <stdio.h>
int main()
{
int size = 3;
int i,*p,arr[size];
p = arr;
printf("please enter 3 integer:\n");
for(i=0; i<size; i++){
scanf("%d", p++);
}
p = arr;
for(i=0; i<size; i++,p++){
printf("%d ", *p);
}
return 0;
}
注意:
- 指向数组的指针变量也可以不带下标
- 利用指针引用数组元素比较方便灵活
用数组名作为函数参数