数组、指针、C标准……

说起指针,初学C语言的时候,总是让人感觉似懂非懂。
后来,学习到了很多操作系统、计算机组成原理、体系结构的知识,逐渐深切地认识到:指针其实就是一块一个字长大小的内存单元,它上面保存着 被其指向的 另一块内存的地址。
理解了指针的实现,由于指针所引发的诸多疑难杂症也很容易就一一治愈。于是在某简历中自诩“精通C语言”……
直到有一天,在论坛到看到一些关于C标准的讨论,才发觉C语言比我所理解的要宽泛得多……

有这么个例子:
int a[10], *p;
for (p=a+9; p>=a; p--) {
printf("%d\n", *p);
}
这段代码有问题吗?

看到这个问题的时候,我的第一感觉是:这帮人太无聊了,这段代码怎么会有问题?
但是正确答案却是:有问题!
为什么呢?假设a==0会怎样?p--会溢出,于是p永远比a大,造成死循环……(或者在循环过程中程序就崩溃了。)

那么,改成这样写呢?
int a[10], *p;
for (p=a; p<=a+9; p++) {
printf("%d\n", *p);
}
这样就没问题。
为什么呢?如果p++溢出,p永远都会小于a+9,同样是死循环。那么,既然p--会溢出,p++为什么就不会?

这就要看C标准了:
c99, 6.5.6 Additive operators

When an expression that has integer type is added to or subtracted from a pointer, the
result has the type of the pointer operand. If the pointer operand points to an element of
an array object, and the array is large enough, the result points to an element offset from
the original element such that the difference of the subscripts of the resulting and original
array elements equals the integer expression. In other words, if the expression P points to
the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and
(P)-N (where N has the value n) point to, respectively, the i+n-th and i?n-th elements of
the array object, provided they exist. Moreover, if the expression P points to the last
element of an array object, the expression (P)+1 points one past the last element of the
array object, and if the expression Q points one past the last element of an array object,
the expression (Q)-1 points to the last element of the array object. If both the pointer
operand and the result point to elements of the same array object, or one past the last
element of the array object, the evaluation shall not produce an overflow; otherwise, the
behavior is undefined. If the result points one past the last element of the array object, it
shall not be used as the operand of a unary * operator that is evaluated.

这条标准提到,参加加减运算的指针及其结果,只有都指向同一数组内(包括数组元素和数组之后的第一个“元素”)时,才是合法的,否则行为是未定义。
也就是说,标准规则了上面的p++是不溢出的,而p--则未定义。
尽管我到现在还觉得这条标准有些蛮横(凭什么p++不溢出,p--就是未定义呢?要么都不溢出、要么都未定义,对称一点多好!),但是我还是很认同标准中诸如此类的许多概念与表述。

在此之前,我总是对一些网友“啃标准”的行为不以为然,何苦让那些概念与规则把自己绕晕,看看实现,一切都一目了解。但是现在我觉得研究标准也还是很有意义的。

C标准描述的是一个抽象的语言逻辑,而现在我们使用的C语言则是在特定计算机条件下的C语言实现。
如果将来计算机环境发生重大变革,C语言还是C语言,但是C语言的实现则可能大相径庭了。比如(假想一下)内存可能不再是一维的了,于是指向内存的指针也需要保存x、y、z这样的多维信息。等等。
理论上说,不管计算机怎么变革,标准的C语言程序都能无缝的移植。当然,现在不利用到操作系统特性(比如多进程、进程间通信、等等等等)并且又很有价值的程序实在太少了,无缝移植我觉得只是个传说。
但是研究研究标准,对深刻理解语言本身还是很有益处的。

时间: 2024-10-30 03:03:44

数组、指针、C标准……的相关文章

ios-避免数组指针出现崩溃问题

