C语言指针与数组

数组的下标应该从0还是1开始? 我提议的妥协方案是0.5,可惜他们未予认真考虑便一口回绝    -- Stan Kelly-Bootle

1. 数组并非指针

为什么很多人会认为指针和数组始终应该可以互换的呢? 因为对数组的引用总是可以写成对指针的引用,而且确实存在一种指针和数组的定义完全相同的上下文环境,

不幸的是,这只是数组的一种极为普通的用法,并非所用情况下都是如此。

2. 什么是声明,什么是定义

C语言中对象必须有且只有一个定义,但它可以有多个extern声明.

定义:只能出现在一个地方,确定对象的类型并分配内存,用于创建新的对象,例如 int a[100]

声明:可以多次出现,描述对象的类型,用于指代其他地方定义的对象(例如在其他文件里) 例如 extern int a[100]

extern对象声明告诉编译器对象的类型和名字,对象的内存分配则在别处进行

3. 数组与指针的区别

出现在赋值左边的符号被称为 左值, 出现在赋值右边的符号被称为 右值。

编译器为每个变量分配一个地址(左值),这个地址在编译时可知,并且该变量在运行时一直保存于这个地址中。

存储于变量中的值(右值)只有在运行时才可知,如果需要用到变量中存储的值,编译器就发出指令从指定地址读入变量并将它存于寄存器中。

例如: char a[9] = "abcdefgh";   c = a[i]

假设编译器符号表具有一个地址9980

运行时步骤1:取 i 的值,将它与 9980 相加 (基址加偏移量)

运行时步骤2:取地址 [9980+i] 的内容

例如:char* p;  c = *p;

假设编译器符号表有一个符号p,它的地址为4624

运行时步骤1:取地址 4624 的内容,假设是 1024

运行时步骤2:取地址1024的内容

例如:char* p = "abcdefgh"   c = p[i]

假设编译器符号表有一个p,地址为 4624

运行时步骤1:取地址4624的内容,假设是 1024

运行时步骤2:取得 i 的值,并将它与 1024 相加  (基址加偏移量)

运行时步骤3:取地址 [1024+i] 的内容

指针

数组

保存数组的地址

保存数据

间接访问数据,首先取指针的内容,把它作为地址,然后从这个地址提取数据。

如果指针有一个下标[i],就把指针的内容 加上i作为地址,从中提取数据

直接访问数据 a[i]只是简单的以a+i作为地址取数据

通常用于动态数据结构

通常用于存储数目固定且数据类型相同的元素

相关的函数为 malloc free

隐式分配和删除

通常指向匿名数据

自身即为数据名

定义指针时,编译器没有为指针所指向的对象分配空间,只是分配指针本身的空间

ANSI C中,初始化指针时所创建的字符串常量所定义为 只读。在有些编译器中,字符串常量被存放在只允许读取的文本段中,以防止它被修改

char* ptr = "hello world"    // 这种写法是非常不推荐的,因为 ptr 所指对象是只读的,这将隐式的将 const 转 non-const,任何对 ptr 的修改都会 coredump

const char* ptr = "hello world"   // 这种写法明确表示 ptr 的const属性,这时对 ptr 所指对象的修改都会 在编译时报错

char a[] = "hello world"              //这种写法表明 数组中元素都是可修改的,但是数组名是不可修改的左值,即数组首地址不可以改变,是常量

4. 什么时候数组与指针相同

所有作为函数参数的数组名可以通过编译器转换为指针

数组的声明就是数组,指针的声明就是指针,两者不能混淆

注意:如果定义一个数组,在其他文件中对它extern声明时也必须把它声明为数组,指针也是如此

在使用数组(在语句或表达式中引用)时,数组总是可以写成指针的形式

数组下标表达式总是可以改写成带偏移量的指针表达式

什么时候数组和指针是相同的:

规则1:表达式中的数组名(与声明不同)被编译器当作一个指向该数组第一个元素的指针 (具体见 ANSI C标准 第6.2.2.1 节)

规则2:下标总是与指针的偏移量相同(具体见ANSI C标准 第6.3.2.1 节)

规则3:在函数参数的声明中,数组名被编译器当作指向该数组第一个元素的指针(具体见ANSI C标准 第6.7.1 节)

其实规则1和规则1合起来理解如下:对数组下标的引用总是写成"一个指向数组的起始地址的指针加上偏移量"

对数组的引用如a[i]在编译时总是被编译器改写成*(a+i)指针访问的形式

"作为函数参数的数组名"等同于指针

void func(int* arg);

void func(int arg[10]);

void func(int arg[]);

上述三种形式是完全等同的

5. 为什么C语言把数组形参当作指针

把作为形参的数组和指针等同起来是出于效率原因的考虑

在C语言中,所有非数组形式的数据实参均以传值形式(对实参做一份拷贝并传递给调用的函数,函数不能修改作为实参的实际变量的值,而只能修改传递给它的那份拷贝)调用

