C/C++——C语言数组名与指针
版权声明:原创文章,转载请注明出处。
1. 一维数组名与指针
对于一维数组来说,数组名就是指向该数组首地址的指针,对于:
int array[];
array就是该数组的首地址,如果我们想定义一个指向该数组的指针,我们可以用如下定义:
int *p;
然后令:
p = array;
那么指针p就指向了数组array的首地址,此时我们可以向操作array一样操作p:
#include <stdio.h>
int main(){
int array[]= {,,,,,,,,,};
int *p = array;
for(int i=;i<;i++){
printf("%d ",array[i]);
}
printf("\n");
for(int i=;i<;i++){
printf("%d ",p[i]);
}
printf("\n");
for(int i=;i<;i++){
printf("%d ",*(array+i));
}
printf("\n");
for(int i=;i<;i++){
printf("%d ",*(p+i));
}
printf("\n");
return ;
}
结果如下:

2. 多维数组名与指针
但是如果我们定义一个多维数组,如:
int arrays[2][2];
数组名arrays是数组元素的首地址,如果我们还用上面的那种定义:
int *p;
p = arrays;
这样p就指向了该多维数组的首地址,由于多维数组其实是数组的数组,所以多维数组的首地址就是一个地位的数组的首地址,即arrays[0],它是一个有2个元素的数组。因此我们可以将一维数组名赋值给int*型的指针,
#include <stdio.h>
int main(){
int arrays[][] = {,,,};
int *p = arrays;
for(int i=;i<;i++){
printf("%d ",p[i]);
}
printf("\n");
return ;
}
结果如下:

可以发现,编译时发生警告:

我们之所以可以通过p来遍历arrays中所有元素,是因为,数组本质上是按行优先存储的。
我们可以通过两次解引用获取到数组中的某一个元素的值,有下式成立:
**arrays == *&arrays[][] == arrays[][]
如:
#include <stdio.h>
int main(){
int arrays[][] = {,,,};
int *p = arrays;
printf("%d == %d == %d\n",**arrays,*&arrays[][],arrays[][]);
return ;
}
结果:

对于多维数组我们可以定义一个指向多维数组的指针:
int (*p)[2];
p = arrays;
这个括号是一定要加的,因为[]的优先级比较高(?)。
比较 int *p[2] 和 int (*p)[2] :
- int *p[2] 表示p是一个有2个元素的数组,数组中的每一个元素表示一个指向int型变量的指针;
- int (*p)[2] 表示p是一个指针,它指向一个数组,数组中的每个元素指向一个有2个元素的数组。
因此我们知道 int (*p)[2] 与arrays有同样的数组结构,p就是arrays的一个别名,我们可以通过p来实现任何arrays能实现的操作:
#include <stdio.h>
int main(){
int arrays[][] = {,,,,,};
int (*p)[] = arrays;
for(int i=;i<;i++){
for(int j=;j<;j++){
printf("%d ",p[i][j]);
}
printf("\n");
}
return ;
}
结果如下:

3. 数组名和指针的区别
数组名和指针之间,经常会交替使用这两个变量,例如把一个指针当成数组来使用,或者是把数组名赋值给指针,通过指针来访问数组成员变量。
但是,数组名和指针毕竟是定义不同的变量,它们之间也有一定的区别和联系。
理解数组名和指针的区别和联系有助于我们正确使用C语言,即什么情况下该使用数组名,什么情况下该使用指针。
区别1:
数组名和指针取地址后的值不一样:
- 数组名取地址得到的是数组名所指元素的地址。
- 对指针取地址得到的是指针变量自身的地址。
1)对于数组名:
#include <stdio.h>
int main(){
int array[] = {,,,,,};
printf("array = 0x%x\n",array);
printf("&array[0] = 0x%x\n",&array[]);
printf("&array = 0x%x\n",&array);
return ;
}
输出结果如下:

