文档章节

第二章 数组名是一个指针常量吗?

北极心
 北极心
发布于 2016/08/11 10:11
字数 1216
阅读 2
收藏 0
点赞 0
评论 0

 

数组名是一个指针常量这种观点来源于数组名在表达式计算中与指针的结果等效性。例如下面的代码:

int a[10], *p = a, *q;

q = a + 1;

q = p + 1;

在效果上看,a + 1与 p + 1是相同的,这很容易给人一种a就是p的假象,但,这仅仅是假象。鉴于指针常量包含了指针和常量两类概念,我们可以把这个问题分开两部分进行讨论。

一、数组名是指针吗?

在《C与指针》一书中,作者用一个著名的例子阐述了数组名与指针的不同。在一个文件中定义:int a[10];然后在另一个文件中声明:extern int *a; 笔者不在这里重复其中的原理,书中的作者试图从底层操作上阐述数组名与指针的不同点,但笔者认为这个例子存在一些不足,a在表达式中会转换为一个非对象的符号地址,而指针a却是一个对象,用一个非对象去跟一个对象比较,有“偷跑”的嫌疑,这个例子只是说明了数组名的非对象性质,只能证明对象与非对象实体在底层操作上的不同,事实上,如上一章所述,指针也有非对象形态。笔者认为,无须从底层的角度上花费那么多唇舌,仅仅从字面上的语义就可以推翻数组名是一个指针的观点。

首先,在C/C++中,数组类型跟指针类型是两种不同的派生类型,数组名跟指针是两种不同类型的实体,把数组类型的实体说成“是”另一个类型的实体,本身就是荒谬的;

其次,a + 1在效果上之所以等同于p + 1,是因为a进行了数组到指针的隐式转换,这是一个转换的过程,是converted to而不是is a的过程。如果是两个相同的事物,又怎会有转换的过程呢?当把a放在a + 1表达式中时,a已经从一个数组名转换为一个指针,a是作为指针而不是数组名参与运算的;

第三,a + 1与p + 1是等效关系,不是等价关系。等价是相同事物的不同表现形式,而等效是不同事物的相同效果。把数组名说成是指针实际上把等效关系误解为等价关系。

因此,数组名不是指针,永远也不是,但在一定条件下,数组名可以转换为指针。

二、数组名是一个常量吗?

看见这句话有人会觉得奇怪,数组定义之后就不能改变了,数组名不就是个常量吗?在表达式中,数组名的确可以转换为一个不变的符号地址,但在C中,不变的实体不一定是常量!而且,C/C++有常量与常量表达式之分,常量与常量表达式是两种不同的实体,但常量表达式可以作为常量使用。C/C++中的常量虽然有所不同,但都不包括数组或数组名,而且数组名也不一定是常量表达式。

请在C90的编译器中编译如下代码,注意不能是C99和C++的,因为C99和C++不再规定数组的初始化器必须是常量表达式,会看不到效果:

int main( void )
{
    static int a[10], b[10];

    int c[10], d[10];

    int* e[] = { a, b };     /* A */

    int* f[] = { c, d };     /* B */

    return 0;

}

 

B为什么不能通过编译?是由于自动数组名并不是常量表达式。在C中,常量表达式必须是编译期的,只在运行期不变的实体不是常量表达式,请看标准的摘录:

6.6 Constant expressions

A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.

c和d是自动数组,首地址在编译期是不可知的,因为这样的对象在编译期还不存在;a和b是静态数组,静态对象从程序开始时就已存在,因此a和b的首地址在编译期是已知的,它们都属于常量表达式中的地址常量表达式。

所以,C/C++中的数组名,都不是常量。C中的数组名,是否常量表达式要视其存储连续性而定,全局数组、静态数组名都是常量表达式,而自动数组名不是。在C++中,由于不再规定常量表达式必须是编译期的,因此C++的数组名都是常量表达式。

本文转载自:http://blog.csdn.net/code_crash/article/details/4855018

共有 人打赏支持
北极心
粉丝 35
博文 39
码字总数 16464
作品 0
深圳
后端工程师
转:再再再论指针

  一直以来想把2005年写的《再再论指针》修改一下,因为经过了这么多年,对C/C++的理解与05年相比又有了一些进展。但公司的工作一直很忙,没有时间进行修改工作。直到10月初的长假...

IMGTN ⋅ 2012/06/20 ⋅ 1

C语言-第七章、用指针实现程序的灵活设计

7_1 指针的基本概念 _1.1 地址与指针 C语言中通常把地址成为指针。 _1.2 内存单元的指针与内存单元的内容 _1.3 变量的指针 变量的指针就是变量的地址 _1.4 直接访问与间接访问 7_2 指向变量的...

南风末 ⋅ 2016/11/04 ⋅ 0

C Primer Plus 第11章 字符串和字符串函数 11.1字符串表示和字符串I/O

当然,最基本的您已经知道了:字符串(character string)是以空字符(o)结尾的char数组。因此,您所学的数组和指针就可以用在字符串上。但是由于字符串的使用非常广泛,C提供了很多专为字符...

