文档章节

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

北极心
 北极心
发布于 2016/08/11 10:11
字数 1216
阅读 3
收藏 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

共有 人打赏支持
北极心
粉丝 34
博文 39
码字总数 16464
作品 0
深圳
后端工程师
C Primer Plus 第11章 字符串和字符串函数 11.1字符串表示和字符串I/O

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

idreamo
2016/08/17
22
0
C语言-第七章、用指针实现程序的灵活设计

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

南风末
2016/11/04
11
0
【C++】第7章 函数 知识总结

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

qq_37792173
2017/10/10
0
0
C语言-第八章、构造数据类型

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

南风末
2016/11/05
7
0
从编译器角度分析C语言中数组名和指针的区别

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

huang19015
2014/04/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

180.mariadb 主从复制

参考:https://blog.csdn.net/chengxuzaza/article/details/62042920 睡觉睡觉,明天写 1.效果 当主库中数据有变化的时候,从库就自动同步 2. 环境要求 至少两台 linux服务器 (教程:https...

Lucky_Me
6分钟前
0
0
erlng file id3v1 id3v1.1

%% ---%% Excerpted from "Programming Erlang",%% published by The Pragmatic Bookshelf.%% Copyrights apply to this code. It may not be used to create training material, %% ......

xueyuse0012
8分钟前
0
0
RabbitMq的安装

环境Centos6.5 32位 JDK 1.7.8 Jdk的卸载 rpm -qa|grep jdk yum –y remove 上边的安装包 JDK的安装 Rpm –ivh jdk安装包 配置环境变量 export JAVA_BIN=/usr/java/jdk1.7.0_80/bin export J......

DemonsI
12分钟前
0
0
http和https协议

HTTPS全称为Hypertext Transfer Protocol over Secure Socket Layer,中文含义为“超文本传输协议在安全加密字层”,简单来说就是加密数据传输,通俗的说就是安全连接。 HTTPS安全超文本传输...

寰宇01
18分钟前
0
0
vue内引入语音播报功能

在vue项目中引入语音播报,使用的科大讯飞语音接入, 具体思路为每次接收到语音信息后存入一个数组,然后监听这个数组,开始冲第一个索引播放,并且同时根据vuex getter 来动态删减数量 给a...

originDu
26分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部