C语言学习之 数组,指针,字符串. (一)

原创
2012/11/03 22:31
阅读数 163

此文由来: 是看到野鬼发表的关于C语言知识内容后,一激动,手一痒.回了一篇.可惜误操作让回复没能保存.
 之后再写就是下面的内容. 野鬼发表的内容 http://www.oschina.net/question/249672_77341

计算机是按照指令进行操作的. C语言与汇编比算高级语言, 但它仍然很"低级".
计算机操作的都是数字, 差别只是 直接操作与间接操作. C仍然可以用这些概念来了解 数组与指针的关系.
比如: int i; i=0; i++; 这3条语句就是属于直接操作, 操作数是 i, 操作的目标也是i;
 另外一种 int *p; *p=0; (*p)++; 这3条语句属于间接操作,操作数是p,操作目的(*p);
记住一点,计算机操作的都是数字,也就是 i, 和 p 都是数字, 他们都可以用 printf("%d %d",i,p);来看看具体是什么数字. 这里的差别只是i是一个具体的被操作数,而p只是一个指针,例子中改变的不是p这个数,而是p对应的内容. p所对应的内容是一个int 类型. 所以声明 用的是int *p;
另外,(*p)++; 这个括号不可以少, 否则会变成 p这个指针自增,然后取内容.p自增后指向那里.不确定,当然是野指针,会出问题的.后话,以后会讨论, 里面有戏法,这个是C的优点.善加利用会有好处.

居然有人顶我的回帖,这给我增加了信心. 好吧,我会继续完善我的跟帖,帮助与我同一起跑线的朋友一起学习C语言. 这里声明一点,我也是学习C语言的新手. 跟帖内容是我的理解, 并非是正确的解释. 具体正确解释还是请大家听取野鬼的指导文章. 也欢迎给位朋友指出我表述中存在的问题,好帮助我更准确的学习这门语言. 愿我与大家共同进步.

之前表述内容是了解 计算机在处理信息方面采用的方式, 重点还是"一切都是数字". 
接下来说说所有变量都有存储位置. 当然,这个是相对来讲的.程序编译以及优化过程中这些概念不一定合适, 但是,对与学习这门语言来说.还是认为这句话是对的比较好.(虽然这句话本身就是错的).
 继续给例子, int i; 这个语句声明了一个变量i(我也不知道如何说明这个i, 姑且认为他是一个变量的存储空间).  i就表示一个存储空间, 他的大小 足够放的下一个 int 内容. int 是什么? 是一种类型.这些概念之前有讲过, 可以看之前内容加深理解.  这里可以大体上理解为 "宽度" 如果以8位表示一个字节的话, char 类型就是占用一个字节, int 类型占用 sizeof(int) 个字节, sizeof(int) 是什么?  sizeof 是操作符. 用来返回 目标 占用的存储空间大小, 以字节为单位表示. sizeof(char) 返回肯定是1. 这个就叫标准. sizeof(int) 会返回什么? 标准中没规定具体数值. 根据编译器以及对编译目标平台来决定. sizeof用来干什么? 备用. 
之后说说 数组.  char a[9];  这个语句就是定义一个数组. 数组名是a,  数组大小是9个char 大小. 占用空间 计算方式为 9*(sizeof(char)). sizeof(char) =1 (这个是规定). 所以 9*sizeof(char) =9; 所以 char a[9]  会占用9个字节的存储空间. char a[8] 会占用8个字节的存储空间. 所以 char a[9] 是用来声明 a 地址内会有 9 个字节的空间可以用以程序使用.  short a[9] 会有 18个字节的空间, 此时a 的大小有 9*sizeof(short) = 18.  sizeof(short) = 2 也是规定.   在这里记住一点, a 也是有数值的. 所有操作都是用来操作数字的. a可以理解为一个 存储空间的首地址. 一切皆为数字.