idreamo ⋅ 2016/08/17 ⋅ 0

【C++】第7章 函数 知识总结

《C++ Primer Plus》第7章知识点总结 简单的知识不再进行赘述 形参:函数头中用于接受传递值的变量 实参:传递给函数的值 使用C++函数,必须完成以下工作: (1)提供函数定义 (2)提供函数...

qq_37792173 ⋅ 2017/10/10 ⋅ 0

C语言-第八章、构造数据类型

8_1 结构体的概念和结构体变量 _1.1 结构体的概念 C语言中允许用户自己构造由不同数据类型的数据所组成的集合体,称为结构体。结构体属于数据类型,每一个结构体有一个名字,称为结构体名。一...

南风末 ⋅ 2016/11/05 ⋅ 0

从编译器角度分析C语言中数组名和指针的区别

数组名和指针是两个往往很容易让人们混淆的概念,很多人以为数组名就是一个指针,也有很多人知道数组名不同于指针但是仅知道数组名的值不能像指针一样改变,例如你可以写出下面这样的代码: ...

huang19015 ⋅ 2014/04/09 ⋅ 0

C Primer Plus 第10章 数组和指针 10.9 复合文字

假设需要向带有一个int参量的函数传递一个值,您可以传递一个Int变量,也可以传递一个int常量,比如5。在C99标准出现之前,数组参数的情况是不同的:可以传递数组,但没有所谓的数组常量可供...

idreamo ⋅ 2016/08/09 ⋅ 0

第一章 数组与指针概念剖析

数组与指针生来就是双胞胎,多数人就是从数组的学习开始指针的旅程的。在学习的过程中,很自然就会经常听到或见到关于数组与指针的各种各样的看法,下面我节选一些在各种论坛和文章里经常见到...

北极心 ⋅ 2016/08/11 ⋅ 0

C Primer Plus 第10章 数组和指针 10.3 指针和数组

我们举一个这种变相使用的例子:数组名同时也是该数组首元素的地址。也就是说,如果flizny是一个数组,下面的式子是正确的: flizny == &flizny[0] //数组名是该数组首元素的地址 flizny和&...

idreamo ⋅ 2016/07/25 ⋅ 0

C语言指针讲解(二)

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

长风留言 ⋅ 2017/11/13 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

zblog2.3版本的asp系统是否可以超越卢松松博客的流量[图]

最近访问zblog官网,发现zlbog-asp2.3版本已经进入测试阶段了,虽然正式版还没有发布,想必也不久了。那么作为aps纵横江湖十多年的今天,blog2.2版本应该已经成熟了,为什么还要发布这个2.3...

原创小博客 ⋅ 30分钟前 ⋅ 0

聊聊spring cloud的HystrixCircuitBreakerConfiguration

序 本文主要研究一下spring cloud的HystrixCircuitBreakerConfiguration HystrixCircuitBreakerConfiguration spring-cloud-netflix-core-2.0.0.RELEASE-sources.jar!/org/springframework/......

go4it ⋅ 54分钟前 ⋅ 0

二分查找

二分查找,也称折半查找、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于...

人觉非常君 ⋅ 今天 ⋅ 0

VS中使用X64汇编

需要注意的是,在X86项目中,可以使用__asm{}来嵌入汇编代码,但是在X64项目中,再也不能使用__asm{}来编写嵌入式汇编程序了,必须使用专门的.asm汇编文件来编写相应的汇编代码,然后在其它地...

simpower ⋅ 今天 ⋅ 0

ThreadPoolExecutor

ThreadPoolExecutor public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, ......

4rnold ⋅ 昨天 ⋅ 0

Java正无穷大、负无穷大以及NaN

问题来源:用Java代码写了一个计算公式,包含除法和对数和取反,在页面上出现了-infinity,不知道这是什么问题,网上找答案才明白意思是负的无穷大。 思考:为什么会出现这种情况呢?这是哪里...

young_chen ⋅ 昨天 ⋅ 0

前台对中文编码,后台解码

前台:encodeURI(sbzt) 后台:String param = URLDecoder.decode(sbzt,"UTF-8");

west_coast ⋅ 昨天 ⋅ 0

实验楼—MySQL基础课程-挑战3实验报告

按照文档要求创建数据库 sudo sercice mysql startwget http://labfile.oss.aliyuncs.com/courses/9/createdb2.sqlvim /home/shiyanlou/createdb2.sql#查看下数据库代码 代码创建了grade......

zhangjin7 ⋅ 昨天 ⋅ 0

一起读书《深入浅出nodejs》-node模块机制

node 模块机制 前言 说到node,就不免得提到JavaScript。JavaScript自诞生以来,经历了工具类库、组件库、前端框架、前端应用的变迁。通过无数开发人员的努力,JavaScript不断被类聚和抽象,...

小草先森 ⋅ 昨天 ⋅ 0

Java桌球小游戏

其实算不上一个游戏,就是两张图片,不停的重画,改变ball图片的位置。一个左右直线碰撞的,一个有角度碰撞的。 左右直线碰撞 package com.bjsxt.test;import javax.swing.*;import j...

森林之下 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部