C语言语义缺陷(一)

前言

在一个句子,哪怕其中的每个单词都拼写正确,而且语法也无懈可击,仍然可能有歧义或者并非书写者希望表达的意思。程序也有可能表面上是一个意思,而实际上的意思却相差甚远。本篇讲述了几种可能引起上述歧义的程序书写方式

1、指针与数组

C语言中,指针与数组这两个概念之间的联系是十分密切的

C语言中的数组有两个需要注意的方面:

1、C语言中只有一维数组,而且数组大小在声明数组时就需要确定下来,不过数组中的元素可以是任何类型的对象,当然也可以是另外一个数组,这样要"仿真"出一个多维数组就不是一件难事

C99标准允许变长数组(VLA),GCC编译器中实现了变长数组,但细节与C99标准不完全一致

2、对于一个数组,我们只能做两件事:确定该数组的大小以及获得指向该数组首元素(下标为零)的指针。其它有关数组的操作,哪怕它们乍看上去是以数组下标进行运算的,实际上都是通过指针进行的。换句话说,任何一个数组下标运算都等同于一个对应的指针运算,因此我们完全可以依据指针行为定义数组下标的行为。

指针与数组的关系

1、如果一个指针指向的是数组中的第一个元素,那么我们只要给这个指针加/减1,就能够得到指向该数组中下/上一个元素的指针,其它数字同理类推

这句话暗示了这样一个事实:给一个指针加上一个整数,与给该指针的二进制表示加上同样的整数,二者的含义截然不同。如果指针ip指向一个整数,那么ip+1指向的是该计算机内存中的下一个整数,在大多数现代计算机中,它都不同于ip所指向地址的下一个内存位置

2、如果两个指针指向同一数组中的元素,这两个指针相减的结果是有意义的:

cpp 复制代码
int *q = p + i;

p指针与q指针的差值就是两指针指向的元素之间的位置的差值(意思是这个意思) ,但是如果它们指向的不是同一个数组,那么即使它们所指向的地址在内存中的位置正好间隔一个数组元素的整数倍,所得的结果仍然无法保证其正确性

**3、如果我们在该出现指针的地方,采用了数组名代替,**数组名就是该数组首元素的地址:

cpp 复制代码
//正确,将数组a中下标为0的元素的地址赋值给了指针p
p = a
//错误
p = &a

p=&a这种写法在ANSI C标准中是非法的,因为**&a是一个指向数组的指针此时取出的地址是整个数组的地址而非数组首元素的地址,而p是一个指向整型变量(数组中某个整型元素)的指针,它们的类型不匹配。**

4、p是一个指向数组的指针,p = p + 1 == p++

5、*数组名,此时的数组名表示数组首元素地址,该语句可以将数组首元素的值替换

cpp 复制代码
*a = 84;

它等价于*(a+0),同理,*(a+1)是数组a中下标为1的元素的引用,依次类推。概而言之,*(a+i)即数组a中下标为i的元素的引用,由于这种写法十分常用,所以C语言将它变为了另一种形式ai,

ai == *(a+i)
~未完待续~

2、非数组的指针

3、作为参数的数组声明

4、避免"穷隅法"

5、空指针并非空字符串

~over~

相关推荐
北冥you鱼1 分钟前
Go 语言 Channel 机制详解:从原理到实战
开发语言·后端·golang
谢亮_vipxieliang4 分钟前
Go 并发控制进阶:sync 包高级原语与 Context 生命周期管理
开发语言·后端·golang
xuxigifxfh19 分钟前
HJ5 进制转换
java·开发语言·华为机考
denlaku21 分钟前
JDK 12 新特性详解
java·开发语言
Nebula_g25 分钟前
JavaSE拓展:可变参数
java·开发语言·算法·安全·javase·可变参数
Logic10136 分钟前
C语言/数据结构字符串题解:最短循环节——找出能重复构成原串的最短基础子串
c语言·数据结构·字符串·枚举·时间复杂度·算法题·kmp优化
我就是不信1 小时前
CuTest:轻量级 C 语言单元测试框架实战指南
c语言·单元测试·log4j
anew___1 小时前
《从零手写操作系统 (30):环境变量与进程上下文——export/unset与继承语义》
java·开发语言·网络·jvm·算法
Cx330❀1 小时前
Qt 多线程深度解析:从底层原理到 UI 线程与同步实战
开发语言·qt·ui·搜索引擎·性能优化·图形渲染
谢亮_vipxieliang1 小时前
Go GMP调度模型——从原理到实战的完整指南
开发语言·网络·golang