C语言允许程序员把形参声明为数组(程序员打算传递给函数的东西)或者指针(函数实际所接收到的东西)

不管程序员实际所写的是哪种形式,函数并不自动知道指针所指数组共有多少个元素,所以必须有个约定,如数组以NULL结尾或者另一个附加的参数表示数组的范围

可以通过向函数传递一个指向数组第一个元素的指针来访问整个数组,但也可以让指针指向任何一个元素,这样传递给函数的就是从该元素之后的数组片段

C语言指针和数组知识总结(上)

C语言指针和数组知识总结(上) 一.指针的基础 1.C语言中,变量的值能够通过指针来改变,打印指针的语句符号可以是:  %08x 2.指针的本质 指针的本质就是变量,那么既然是变量,那么一定会分配地址 ...

C语言指针与数组的定义与声明易错分析

部分摘自 1.定义为数组,声明为指针 在文件1中定义: char a[100]; 在文件2中声明: extern char *a; //这样是错误的 这里的extern告 ...

11-C语言指针&一维数组&字符串

一.用指针遍历数组元素 1.最普通的遍历方式是用数组下标来遍历元素 1 // 定义一个int类型的数组 2 int a[4] = {1, 2, 3, 4}; 3 4 int i; 5 for (i = ...

c语言指针,数组

指针:说简单点就是一个地址.例如int *p,p是个变量,里面放的是地址0x0000,同理,每一个指针,不管什么类型,都是地址,也就是空间都是4个字节(32位机). 以此类推,指针也有指向它的指针in ...

C语言指针和数组

#include int main() { /********************************************* * * 指针和数组: * 定义 ...

c语言 指针与数组

关键概念: 1.多个不同类型的指针可以对应同一个地址: 2.(&p)则是这样一种运算,返回一个指针,该指针的值是当时声明p 时开辟的地址,指针的类型是p的类型对应的指针类型: 3.(*p)操作 ...

C语言指针和数组知识总结(下)

一.数组指针: 数组指针就是一个指针,只不过它指向的是一个数组.可以通过如下方式来定义 typedef int Array[5]; //数组类型 Array* m;      //数组定义 还有一种更 ...

C语言核心之数组和指针详解

指针 相信大家对下面的代码不陌生: int i=2; int *p; p=&i;这是最简单的指针应用,也是最基本的用法.再来熟悉一下什么是指针:首先指针是一个变量,它保存的并不是平常的数据,而 ...

指针与数组的区别 —— 《C语言深度剖析》读书心得

原书很多已经写的很清楚很精炼了,我也无谓做无意义的搬运,仅把一些基础和一些我自己以前容易搞混的地方写一下. 1. 意义: 指针: 指针也是一种类型,长度为4字节,其存放的内容只能是一个地址(4字节). ...

随机推荐

Windows和linux的文件共享(1)

今天是我学习linux以来第一次写博客.带着一种激动心情我开始尝试着去完成第一篇博客.从易到难.所以第一次我就主要学习了Windows之间的文件共享. Window之间的文件共享是通过局域网实现的.局 ...

android:persistent属性

application PhoneApp既没有被Broadcast唤醒,也没有被其他service调用,那么是android是通过什么方式来启动PhoneApp,所以就发现了属性android:per ...

js中的写出想jquery中的函数一样调用

1.IIFE: Immediately-Invoked function Expression 函数模块自调用 2.代码实现

unity项目build成webgl时选择生成目录(解决方法)

在unity里点击File>>Build Settings...>>勾选你要生成的Scenes>>选择webgl>>后面Development Buil ...

docker学习系列(二):使用Dockerfile创建自己的镜像

dockerfile可以允许我们自己创建镜像,通过编写里面的下载软件命令,执行docker build 即可生成镜像文件. 初尝dockerfile 新建一个目录test,然后进入这个目录,创建一个名 ...

主引导记录MBR的结构和作用

MBR磁盘分区都有一个引导扇区,称为主引导记录,英文简称为MBR.1. MBR的结构MBR扇区位于整个硬盘的第一个扇区:按照C/H/S地址描述,即0柱面〇磁头1扇 区:按照LBA地址描述即0扇区.它是 ...

Scrum Meeting 5 -2014.11.11

放假过掉一大半.大家都努力赶着进度,算法实现基本完成.可能还有些细小的改动,但也可以统一进入测试阶段了. 今天叫了部分在校人员开了个小会.任务决定以测试为主,同时开始进行服务器的部署. 在之前尝试服务 ...

vue组件中,iview的modal组件爬坑--modal的显示与否应该是使用v-show

这是我第一次写博客,主要是记录下自己解决问题的过程和知识的总结,如有不对的地方欢迎指出来! 需求:点击btn,弹出modal显示图表(以折现图为例) 这应该是很基本的需求也是很容易实现的,代码和效果如 ...

关于Android不同系统版本的市场占比情况详解

一,google官方统计的不同Android版本市场的占比强开 google统计的数据情况 这个是google官方对于不同版本的市场占比情况.这个是针对全世界所有的Android手机占比情况. 二,友 ...

