有一个这样的错误:

在一个文件中定义:int mango[100]; 

在另一个文件中声明:extern int *mango; 

将会产生错误

定义和声明的区别:

在C中,任何对象都有且只有一个定义,但是可以有多个声明

  • definition:只出现一次    为一个对象指定类型,分配存储空间。用于创建一个新的对象
  • declaration:可以出现多次    描述这个对象的类型。用于引用某个已经定义了的对象

所以数组的定义需要指定大小,声明不需要。但是对于多维数组,需要在声明的时候指定除最左侧维度的其他维度的大小,这样编译器才知道怎么解析下标

地址y和地址y的内容:

虽然在大多数语言中二者使用相同的符号表示,但是二者有不同的含义

以一个赋值语句为例:x=y

  • 符号x:在这条语句中表示的是x这个符号代表的内存地址,这个地址被称为左值。左值在编译期间确定,指明存储值的位置
  • 符号y:在这个语句中表示的是y代表的地址的内容,这个内容被称为右值。右值直到运行期间才可以确定,"y的值"表示右值

"可修改左值"是C引进的术语

  • 表示一个左值可以放到一个赋值语句左侧(并不意味之左值本身代表的地址值可以被改变)
  • 这个概念为了兼顾数组名,数组名是一个指明对象位置的左值,但在C中不能被赋值,所以数组名是左值但不是可修改左值

编译器会为x和y都分配一个地址空间,也就是左值。这两个左值在编译期间确定,并用于在运行期间存放变量

但是这两个左值中存放的值只有在运行期间才可以确定,当需要用到存储在变量中的值的时候,编译器执行命令获取存储在地址空间中的值放到寄存器中

关键的区别在于:

因为编译期间就可以确定每个符号,所以如果编译器想要对某个地址(左值)进行操作就可以直接去做而不用执行指令去获取这个地址

而一个指针的值(右值)只有在运行期间才可以知道并被解引用

指针中存放的地址可以随便更改,地址指向的存储空间中的值也可以随便更改,但是数组的存储位置在程序运行期间不会改变,即便存储的值会变

所以声明一个数组和声明一个指针的区别在于指针需要在运行期间使用额外的指令去获取指针中存放的值,而数组是编译器已经知道的

错误的原因:

定义是数组,所以mango代表的地址空间以及之后的一片空间都直接存放的是char字符

引用是指针,编译器执行指针的解析方式:获取mango代表的地址空间,获取它里面存放的值,然后把这个值当作地址并加上偏移之后获取对应位置的值

但是实际上mango代表的地址空间中的值是一个ASCII字符,编译器解析为指针就会产生错误

正确的方式:

file 1: 

int mango[100]; 

file 2: 

extern int mango[];

字面量初始化:

数组和指针都可以用一个字面量初始化,但是二者的效果完全不同

指针定义时只会申请一个空间存放地址值而不会为初始化的值申请空间。ANSI标准规定用字面量初始化的指针是只读的,通过指针进行的更改是未定义的。一些编译器会把字面量放到程序的文本段中,那里的数据是受只读权限保护的、

但是数组会为字面量申请空间并存放,所以对它的修改是合法的

实际使用时的数组和指针:

当正常声明一个数组的时候,会发现编译器为这个数组分配的空间正好是数组元素占用的空间,不会为数组名分配有额外的空间

如果声明一个N维数组,你会发现所有维的第一个元素都指向分配的第一个内存地址

如果尝试对数组名进行取地址操作,那么你仍将得到分配的第一个内存地址。但是这个地址中存放的值其实是数组的第一个元素,而不是数组名代表的一个地址类型的值。所以并不会有一个内存地址(开发者可见的,当然编译器会为自己记录一下符号表之类的值)中存放着数组名,也就是数组名只是被编译器维护在符号表中的,而不存在一个实际的变量。编译器在维护的时候将它的地址和它的值都设置为分配的第一个内存地址。

所以,显然的,数组名不能被当作左值,任何将数组名当作左值的操作都会使编译器发出非左值的error

但是如果是一个指针,无论是通过将现有的数组赋给它还是动态申请内存来为它赋值,它本身都有一个实实在在的内存空间用于维护自身,所以它可以作为左值

函数传数组:

编译器在编译的时候会为参数和返回值申请栈空间

所以实际上是有实在的空间存储参数的

在向函数传递数组参数的时候,会向变量中实际传递这个数组名代表的值,因而这个参数占有实际的存储空间,这就成为一个指针了,所以这里的“数组名”将可以作为左值

这也是合理的,函数维护这个变量到底是一个数组还是一个指针将会花费额外的精力,在为参数申请栈空间的时候也要分情况考虑,如果使用一个指针,这将简单的多

但是编译器只会进行一重这样的退化,当参数是多维数组时,函数实际得到的是指向维数少一的数组的指针

这个指针的类型就是数组元素类型的指针,但是在获取它的大小的时候会有一个warring:

warning: 'sizeof' on array function parameter 'a' will return size of 'const double *' [-Wsizeof-array-argument]

到底还是一个指针

动态分配的数组就不会具有这样的性质,因为它们毕竟还是指针,每一重都会多占用一部分内存地址用于存放指针,但是数组就不会

C语言数组和指针是不同的的更多相关文章

  1. C语言 > 数组和指针

    C语言 数组和指针 const: 关于指针和const需要注意一些规则.首先,把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的. 然而,只能把非const数据的地 ...

  2. C语言数组和指针的理解_在取地址运算上的操作_指针加减操作_a 和&a 的区别

    1.一个实例+理论分析 在了解数组和指针的访问方式前提下,下面再看这个例子: main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); pr ...

  3. 深入解析C语言数组和指针

    概述 指针是C语言的重点,同时也是让初学者认为最难理解的部分.有人说它是C语言的灵魂,只有深入理解指针才能说理解了C语言.暂且撇开这些观点不谈.这章是我在阅读<C和指针>这本书的读书笔记. ...

  4. C语言数组与指针总结

    寒假要开始猛刷<剑指offer>,先回顾一下C语言基础做个热身. 指针 相信大家对下面的代码不陌生: ; int *p; p=&i; 这是最简单的指针应用,也是最基本的用法.再来熟 ...

  5. (C语言)数组与指针的区别

    以前常常听过这种说法,说数组和指针这两者比较像,但是不能混淆,可是一直没能理解.刚刚在李云的<专业嵌入式软件开发>中,看了讲述数组与指针区别的一章,似乎有所领悟.本着知乎上看到的这张图,我 ...

  6. (转载)C语言 数组与指针的区别

    1) 字符串指针变量是个变量,指向字符串的首地址:而字符串数组名是个常量,为字符串数组第一个元素的地址: 2)字符串指针变量可以赋值,而字符串数组名不能赋值:对于字符数组只能对各个元素赋值,不能用以下 ...

  7. C语言-数组与指针 字符与字符串

    1 字符与字符串:char c='a'而不能写出char c="a" //字符变量用单引号'',而字符串用双引号. 2 字符数组与字符指针的初始化: char s[10]={0}, ...

  8. c语言-数组、指针面试题

    转载 说明:所有题目均摘录于网络以及我所见过的面试题目,欢迎补充! 无特殊说明情况下,下面所有题s目都是linux下的32位C程序. 先来几个简单的热热身. 1.计算以下sizeof的值. char ...

  9. C语言数组,指针小案例

    /* ============================================================================ Name : hello.c Autho ...

随机推荐

  1. [HDU1160]FatMouse's Speed

    题目大意:读入一些数(每行读入$w[i],s[i]$为一组数),要求找到一个最长的序列,使得符合$w[m[1]] < w[m[2]] < ... < w[m[n]]$且$s[m[1] ...

  2. V4L2驱动程序架构

    1 V4L2简介 video4linux2(V4L2)是Linux内核中关于视频设备的内核驱动,它为Linux中视频设备访问提供了通用接口,在Linux系统中,V4L2驱动的Video设备节点路径通常 ...

  3. 2019-03-15 Python time datetime 获取当下时间 和 格式化时间

    import datetime start_date='2018-01-10' end_date='2019-01-10'# 转换为2018-01-10 00:00:00start_date=date ...

  4. spring security中当前用户信息

    1:如果在jsp页面中获取可以使用spring security的标签库 在页面中引入标签   1 <%@ taglib prefix="sec" uri="htt ...

  5. WinServer-IIS-svg/woff/woff2字体 404错误

    问题:最近在IIS上部署web项目的时候,发现浏览器总是报找不到woff.woff2字体的错误.导致浏览器加载字体报404错误,白白消耗了100-200毫秒的加载时间. 原因:因为服务器IIS不认SV ...

  6. HDU 2879

    利用x<n的信息,可以证得当n为素数时,he[n]=2;同时,若n 为素数,则有HE[N^K]=2;因为若等式成立则有n|x(x-1).抓住这个证即可. 至于符合积性函数,想了很久也没想出来,看 ...

  7. Sublime Text 3 添加到右键菜单

    Sublime Text 3 添加到右键菜单 学习了:http://jingyan.baidu.com/article/cdddd41c99d07653ca00e147.html Windows Re ...

  8. 【POJ 2485】 Highways

    [POJ 2485] Highways 最小生成树模板 Prim #include using namespace std; int mp[501][501]; int dis[501]; bool ...

  9. android init进程分析 init脚本解析和处理

    (懒人近期想起我还有csdn好久没打理了.这个android init躺在我的草稿箱中快5年了.略微改改发出来吧) RC文件格式 rc文件是linux中常见的启动载入阶段运行的文件.rc是run co ...

  10. Android This Activity already has an action bar supplied by the window decor

    This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_ ...