|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
首先,在C语言中,最难的就是定义变量,给变量赋值。其实所有的C程序拉出来看到的都是在定义变量,给变量赋值,中间的程序通过运算得到的结果,也可以算是给变量赋值。
(一)先说定义变量:
因为变量名都是自己定义的标示符,然后最重要的就是变量的类型了。虽然大多C语言书上 都列举出了众多的数据类型,但是个人理解,那些都是最基本的一些东西,其实还有很多中类型 我们经常遇到,却不知道 这些还是数据的类型。
一,指针类型;
int * ,short * ,char *, int **,char**, long int ****************;
这些都是指针类型,很显然,可以看出 指针类型就是在基本数据类型前面加个* , 例如定义一个指针变量,
int * p; 这个变量p,就有两种含义,第一是,这是一个指针变量,第二是他指向int类型。 我们都知道对于32位pc机, 指针变量都是四个字节。 int ** p;对于变量p, 也有两个含义,第一这是一个指针变量,第二,它指向一个int*类型.
二,数组类型。
这里估计,有人就质疑了,C语言里面还有数组类型吗? 有。并且我们一直在写,一直在用,我们一直不知道,是因为C语言的书写方式导致我们不知道有这种类型。 对于一个一维数组, int a[10]; C语言的书是这样解释这个东西的,这是个一维数组,也就是一次性定义了十个变量。 在内存中呈线性排列。。。。。。 其实我个人理解这个东西应该这样定义,这是一(个包含10个int 元素的 类型的) 变量。我们在描述一个变量的时候,总说,这是一个XXX类型的变量,所以在这里对于int a[10];应该这样描述,这是一个有10个int元素的 类型的 变量a; 所以写成 这样 int [10] a; 这是一个变量但是它包含十个元素,这是不是跟我们学过的一个东西特别像? 结构体, 结构体不就是包含里XXX 元素的类型 ,然后用这种类型定义了一个变量,叫做结构体变量。 C语言给结构体类型起名字了,却没给数组类型起名字,所以我们不知道。但是定义数组的时候写成
int [10] a; 这样 很多编译器 都编译不通过,或者说没有编译器认识它,之所以这样写,只是要明白,数组的原理,因为后面对于能正确理解数组指针,至关重要。。。。
三,指针数组;
指针数组很简单,就是int * a[10]; 类型换了一下而已,按照上面的解释更直观一点写成int *[10] a; 这样,就可以解释为,定义了(一个包含10个指针类型元素的 )这种类型的变量 a;
四,数组指针,
若看完了上面对于数组类型的 解释以后,对于数组指针是不是已经很简单了。 定义一个指针数组类型的变量 是
int * a[10];前面说了 ,更直观的写成:
int*[10] a; 那么定义一个指针变量,就是在原有类型前面加一个*, 也就是int* [10] * p; 但是C语言里面不能这样写, 规定要把[10] 写到后面,所以就成了int * * p[10]; 但是现在这样就有个问题了,之前有个[10]在中间隔开,倒是可以区别,(int *[10])* p; 现在[10] 写到了后面,无法区别这两个*,到底属于那边的,加空格没作用,所以只能加最有权威的分隔符() 那么就成了 int * (*p)[10]; 这里定义了一个指向(有10个int*类型元素的数组)的类型的 变量 p;
不好意思,这里有些太绕口,不好理解,确实不好理解,之所以不好理解,是因为我们书写习惯了,看习惯了目前C的这种书写形式,对一些东西根深蒂固。就像很多新人最开始学习指针的时候都是这样定义的,int *p; 这样写虽能编译通过,但是他已经把指针理解错了, 指针不就是一个普通变量,int * p; 就是一个变量p,类型是 int *类型。。......对于学习C语言的新人,要永远记住,对于任何变量,都是某某某类型 的 一个变量。 这个类型可以是任何类型。 不光是书上的那几种类型,有很多类型都是我们自己定义的,例如int ******** 这种类型。
上面说了这么多,最重要的是最近看到前面有几个帖子对于指针和数组。有很多新人都很纠结,这个东西理解很容易进入误区,因为这所有东西都是建立在编译器的前提下的。或许你理解的是对的,但是编译没通过,你会认为这是错的,其实没必要理解是一回事,编译是另一回事;;
五;关于数组和数组名,以及数组指针赋值。
对于一维数组 int a[10]; 它有10个int 类型的元素 在内存单元中呈线性排列,首元素的地址就是这个数组的首地址,也就是 &a[0], 但是C语法规定可以简写成a; 就在这里出现了一个严重的问题,我之前说的 int a[10]; 等于是个int [10] a;
通俗一点说就是int [10] 类型的变量 a;所以a的类型就是 int [10], 这就是为什么printf("%d\n",sizeof(a));会打印出40,因为a 是一个拥有十个元素的数组类型的变量。但是前面说了C语法里面吧&a[0]简写成a;
用过指针的童鞋应该都知道 对于XXX类型的变量,前面加个&。(&变量名)这就是一个表达式了,而这个表达式的类型就是这个变量原来的某某某类型加个* 就是XXX*类型,所以&a[0] 的类型就是int *类型了 ,所以定义一个指针变量,int * p=&a[0]; //p=a;这样都正确,{(但是按照我的理论,p=a;能编译通过,a的类型是int [10] 类型,p是int* 类型,p=a能编译通过不是偶然而是必然,绝不是因为a是&a[0]的简写,而是我个人认为int[10] 跟int* 类型本来就匹配。是同一种类型(推理过程下文有详解))},因为赋值两边类型匹配。无可厚非都是int *类型。 若定义一个数组指针 int (*p)[10], 这里p的类型是int (*)[10] 按我之前的书写方式就是int [10] * ;这种类型,很直观.对于数组 int a[10], 刚才说了 a的类型是 int[10], 所以&a这个表达式的类型就是 int[10]*类型的。所以 int a[10]; int (*p)[10]; p=&a; 这样可以赋值,因为两边类型匹配,无可厚非。这不是谁规定的,真理都是有根据的。。。
下面解释下二维数组;在说二维数组之前,先解释下刚才留下的那个问题:就是int [10] 这个类型跟int *类型为什么匹配的问题,对于一维数组int[10] a; int b; b=*a; 这样没有问题吧,那就说明*a的类型跟b的类型一致,都是int 类型,a的类型本来是int [10] *a就成了int 类型.。大家都知道 只有对于一个指针变量,也就是带*号的类型的表达式 才可以(*非常量表达式),这样之后表达式的类型就变成原来的类型去掉一个*,例如int *** m; *m的类型就是 int**. 想必这大家都知道吧。回到原题
a是int [10] 类型的,*a成了int 类型,所以int[10] ,也可以看成是int *类型,两者“本是同根生,书写却不同”。这就很明了为什么:
int a[10]; int * p=a;这样了。
对于二维数组 int a[5][10]; 可以写成int [10] a[5]; 继续 (int [10])[5] a;这里 的小括号至关重要,我这样写可能大家一时半会反应不过来,但是你若认真的看完了前面我对一维数组的解释之后,并且看懂的话这个就不难看懂。 我只所以再不用通俗语言去解释这个东西,是因为C里面不能这样写,并且没有给这种东西起名字,不像结构体,结构体数组。都有名字,其实这个跟结构体就是一回事,都是个大变量,里面包含很多元素。同一个道理的,闲话不扯,入正题。前面刚解释了对于XXX[]这种类型跟XXX*这种类型是相同的。那么a的类型是 (int [10])[5] ,也就是int [10] *类型。 这又让我们回想起了一个东西,什么呢?数组指针,int (*p)[10]; 这里p的类型是int (*)[10] ,按我书写方式就是int [10] *,这不是跟a的类型匹配了吗?所以对于代码:
int a[5][10];
int (*p)[10];
p=a; 这样可以直接赋值,因为类型匹配,无可厚非。。。。不是老师说的,也不是书上说的,这不是规定的。要相信世间万物必有其存在的道理。。。。。。。。。。。。。
某不才,仓促间用了几个小时完成了这篇文章,里面肯定漏洞百出,若那位兄弟看到可告知某,某不甚感激。。。。。。另外上述纯属个人理解,若那位兄弟有其他的更好的解释,愿分享交流。
|
评分
-
查看全部评分
|