指针c语言与数组,C语言指针与数组相关推荐

  1. 关于C语言中的数组指针、指针数组以及二级指针

    概念解释 数组指针:首先它是一个指针,它指向一个数组,即指向数组的指针:在32 位系统下永远是占4 个字节,至于它指向的数组占多少字节,不知道.数组指针指向的是数组中的一个具体元素,而不是整个数组,所 ...

  2. c语言中的字节和元素,C语言指向数组元素的指针

    指向数组元素的指针和运算法则 所谓指向数组元素的指针,其本质还是变量的指针.因为数组中的每个元素,其实都可以直接看成是一个变量,所以指向数组元素的指针,也就是变量的指针. 指向数组元素的指针不难,但很 ...

  3. 【C语言】12-指向一维数组元素的指针

    本文目录 一.用指针指向一维数组的元素 二.用指针遍历数组元素 三.指针与数组的总结 四.数组.指针与函数参数 说明:这个C语言专题,是学习iOS开发的前奏.也为了让有面向对象语言开发经验的程序员,能 ...

  4. C语言学习笔记--预编译/宏定义/数组/参数传递/函数指针

    目录 预编译 值传递.指针传递.引用传递 数组 typedef 函数指针 预编译 预编译又叫预处理.预编译不是编译,而是编译前的处理.这个操作是在正式编译之前由系统自动完成的.#define 和 #i ...

  5. 【C 语言】数组与指针操作 ( 数组符号 [] 与 指针 * 符号 的 联系 与 区别 | 数组符号 [] 与 指针 * 符号 使用效果 基本等价 | 数组首地址 与 指针 本质区别 )

    文章目录 前言 一.数组符号 [] 与 指针 * 符号 使用效果 基本等价 二.数组首地址 与 指针 本质区别 前言 参考 [C 语言]指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方 ...

  6. 【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  7. C++:C++语言入门级基础知识考察点回顾之数组、指针

    C++:C++语言入门级基础知识考察点回顾之数组.指针 目录 C++的数组.字符串 1.数组 1.1.声明数组 1.2.一维数组的应

  8. 【示例】C语言中利用数组存放函数指针

    C语言中利用数组存放函数指针,增加函数使用的灵活性.使用时只需提供数组索引,即可调用不同函数. 预备知识: 1.指向函数的指针 一个函数在编译时被分配一个入口地址,这个地址就被称为函数的指针. 例如: ...

  9. c语言字符数组给字符指针,C语言常见有关问题之字符串数组和字符指针数组有关问题...

    C语言常见问题之字符串数组和字符指针数组问题 通过如下的实例来讲解这个问题: #include int main(void) { char a[3][4] = {"123", &q ...

  10. c语言数组数据用指针查找,c语言数组与指针_指针篇_2011.ppt

    c语言数组与指针_指针篇_2011 指 针 6.2 指针的概念6.3 指针与数组6.4 字符串的指针6.5 指针数组和指向指针的指针;6.2.1 地址与指针的概念 ;指针的概念;内存地址;2.数组与地 ...

最新文章

  1. 线性代数:04 特征值与特征向量 -- 特征值与特征向量
  2. 心急如焚!程序员拥有 2.2 亿美元巨款,却想不起密码
  3. WPD:Page Download Time Breakdown选项详解
  4. 深度优先算法回溯实例
  5. Java拦截器的小例子
  6. 把AspDotNetCoreMvc程序运行在Docker上-part2:修改容器以及发布镜像
  7. Quaruts II 增量编译
  8. php多功能引流工具箱源码
  9. CentOS下gitlab迁移和升级
  10. 如何在 CentOS 中添加、启用和禁用一个仓库
  11. 金蝶Cloud取物料最后一次采购入库价格
  12. Java在线打开word文档实现指定用户只能编辑指定区域
  13. sierpinski三角形的维数_神奇的分形艺术(二):Sierpinski三角形
  14. 浅谈mysqli连接方式与PDO连接方式
  15. react-router v6替换history.goBack()和goForward()
  16. 【有始有终,不让自己的付出辜负了自己期望 】
  17. java调用OPC-DA出现0x00000005错误
  18. MySQL攻略(2)
  19. android游戏开发实例-可局域网对战的飞行棋(二)
  20. ArcGlobe三维开发之十八——纵断面图的绘制

热门文章

  1. 高等数学精讲01 第一章第一节 函数
  2. 精美FLASH欣赏----
  3. android qq登陆界面代码下载,【Android Demo】QQ登陆界面(一)
  4. 基于康耐视cognexVisionpro用C#二次开发的多相机视觉对位框架
  5. nodejs+vue大学生英语网站express
  6. 监督,无监督以及自监督之间的区别
  7. 《Dolby Vision White Paper》,译名:杜比视界白皮书
  8. 论文学习报告_201106
  9. 找回放开那三国服务器,常年服务器第一《放开那三国》最强开局
  10. 网页游戏分线到不分线