第八章  指针

1、一个变量的地址称为该变量的指针

一个专门用来存放另一变量的地址(即指针),称它为指针变量。指针变量的值是指针(即地址)

如上图2000是变量的指针,pointer是指针变量, 赋值语句可以为  *pointer = 3; *表示指向,*pointer表示指针变量pointer指向的变量

2、指针变量的定义   类型名  *指针变量名;

                                   &    取地址运算符        &a是变量a的地址;

                                    *    指针运算符            *p代表指针变量p指向的对象  

#include<stdio.h>
int main()
{
int a=,b=;
int *pointer1, *pointer2;
pointer1 = &a; //注意不是 *pointer1 = &a,这里的指针变量名是pointer1
pointer2 = &b;
*pointer2 = ;
printf("a=%d,b=%d\n",a,b);
printf("*pointer1=%d,*pointer2=%d",*pointer1,*pointer2);
return ;
}

3、指针变量作为函数参数

int main()
{
int a,b;
int *pointer1,*pointer2;
scanf("%d%d",&a,&b);
pointer1 = &a;
pointer2 = &b;
if( a<b ) Swap1( pointer1,pointer2);
printf("max=%d min=%d",a,b);
return ;
}

下面看一下回字的四种写法

void Swap1( int *p1, int *p2)
{
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}

这种写法是可以完成交换的,把p1指向的内容交换,也就是a和b的值交换了

void Swap2( int *p1, int *p2)
{
int *temp;
temp = p1;
p1 = p2;
p2 = temp;
}

这种做法的意思是把指针变量的值进行交换,但是这是办不到的。因为C语言中实参变量和形参变量之间的数据传递是单向的“值传递”方式。

不可能通过执行调用函数来改变实参指针变量的值,但是可以改变实参指针变量所指变量的值。

void Swap3( int *p1, int *p2)
{
int *temp;
*temp = *p1;
*p1 = *p2;
*p2 = *temp;
}

这种做法更加就不靠谱一点,*p1就是a,是整型变量, *temp是指针变量temp所指向的变量,但由于未给temp赋值,因此temp中并无确定的值,所以temp所指向的单元也是不可预见的,所以,对*temp赋值就是向一个未知的存储单元赋值,而这个未知的存储单元中可能存储着一个有用的数据,这样就有可能破坏系统的正常工作情况。

void Swap4( int a, int b)
{
int temp;
temp = x;
x = y;
y = temp;
}

这个就是比较明显的形参值的改变不能使实参值随之改变,x与y的值交换了,但是a与b的值并未受到影响

4、通过指针引用一维数组

1)在C语言中,数组名(不括形参数组,形参数组不占据实际的内存空间)代表数组中首元素(即序号为0的元素)的地址

int *p;
p = &a[];
p = a; //以上两句等价

2)如果指针变量p已经指向数组中的一个元素,那么p+1指向同一数组中的下一个元素,p-1指向同一数组中的上一个元素。

3)如果p的初值为&a[0],那么p+i和a+i就是数组元素a[i]的地址,*(p+i)或*(a+i)是p+i或a+i所指向的数组元素,即a[i]

4)设p指向数组a的首元素(p=a)

p++;
*p;
//p++使p指向a[1],再执行*p得到a[1]的值 *p++;
//等价于*(p++);相当于a[i++]
//先引用p的值,实现*p的运算,得到a[0],再自增 *(++p);
//相当于a[++i]
//先p自增,再运算得到a[1] ++(*p);
//相当于 ++a[0];

5、通过指针引用多维数组

设一个二维数组  int a[3][4]={ {1,3,5,7},{9,11,13,15},{17,19,21,23} };

表示形式

含义

地址

a

二维数组名,指向一维数组a[0],即0行的首地址

2000

a+1 ,&a[1]

1行首地址

2016

a[1],*(a+1)

1行0列元素a[1][0]的地址

2016

a[1]+2,*(a+1)+2,&a[1][2]

1行2列元素a[1][2]的地址

2024

*(a[1]+2),*(*(a+1)+2),a[1][2]

1行2列元素a[1][2]的值

元素值为13

比较难理解的是 *(a+1)并不是a+1单元的内容(值),因为a+1并不是一个变量的存储单元,也就谈不上它的内容了。*(a+1)就是a[1]

 #include <stdio.h>
#include <stdlib.h>
#include<string.h> int main()
{
int a[][]= {,,,,,},*p=&a[][];
printf("a[0]=%d\n",*a[]); //
printf("a[1]=%d\n",*a[]); //
printf("a[1]+1=%d\n",*a[]+); //
printf("(a[1]+1)=%d\n",*(a[]+)); //
printf("%d\n",*(p+)); //
return ;
}

必须清楚:二维数组名(如a)是指向行的,因此a+1中的1代表一行中全部元素所占的字节

                    一维数组名(如a[1])是指向列元素的,a[0]+1中的1代表一个a元素所占的字节数

                    在指向行的指针前面加一个*,就转换为指向列的指针如 *(a+1)

                    在指向列的指针前面加一个&,就成为指向行的指针

最新文章

  1. .NET单元测试的艺术-3.测试代码
  2. Redis的五种数据结构
  3. C# IO操作(四)大文件拷贝(文件流的使用)、文件编码
  4. BZOJ 1025: [SCOI2009]游戏( 背包dp )
  5. Oracle 去掉重复字符串
  6. bootstrap中的下拉菜单
  7. AfxBeginThread和CreateThread具体区别
  8. oled
  9. PHP多条件分类列表筛选功能开发实例
  10. learning makefile call func
  11. CMM/CMMI的基本概念
  12. elasticsearch 单机多实例
  13. go 语言实现一个简单的 web 服务器
  14. Oracle_spatial的常见错误与注意事项
  15. js中parentNode,parentElement,childNodes,children
  16. centos7 安装 最新版本的docker
  17. [py]django表单不清空实现的2种方法
  18. Hadoop 和 Spark 的关系
  19. ORM创建 脚本运行
  20. 一维码Codabar简介及其解码实现(zxing-cpp)

热门文章

  1. AngularJs 的ng-include指令的使用
  2. synchronized(3)修饰语句块之:synchronized(一般对象)
  3. HTML5 File API的应用
  4. iOS 画环形图
  5. 支付宝SDK
  6. 微信小程序组件解读和分析:十三、radio单选项目
  7. 微信小程序组件解读和分析:九、form表单
  8. Sass的的使用一
  9. CentOS 7 samba server 配置
  10. mac 目录颜色设置