再来说一下指针与数组的关系. 
 看例子. char a[9]; char *pa; pa=a; 这3条语句比较好理解. 首先 声明了一个 大小为 9*sizeof(char) 的存储空间, 入口地址是 a , 之后声明了一个 存储空间, 存放pa, 它是一个指针.大小是指针的存储空间--> sizeof(void *);  类型不同啊. 管他呢.  指针大小在同一平台下是 不变的.   最后 pa=a ; 意思是将第二条 申请的空间内容 存储成 a 的值. a 是什么?  a其实就是一个数字, 是 数组存储位置的首地址.  下面要说的就是神奇的地方. 指针运算.

变戏法, 指针运算
依然看上面的例子.  a 表示一个长度为9的存储空间, a也是个数字, a也可以表示为9个存储空间的首地址. 由此可以理解为, 数组,是一段连续空间的表示形式. 数组名是空间首地址.
在这里需要引入一个概念, 数组指针, 数组指针是区别与指针数组的. 数组指针实际上是一个指针, 声明的时候会分配一个存储空间给它,分配给他的存储空间长度为 指针的长度, 内容是一段指向连续空间的存储空间首地址.
先来说一下指针,数组之间的魔法. 例子中 pa 是一个指针, 类型是 char . a 是一个数组, 类型是 char 的数组,  pa=a; 后,会发生什么呢, pa 是一个char 类型的指针, 指向的内容类型也就是一个 char, 所以 *pa 就是一个char 类型. 来看下:
char a[9]="9742"; /*声明并赋值*/ 
char *pa;
pa=a;/*这段可以简单写成 char *pa=a; 声明并赋值*/
printf("%c\n", *pa);/* 这段会输出 字符 9 并换行. */
pa++; /* 指针运算,自增 */
printf("%c\n", *pa);  /* 这段会输出字符 7, 并换行*/

其实,上面这段是一个小魔术, 不过这个魔术会在C语言中随处可见. 原因很简单. C代码当中,到处都是指针. 为了代码的优美, 指针遍布各个角落, 这样的魔术也遍布个个角落. 相对于数组, 指针可以通过修改一个数字来操作改变后的内容,相对于数组只能通过下标的不同来修改要方便的.
为加深印象. 查看下面的代码.
 short a[9]; /*声明数组*/
a[0] = 9;
a[1] = 1;
a[2] = 7;
a[3] = 4;
a[4] = 8;
short *pa; pa=a; 
printf("%d\n", *pa);
pa++;
printf("%d\n", *pa);
printf("%d\n", *(pa+1)); 
printf("%d\n", *(pa+2));  
当然,在这里, 也可以用printf("%d\n", *(a+1)); 来实现第二个输出语句所实现的目的. 但是却没办法执行 a++; 这样的操作.  或许会有疑问, 既然可以*(a+1) 为什么还要 *(pa+1);
这就引出更多的内容. tyepdef

我不是万恶之源,我只是一粒沙.我是 typedef
为什么要这么说. 因为我不是让代码变得 凌乱的 罪魁祸首, 我只是一个让一切变得好起来的帮手.我是typedef. 请好好待我.

还是例子:
typedef char ta[5];/* 一个5字节的连续空间 */
int fa() { 
ta a;
return 0;
}
定义了一个函数 fa, 返回类型是 int ,  里面声明了一个变量 a;
a 其实就是一个 数组,  和 char b[5]; 效果是一样的. 这没什么好稀奇的.
使用的时候可以 a[0],a[1],a[2]; 类似的, char b[5]在使用的时候也可以是 b[0],b[1],b[2],b[3]

ta a[3];  a[3] 的效果和 char b[3][5]; 是一样的. 二维数组. 没错.就是他, 可以更简单一些.
使用的时候, 可以 a[0][0]... a[2][4]; 是这样. 那有什么优势呢?  魔术,魔法. 指针是很神奇的东西.


展开阅读全文
打赏
0
2 收藏
分享
加载中
更多评论
打赏
0 评论
2 收藏
0
分享
返回顶部
顶部