我们已经知道,数组名即数组首元素的地址,因此array和&array[0]的值一样,但是令我们惊奇的是,数组名的地址&array和和数组首元素的地址&array[0]也一样。
2)对于指针:
#include <stdio.h>
int main(){
int array[] = {,,,,,};
int *p = array;
printf("array = 0x%x\n",array);
printf("&array[0] = 0x%x\n",&array[]);
printf("&array = 0x%x\n",&array);
printf("\np = 0x%x\n",p);
printf("&p = 0x%x\n",&p);
return ;
}
结果如下:

可以发现指针的值和指针所在的地址是不同的。
区别2:
数组名是指针常量,指针是指针变量。
- 数组是固定大小的,数组一经定义,那么数组名就是一个指向数组首元素类型的常量指针,也就是说数组名是不允许更改的;
- 但是我们知道除非定义指针常量,否则指针变量是可以再赋值的。
区别3:
当对数组名使用sizeof时,得到的是数组所有元素所占的字节数,对指针sizeof得到的是指针类型的字节数。
#include <stdio.h>
int main(){
int array[] = {,,,,,};
int *p = array;
printf("sizeof array = %d bytes\n",sizeof(array));
printf("sizeof pointer = %d bytes\n",sizeof(p));
return ;
}
输出如下:

区别4:
对数组名取&和对指针取&的意义不同。
#include <stdio.h>
int main(){
int array[] = {,,,,,};
int *p = array;
printf("&array = 0x%x\n",&array);
printf("&array + 1 = 0x%x\n\n",&array + );
printf("&p = 0x%x\n",&p);
printf("&p + 1 = 0x%x\n",&p + );
return ;
}
输出如下:

