下面写的是一个关于指针的比较经典的例子——互换两个数
例1:
# include <stdio.h>
void huhuan_1(int, int);
void huhuan_2(int *, int *);
void huhuan_3(int *, int *);
int main(void)
{
int a = 3;
int b = 5;
// huhuan_2(&a, &b);
// huhuan_2(*p, *q); 是错误的 huhuan_2(a, b); 也是错误的
huhuan_3(&a, &b);
printf("a = %d, b = %d\n", a, b);
return 0;
}
void huhuan_1(int a, int b) //不能完成互换功能
{
int t;
t = a;
a = b;
b = t;
return;
}
void huhuan_2(int * p, int * q) //不能完成互换功能
{
int * t; //如果要互换p和q的值 t必须是int * ,不能是int
t = p;
p = q;
q = t;
}
void huhuan_3(int * p, int * q) //可以完成互换功能
{
int t; //如果要互换*p和*q的值,则t必须定义成int,不能定义成int *,否则语法出错
t = *p;//p是int *,*p是int
*p = *q;
*q = t;
}
输出结果为:
这个程序需要好好看看,要明白为什么前两个函数为什么不能实现两个数的互换
附注:
* 的含义:
1、乘法
2、定义指针变量
int * p;
//定义了一个名字叫p的变量,int * 表示p只能存放int变量的地址
3、指针运算符
该运算符放在已经定义好的指针变量的前面
如果p是一个已经定义好的指针变量
则 *p表示以p的内容为地址的变量
如何通过被调函数修改主调函数普通变量的值
1、实参必须为该普通变量的地址
2、形参必须为指针变量
3、在被调函数中通过
*形参名 = ......
的方式就可以修改主调函数相关变量的值
下面再说一个例子:利用指针使函数返回一个以上的值
例2:
# include <stdio.h>
int f(int i, int j)
{
return 100;
// return 88;
}
void g(int * p, int * q)
{
*p = 1;
*q = 2;
}
int main(void)
{
int a = 3, b = 5;
g(&a, &b);
printf("%d %d\n", a, b);
return 0;
}
输出结果为:
指针和数组
指针和一维数组
一维数组名
一维数组名是一个指针变量
它存放的是一维数组第一个元素的地址
下面举个例子说明一下
例3:
# include <stdio.h>
int main(void)
{
int a[5];// a是数组名,5是数组元素的个数,元素就是变量 从a[0]—a[4]
// int a[3][4]; //3行4列 a[0][0]是第一个元素 a[i][j]是第 i+1 行 j+1 列个元素
int b[5];
// a = b;//错误 a是常量
printf("%#x\n", &a[0]);
printf("%#x\n", a);
return 0;
}
输出结果为:
下标和指针的关系
如果p是个指针变量, 则
p[i]永远等于 *(p+i)
例4:
# include <stdio.h>
int main(void)
{
int a[5] = {1, 2, 3, 4, 5};
int i;
for (i=0; i<5; ++i)
printf("%d\n", a[i]); //a[i] == *(a+i)
return 0;
}
输出结果为:
确定一个一位数组需要几个参数【如果一个函数要处理一个一位数组,则需要接受该数组的哪些信息】
需要两个参数:
数组第一个元素的地址
数组的长度
下面举几个例子
例5:
# include <stdio.h>
//f函数可以输出任何一个一位数组的内容
void f(int * pArr, int len)
{
int i;
for(i=0; i<len; ++i)
printf("%d ", *(pArr+i) ); // *pArr *(pArr+1) *(pArr+2)
printf("\n");
}
int main(void)
{
int a[5] = {1, 2, 3, 4, 5};
int b[6] = {-1, -2, -3, 4, 5, -6};
int c[100] = {1, 99, 22, 33};
f(a, 5); // a是 int *
f(b, 6);
f(c, 100);
return 0;
}
输出结果为:
例6:
# include <stdio.h>
void f(int * pArr, int len)
{
pArr[3] = 88; //5行
}
int main(void)
{
int a[6] = {1, 2, 3, 4, 5, 6};
printf("%d\n", a[3]); // 11行
f(a, 6);
printf("%d\n", a[3]); // 13行
return 0;
}
一定要明白 5行的pArr[3] 和11行、13行的a[3]是同一个变量
输出结果为:
例7:
# include <stdio.h>
void f(int * pArr, int len)
{
int i;
for(i=0; i<len; ++i)
printf("%d ", pArr[i] ); // *(pArr+i) 等价于 pArr[i]
printf("\n");
}
int main(void)
{
int a[5] = {1, 2, 3, 4, 5};
int b[6] = {-1, -2, -3, 4, 5, -6};
f(a, 5);
f(b, 6);
return 0;
}
输出结果为:
指针变量的运算
指针变量不能相加 不能相乘 也不能相除
如果两个指针变量指向的是同一块连续空间中的不同存储单元,
则这两个指针变量才可以相减
例8:
# include <stdio.h>
int main(void)
{
int i = 5;
int j = 10;
int * p = &i;
int * q = &j;
int a[5];
p = &a[1];
q = &a[4];
printf("p 和 q 所指向的单元相隔 %d 个单元\n", q-p);
// p-q 没有实际意义
return 0;
}
输出结果为:
一个指针变量到底占几个字节[非重点]
预备知识:
sizeof(数据类型)
功能:返回值就是该数据类型所占的字节数
例子:sizeof(int) = 4 sizeof(char) = 1
sizeof(double) = 8
sizeof(变量名)
功能:返回值是该变量所占的字节数
假设p指向char类型变量(1个字节)
假设q指向int类型变量(4个字节)
假设r指向double类型变量(8个字节)
p q r 本身所占的字节数是否一样?
答案:p q r 本身所占的字节数是一样的
请看下例
例9:
# include <stdio.h>
int main(void)
{
char ch = 'A';
int i = 99;
double x = 66.6;
char * p = &ch;
int * q = &i;
double * r = &x;
printf("%d %d %d\n", sizeof(p), sizeof(q), sizeof(r));
return 0;
}
输出结果为:
总结:
一个指针变量,无论它指向的变量占几个字节
一般情况下,该指针变量本身只占4个字节
一个变量的地址是用该变量首字节的地址来表示
【所有代码均在windows系统下VC++6.0下运行通过】
(如有错误,敬请指正)