当前位置:学者斋 >

计算机 >C语言 >

C语言学习趣事:关于C语言中复杂类型定义

C语言学习趣事:关于C语言中复杂类型定义

说到C语言, 很多人都是又爱又恨啊,既感到用C语言给了程序员极大的开放度和自由度,同时又对C语言的灵活性和高难度性。让我们一起来看看下面这则关于C语言的趣事吧!

C语言学习趣事:关于C语言中复杂类型定义

  C语言学习趣事:关于C语言中复杂类型定义

就目前中国教育做法来说吧,估计大部分高校给学生选的入门级语言就是C语言, 然而经过大学几年的学习,大部分的学生也只能做到写个“HelloWord” 这样的代码。即便是计算机专业的毕业生,在离开学校后,大部分也是对C语言的掌握也只是停留在简单的应用,更不用说非计算机专业的学生了, 就像我这样非计算机专业毕业的,到现在也不会用C语言编写一个具有实际应用意义的程序。

估计C语言中最难让人摆平的估计要算是指针了, 不但难以捉摸,同时又非常复杂。尤其是当具有复杂的数据类型定义的时候。

  1、指针

何谓指针,这个问题估计不需要说明了。从硬件角度来看,指针应该指的是CPU地址总线上呈现的电平状态的数字化表示,估计大家都知道经典8051中的寻址过程, 通过地址总线选择需要操作的存储地址;在8051中我们知道共有16根地址总线, 因此具有2^16方的可寻址空间,就是具有64K的寻址空间。当所有地址总线呈现低电平时选择的是0000_0000_0000_0000,即0000H的地址;而当地址总线全部呈现高电平状态则选择的是1111_1111_1111_1111,即FFFFH的地址。这个同样适合8086架构下的寻址, 如果用汇编语言编写程序,就可以直接指定要操作的地址,或者说可以直接寻址地址。

  2、C语言中的指针

C语言高效的一个原因就在于可以直接对地址进行操作,虽然不如汇编语言那样的直接,但是相对于其他一些语言例如VB等语言来说,C的指针操作已经非常“高级”了。C语言的发明者真够神的, 发明了指针这样难以驾驭的指针,但是C语言中指针的定义则非常的简单。

  3、C语言中指针类型定义

定义语法:

指针指向的基类型 * 指针标识符

例如: int * pValue; 这样就定义了一个可以指向int类型变量的指针,哈哈,还真神奇,这样就可以控制硬件的连线上的电平了,

  4、指针用法




  5、复杂指针定义:

指针常量和常量指针:


int const * p; // 定义一个指向常量的指针, 这个指针可以随意改变指向

int * const p; //定义一个指针常量, 这个指针只能指向一个变量,并且指向后不能在改变

const int * const p; //定义一个指向常量的指针常量, 指针变量本身的值不可修改,并且指针指向的变量也不能被修改。

例如:

int * const pconst=&test; //这里定义的pconst指针就不能再指向别的整型变量

const int constvalue=50; //定义一个整型常量, 等价于 int const constvalue

int const *constvar=&constvalue; //定义一个指向整型常量的指针, 指针指向的变量值不可修改,但是指针指向可以更改

const int * const constpvar=&constvalue; //定义一个指向整型常量的指针, 指针的`指向不可修改。

这类指针定义的一个简单的阅读方法就看: const修饰的是什么, 当其修饰数据类型的时候则定义的是数据类型的变量不能修改;

当修饰的是指针变量的时候则指针的指向不可改变。

从上面的实例可以看出: 当没有指针存在的时候,const 的位置不会影响变量的使用,但是也可以根据其修饰的对象来理解。

  指针数组和数组指针

int *p[];

int (*p)[];

这两类指针的定义着实非常令人纠结啊, 到底怎么解释和理解呢? 一团雾水啊...........

首先看第一个: int *p[ ];

如上定义: p 的左右各有一个运算符, *和[]; 指针运算符和数组运算符, 在C规范里面, 数组运算符的优先级别高于指针运算符。

在这里同样可以利用运算符的优先级来理解这个指针,

因为[ ]的优先级高于 * ,引起p应该先和[ ]结合,这里就是可以看出,p是一个数组, 然后p再与* 结合,可以看出p是一个指针,最后看数据基类型,p的数据基类型是int型的;综合上面的描述可以知道: p被定义为一个存储int型指针的数组。 即p是一个数组,其数组元素的类型是int型指针。

如果要引用其指向的变量的内容的话,可以这样使用: int sizex=*p[0]; 这就是指针数组, 就是说数组元素全是指针。

接下来看第二个:

int (*p)[];

同样可以利用优先级别来理解: ()和[ ]具有相同的优先级, 因此 p 是一个指针, 然后再用 [ ]来修饰p; 则可以看出p将指向一个数组类型数据,这就是说 int (*p)[]是指向int型数组的指针。这个指针不能指向别的数组。

例如:

int iArray[4][5];

int (*pArray)[5];

pArray=iArray; //这样可以编译成功, 因为pArray的类型是 : int (*) [] ; 而 iArray 的类型是 int [4][5]; 可以进行数据类型的转换

但是如果:

pArray=&iArray; //编译不成功,为什么呢? 因为pArray的类型是 : int (*) [] ; 而&iArray 的类型是 int *[][];很显然数据类型不一样

如果:

pArray=&iArray[0]; // 编译成功。

我们知道在二维数组中, 可以这样理解:其行元素相当于指针,即 iArray[0]、 iArray[1]、 iArray[2]、iArray[3], 但是其存储的并不是指针,其存储的是一个具有5个元素数组的首地址。但是需要这样才能 iArray=&iArray[0]; (这里二维数组的首地址与 iArray[0] 的地址相同 )。

对于数组指针的理解,可以将变量去除后然后进行剥离得出其数据类型然后进行理解。例如:

pArray: int (*)[];

&iArray[0]: int (*)[ ];

特殊的引用方式:

int iArray[4];

int (*pArray)[4]=NULL; //指定义不初始化同样可以,但是为了防止出现游离指针,最好用NULL初始化;

pArray=&iArray; // 这个编译成功

指向函数的数组指针

int (*a[10])(int); // 这个定义一个数组,数组共有10个元素,每个元素存储一个指向 int (*)(int )函数的指针, 同样利用优先级来理解。

  指针的指针

  • 文章版权属于文章作者所有,转载请注明 https://xuezhezhai.com/zh-sg/jsj/cyuyan/k909vp.html