文档章节

C语言基础-06-指向一维数组元素的指针

Corwien
 Corwien
发布于 2016/03/15 23:57
字数 2059
阅读 17
收藏 3

一、用指针指向一维数组的元素

// 定义一个int类型的数组
int a[2];

// 定义一个int类型的指针
int *p;

// 让指针指向数组的第0个元素
p = &a[0];

// 修改所指向元素的值
*p = 10;

// 打印第一个元素的值
printf("a[0] = %d", a[0]);

输出结果:,说明已经通过指针间接修改了数组元素的值,跟指向一个普通int类型变量是一样的。

由于数组名代表着数组的首地址,即a == &a[0],因此第8行代码等价于:

// 让指针指向数组的第0个元素
p = a;

内存分析图如下,一个指针变量占用2个字节,一个int类型的数组元素占用2个字节

二、用指针遍历数组元素

1.最普通的遍历方式是用数组下标来遍历元素

// 定义一个int类型的数组
int a[4] = {1, 2, 3, 4};

int i;
for (i = 0; i < 4; i++) {
    printf("a[%d] = %d \n", i, a[i]);
}

输出结果:

2.接下来我们用指针来遍历数组元素

先定义一个指针,指向数组的第一个元素

// 定义一个int类型的数组
int a[4] = {1, 2, 3, 4};
// 定义一个int类型的指针,并指向数组的第0个元素
int *p = a;

p的值是a[0]的地址,因此,现在我们利用指针p只能访问数组的第0个元素a[0],用*p就可取出a[0]的值1。要想访问其他元素,就必须拿到元素的地址,可以发现每个元素的地址差值为2,因为在16位编译器环境下,一个int类型的变量占用2个字节。现在只是知道a[0]的地址值为p,怎么根据a[0]的地址获取其他元素的地址呢?其实非常简单,p+1就是a[1]的地址。注意了,这里的p+1代表着p的值加2,并不是p的值加1,比如p的值为ffc3,p+1则为ffc5,而非ffc4。依次类推,p+2就是a[2]的地址ffc7,p+3就是a[3]的地址ffc9。

我先解释一下,为什么p+1代表p的值加2,而不是加1呢?

其实,p+1不一定代表p的值加2,也可能是加1、加4或者加8。究竟加多少,这跟指针的类型有关。下图是在16位编译器环境下的情况。

聪明的你可能已经找到规律了,因为char类型的变量要占用1字节,所以p+1代表p的值加1;float类型的变量占用4字节,所以p+1代表p的值加4。从这一点,也可以很好地说明为什么指针一定要分类型,不同类型的指针,p+1的含义是不一样的。

上述代码中的p指向了int类型的数组元素a[0],所以p+1代表p的值加2。知道怎么获取其他元素的地址了,那么就可以利用指针p遍历数组元素了。

// 定义一个int类型的数组
int a[4] = {1, 2, 3, 4};

// 定义一个int类型的指针,并指向数组的第0个元素
int *p = a;

int i;
for (i = 0; i < 4; i++) {
    // 利用指针运算符*取出数组元素的值
    int value = *(p+i);
    
    printf("a[%d] = %d \n", i, value);
}


注意第10行的代码,*(p+i)代表根据p+i的值(其实就是第i个数组元素的地址)访问对应的存储空间,并取出存储的内容(也就是取出第i个数组元素的值),赋值给左边的value。

最后的输出效果是一样的:。注意的是:遍历完毕后,指针变量p还是指向a[0],因为p值一直没有变过,一直都是a[0]的地址ffc3

补充一下,其实第10行改成下面的代码也是可以的:

int value = *(a+i);

大家都知道,a值代表数组的首地址,也就是a[0]的地址ffc3。a+1则代表a的值加2,即a[1]的地址ffc5,也就是说,a+i代表着元素a[i]的地址。相信大家也能猜出来了,a+1不一定代表着a值加2,究竟加多少,取决于数组的类型a+i的计算方法与p+i相同

 

利用上面的方法遍历完数组元素后,p一直指向元素a[0]。其实我们也可以直接修改p的值来访问数组元素,只需要改一下第10行的代码即可

// 利用指针运算符*取出数组元素的值int value = *(p++);

p++其实就是相当于p = p + 1,直接修改了p值,而且每次是加2。因此,每执行一次p++,指针p就会指向下一个数组元素。

输出结果肯定是一样的:。但是,遍历完毕后,指针变量p没有指向任何数组元素,因为一共执行了4次p++,最后p值为ffcb。当然,可以重新让p指向a[0]:p = &a[0];或者p = a;

注意,这里的写法是错误

int value = *(a++);

a++相当于a=a+1,数组名a是个常量!不能进行赋值运算!

 

三、指针与数组的总结

p是指针,a是一个数组

1> 如果p指向了一个数组元素,则p+1表示指向数组该元素的下一个元素。比如,假设p = &a[0],则p+1表示a[1]的地址

2> 对于不同类型的数组元素,p值的改变是不同的。如果数组元素为int类型,p+1代表着p的值加上2(16位编译器环境下)

3> 如果p的初值是&a[0],那么

  • p+i和a+i都可以表示元素a[i]的地址,它们都指向数组的第i个元素。a代表数组首地址,a+i也是地址,它的计算方法与p+i相同

  • *(p+i)和*(a+i)都表示数组元素a[i]

  • 虽然p+i和a+i都指向数组的第i个元素,但二者使用时还是有区别的。因为作为指针变量的p可以改变自身值,如p++,使p的值自增。而数组名a是一个代表数组首地址的常量,它的值是不能改变的,即a++是不合法的

4> 引用一个数组元素可以有两种方法:

  • 下标法: 如a[i]

  • 指针法: 如*(p+i) 或 *(a+i)


四、数组、指针与函数参数

1.用数组名作为函数实参时,是把实参数组的首地址传递给形参数组,两个数组共同占用同一段内存空间,这样形参数组中的元素值发生变化就会使实参数组的元素值也同时变化

void change(int b[]) {
    b[0] = 10;
}

int main()
{
    // 定义一个int类型的数组
    int a[4] = {1, 2, 3, 4};

    // 将数组名a传入change函数中
    change(a);
    
    // 查看a[0]
    printf("a[0]=%d", a[0]);
    
    return 0;
}

change函数的形参是数组类型的,在第11行调用change函数时,将数组名a,也就是数组的地址传给了数组b。因此数组a和b占用着同一块内存空间。

输出结果:

 

2.这种地址的传递也可以用指针来实现。函数的实参和形参都可以分别使用数组或指针。这样就有4种情况:

也就是说,如果一个函数的形参类型是一个数组,调用函数时,你可以传入数组名或者指针变量;


注:本文转自M了个J的博客。

本文转载自:http://www.cnblogs.com/mjios/archive/2013/03/18/2964748.html

Corwien
粉丝 27
博文 149
码字总数 115164
作品 0
广州
程序员
私信 提问
C语言数组与指针一本道来

数组与指针.png 一本道来其他系列 C语言关键字 C语言注释符号一本道来 C语言编译预处理技术一本道来 指针的基础 注意本节内容可能在gcc下不能完成编译,请切换到Windows平台,使用或其他 指针...

PcDack
2017/12/04
0
0
C语言指针讲解(二)

谨记 听......黎明在远方呼唤清晨,别在等,人的一生必将经历许多磨难,所以在人生前行的道路上,我们不可对每件轻微的伤害而敏感,在生活的磨难面前,精神上的坚强和无动于衷是我们抵抗罪恶...

长风留言
2017/11/13
0
0
嵌入式开发之C基础学习笔记06--数组和指针(非常重要,难点)

C语言进阶学习 数组 1)数组的使用 2)字符串(String):数组(尤其是一维数组)最常用的地方——————>C语言中字符串就是一维数组 数组: 定义:具有相同类型的数据的有序集合,并用唯一的...

吴锦涛
2012/12/14
654
0
数组指针和指针数组的区别

数组指针和指针数组的区别 数组指针(也称行指针) 定义 int (*p)[n]; ()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行...

超级极客
2016/12/05
0
0
数组指针和指针数组

一、两者的比较(出处:http://www.cnblogs.com/hongcha717/archive/2010/10/24/1859780.html)数组指针(也称行指针) 定义 int (*p)[n]; ()优先级高,首先说明p是一个指针,指向一个整型的...

8yi少女的夢
2017/09/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Nginx 快速安装详解

一、Nginx Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамбле...

网络小虾米
29分钟前
4
0
技术分享 | slave_relay_log_info 表认知的一些展开

作者:胡呈清 slave_relay_log_info 表是这样的: mysql> select * from mysql.slave_relay_log_info\G *************************** 1. row *************************** Number_of_lin......

爱可生
31分钟前
3
0
nginx配置http访问自动跳转到https

server {listen 80;server_name www.域名.com;rewrite ^(.*) https://$server_name$1 permanent;}server {listen 443;server_name www.域名.com;root /home/www;ssl on;......

很好亦平凡ms
32分钟前
4
0
SpreadJS:一款中国研发的类Excel开发工具,功能涵盖Excel的 95% 以上

Excel 作为一款深受用户喜爱的电子表格工具,借助其直观的界面、出色的计算性能、数据分析和图表,已经成为数据统计领域不可或缺的软件之一。 基于Excel对数据处理与分析的卓越表现,把Excel...

葡萄城技术团队
32分钟前
3
0
用javafx框架tornadofx做了个天气预报的程序

class WeatherApp : App(WeatherView::class)class WeatherView : View("十五天天气预报") { val weatherVM: WeatherViewModel by inject() val controller: WeatherController by......

oschina4cyy
35分钟前
4
1

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部