上图可以看到对array取地址后加一,增大了24个字节,恰好是数组的大小;而对指针p取地址后加一,只增大了8个字节,恰好是一个指针类型所占的字节数。
4. 总结
- 数组名代表了一个指向数组首元素的指针常量,一经定义,不可更改;指针是指针变量,定义之后仍可更改,其类型在定义时确定。
- 当出现 sizeof 和 & 操作符时,数组名不再当成指向一个元素的指针常量来使用,而指针仍当成指向一个元素的指针变量来使用。
- 对于使用指针和数组下标的选择:
- 系统在使用数组下标对数组成员变量进行访问时,开销比较大,指针的访问效率是远远大于数组名的访问效率的;
- 但是只有在指针正确访问时,使用指针才比下标法更有效率;
- 下标法更加容易理解,在可读性方面,也更加的具有优势。
参考资料:
- https://blog.csdn.net/findgeneralgirl/article/details/78501734
- https://blog.csdn.net/dream_follower/article/details/80356754
C/C++——C语言数组名与指针的更多相关文章
- 对于C语言中数组名是指针的理解
我们都知道,c语言中数组名是一个指针,比如下面这段代码 #include<iostream>using namespace std;int main(){ int a[4]={1,2,3, ...
- C语言 数组名不是指针
今天上计算机系统课的时候老师讲到了C中的聚合类型的数据结构.在解释数组名的时候说"数组名是一个指针,指向该数组的第一个元素",附上ppt(第二行): 我觉得这是不正确的,是一个常见 ...
- C语言 数组名不是首地址指针
今天上计算机系统课的时候老师讲到了C中的聚合类型的数据结构.在解释数组名的时候说"数组名是一个指针,指向该数组的第一个元素",附上ppt(第二行): 我觉得这是不正确的,是一个常见 ...
- 【转】C语言中数组名和指针的区别
注:本文转自http://www.cnblogs.com/furaibo/archive/2010/03/19/1689710.html 魔幻数组名 请看程序(本文程序在WIN32平台下编译): #i ...
- 数组名和指针的深入理解(C++)
指针是C/C++语言的特色,而数组名与指针有太多的相似,甚至很多时候,数组名可以作为指针使用.于是乎,很多程序设计者就被搞糊涂了.魔幻数组名请看程序(本文程序在WIN32平台下编译): #includ ...
- c/c++数组名和指针区别深入探索
指针是C/C++语言的特色,而数组名与指针有太多的相似,甚至很多时候,数组名可以作为指针使用.于是乎,很多程序设计者就被搞糊涂了.而许多的大学老师,他们在C语言的教学过程中也错误得给学生讲解:&quo ...
- C/C++数组名与指针区别深入探索(转载)
转载自: C/C++数组名与指针区别深入探索 引言 指针是C/C++语言的特色,而数组名与指针有太多的相似,甚至很多时候,数组名可以作为指针使用.于是乎,很多程序设计者就被搞糊涂了.而许多的大学老师, ...
- CPP-基础:C/C++数组名与指针的区别
2005-08-23 08:36 来源:天极网 作者:宋宝华 责任编辑:方舟·yesky 引言 指针是C/C++语言的特色,而数组名与指针有太多的相似,甚至很多时候,数组名可以作为指针使用.于是乎,很 ...
- C/C++数组名与指针的区别详解
1.数组名不是指针我们看下面的示例: #include <iostream> int main() { ]; char *pStr = str; cout << sizeof( ...
随机推荐
- Redis安装与配置Redis安装与配置
今天在使用Redis的时候遇到了一些问题,这个问题的解决,发现很多人使用Redis的时候没有一点安全意识.所以又重温了一下Redis,觉得应该写一下Redis的安全和配置. Redis安装与配置Red ...
- 【MediaElement】WPF视频播放器【2】
一.前言 上回说到需要做放视频的使用向导,这两天公司里的老司机一直帮我答疑解惑,让这个任务变得挺顺的,真心感谢他们! 这次与[1]中的不同之处在于: (1)播放和暂停按钮集成在<Me ...
- 【CF813E】Army Creation(主席树)
[CF813E]Army Creation(主席树) 题面 CF 洛谷 翻译 by ppl 见洛谷 题解 考虑最多只会有\(K\)个相同的数 那么,也就是说,如果一个数会被选 那么,和它相等的数中,在 ...
- 【入门OJ】2003: [Noip模拟题]寻找羔羊
这里可以复制样例: 样例输入: agnusbgnus 样例输出: 6 这里是链接:[入门OJ]2003: [Noip模拟题]寻找羔羊 这里是题解: 题目是求子串个数,且要求简单去重. 对于一个例子(a ...
- 洛谷 P4319 变化的道路 解题报告
P4319 变化的道路 题目描述 小 w 和小 c 在 H 国,近年来,随着 H 国的发展,H 国的道路也在不断变化着 根据 H 国的道路法,H 国道路都有一个值 \(w\),表示如果小 w 和小 c ...
- Codeforces 582C. Superior Periodic Subarrays(数学+计数)
首先可以把 i mod n=j mod n的看成是同一类,i mod s=j mod s的也看成是同一类,也就是i mod gcd(s,n)的是同一类,很好理解,但是不会数学证明...大概可以想成数轴 ...
- 高性能相关、Scrapy框架
高性能相关 在编写爬虫时,性能的消耗主要在IO请求中,当单进程单线程模式下请求URL时必然会引起等待,从而使得请求整体变慢. import requests def fetch_async(url): ...
- selenium - webdriver - 定位一组元素
八种方法: find_elements_by_id() find_elements_by_name() find_elements_by_class_name() find_elements_by_t ...
- nginx 前后分离,地址重写,url匹配中遇到的问题
我遇到的问题: 前端用vue的路由做页面路由,后台用spring mvc做数据接口,但是遇到路由地址和接口地址无法区分的问题,导致nginx无法正确准发比如: 1)http://127.0.0.1/i ...
- Bootstrap自学笔记
<!DOCTYPE html><html lang="zh-cn"> <head> <meta charset="utf-8&q ...