问题描述 避免数组指针出现崩溃问题 如果在访问每个指针之前检查数组指针,像下面的代码中,是不是可以避免数组出现崩溃?会不会出现其他问题? -(BOOL)checkIndexAvailability:(NSArray *)array_ withIndex:(int)index_ { if ((array_.count-1)>=index_) { return TRUE; } return FALSE; } 在访问数组时的调用方式: if ([self checkIndexAvailability:

Php核心技术-数组指针

  数组指针的操作: 移动数组指针的操作: Next() 向下 同时会获得当前元素的值. Prev() 向上同时会获得当前元素的值. End() 移动到最后一个元素单元 获得最后一个元素的值 Reset() 移动到第一个单元 获得第一个元素的值. 如果移动不成功,返回false. 参数都为需要操作的数组,并且是引用传递.   获得指针指向的元素的信息: Key();//获得当前数组指针指向的元素下标 Current();//获得当前数组指针指向的元素 只获取数据 不移动指针 还有一个混合的操作:

C/C++中多维数组指针作为函数参数传递

注意此题的意思在于输入3个同4门课的成绩,计算出平均值和显示其中一个同学的4门课成绩,此例是对多维数组指针和多维数组的指针作为涵数参数传递的总结,认真联系和体会可以很好的了解多维数组指针的概念到底是什么! #include <stdio.h> main() { void search_score(); /* 定义自定义涵数类型为不返回型 */ void count_avg(); /* 定义自定义涵数类型为不返回型 */ static float a[3][4]={{97,45.5,66,77}

C语言数组指针的小例子

1.功能:输入6个学生的5门课程成绩,计算出每个学生的平均分和每门课程的平均分. 2.C语言实现代码:(其实就是用二维数组来实现的,二维数组的引用传递使用数组指针来完成) 复制代码 代码如下: #include <stdio.h> #define STUDENT 5 #define SCORE 6 void input_array(float (*score)[STUDENT]); void avg_score(float (*score)[STUDENT]); void avg_course

C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

原文:C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表本文由 arthinking 发表于315 天前 ⁄ itzhai.com原创文章 ⁄ C语言 ⁄ 评论数 3 ⁄ 被围观 1,775 views+   指针数组: 在一个数组中,如果它的元素全部都是指针

C++中的指针、数组指针与指针数组、函数指针与指针函数

C++中的指针.数组指针与指针数组.函数指针与指针函数 本文从初学者的角度,深入浅出地详解什么是指针.如何使用指针.如何定义指针.如何定义数组指针和函数指针,并给出对应的实例演示:接着,区别了数组指针与指针数组.函数指针与指针函数:最后,对最常混淆的引用传递.值传递和指针传递做了区处. C++中一个重要的特性就是指针,指针不仅具有获得地址的能力,还具有操作地址的能力.指针可以用于数组.或作为函数的参数,用来访问内存和对内存的操作,指针的使用使得C++很高效,但是指针也非常危险,使用不当会带来比较

c语言-数组指针指向数组的问题

问题描述 数组指针指向数组的问题 int main() { char a[5]={'A','B','C','D'}; char (*p3)[10] = &a; char (*p4)[10] = a; return 0; } int main() { char a[5]={'A','B','C','D'}; char (*p3)[3] = &a; char (*p4)[3] = a; return 0; } 这两个式子怎么理解啊?貌似指针这样指有点问题,面试题上看到的,也是醉的不行.p3+1

c语言数组指针,不报错,就停止工作,请问哪里错了

问题描述 c语言数组指针,不报错,就停止工作,请问哪里错了 第一次提问,多包含,也不报错,为什么一运行就按停止工作报错 #include #include #include struct arr { int *pbase;//第一个元素的首地址 int len;//数组所能容纳的最大元素个数 int cnt;//当前数组有效元素个数 }; void init_arr(struct arr *p1,int length) { (p1->pbase) = (int *)malloc(sizeof(i

c++ 指针-C++中数组指针怎么输出每一个所谓的一维数组的头一个元素

问题描述 C++中数组指针怎么输出每一个所谓的一维数组的头一个元素 #includeusing namespace std;int main(){int a[3][4] = {{1357}{9111315}{17192122}};int (* p)[4];for(p = a; p < a + 3; p++){cout << ((p + 0)) << "" "";cout << *p <<endl;}cout &l

关于指针数组和数组指针的区别

问题描述 关于指针数组和数组指针的区别 为什么上面那个就代表指针数组下面的就代表数组指针了呢 解决方案 指针数组:array of pointers,即用于存储指针的数组,也就是数组元素都是指针.和普通的变量定义一样,如果是要数组,变量名就是:a[4],数组存储的类型就是:int* 例如int* a[4] 数组指针:a pointer to an array,即指向数组的指针,和普通变量一样的定义,表示指针变量名 *a:指针int[]类型,int 以上是个人理解,如果有错误还请指正 解决方案二: