03月 1st, 2010只见过那合久的分了,没见过分久的和
嗯,就是这样。新域名,老blog。
访问的话,请移步:
域名很好记,sray有点猥琐。
不用什么blog了,不用什么www了,也不用com、cn什么的了
多罗嗦一句,希望订阅了这里的,改订阅
http://feed.srayu.ws
链接、收藏了这里的,改成
srayu.ws
谢谢大家长期以来的关注
嗯,就是这样。新域名,老blog。
访问的话,请移步:
域名很好记,sray有点猥琐。
不用什么blog了,不用什么www了,也不用com、cn什么的了
多罗嗦一句,希望订阅了这里的,改订阅
http://feed.srayu.ws
链接、收藏了这里的,改成
srayu.ws
谢谢大家长期以来的关注
毫无疑问,C语言里,最麻烦的地方,就是指针和数组的互相转换问题了。因为,它俩实质上就是一个东西。
今天要说的是,如何将简单的一维数组和多位数组互相转换。
我们知道,在C语言的申明中,我们可以申明一个2维数组,形如:
int a[2][5]
从申明的含义上,a是一个有2个元素的数组,它的元素,我们记为t。而t怎是一个有5个int元素的数组。
从参数的解释上,事实上 int a[][] 和 int **a是一样的。
而从内存空间的分配上,int a[2][5]和 int b[10]一样,是占用10个连续的int空间。其顺序是:a[0][0],a[0][1]…a[0][4],a[1][0]…a[1][3],a[1][4]
有了上面这些内容,我们就可以像折叠一样,把一串很长的一维数组,给一层一层的折叠成高维数组。下面是我随手写的一段样例代码:
#include <stdio.h> int main (void) { int a[20]; int (*b)[5]; // 申明很猥琐,见最后红字 int i,j; for (i=0; i<20; i++) { a[i]=20-i; } b=a; for (i=0; i<4; i++) for (j=0; j<5; j++) printf ("%d ",b[i][j]); return 0; }
这样做有什么意义呢?
本质上说,确实没有什么太大的意思。而且很多时候,我们可以很轻易的将一个高维数组里的(i,j,k)位置映射到顺序存放的一维数组里。
譬如说对于int a[p][q][r]中的位置(i,j,k)事实上,对应于int a[p*q*r]中的:
i*q*r + j*r + k
(而且事实上,在计算机内部,也就是这么做的。)
反过来,我们也可以通过模、除运算,将一个线性空间中的位置换算成高维空间的位置。式子比较奇怪,就不写了。
如果非要说什么这样通过折叠的方式,重叠指针的好处的话……那就是如果一组数,我们既需要顺序的方位,又希望可以通过指定行列的方式来获取的话……可能会比较方便。(当然,我觉得把上面那个 i*q*r + j*r + k 写成一个宏,也是未尝不可的。但是,总觉得,乘法什么的,交给编译器去做,会不会比我写的要快些?)
最后,再给一个很牵强的应用代码。
描述是这样的,我有4组数据,每组包含5个int数。
然后,我希望以行为基本单位排序,排序的依据是,某一列的数值大小。
下面是样例代码:
#include <stdio.h> #include <stdlib.h> int col=0; int cmp (const void *x, const void *y) { return *((int*)x+col) - *((int*)y+col); } int main () { int a[20]= { 11,41,41,21,31, 22,32,22,42,12, 33,23,13,13,43, 44,14,34,34,24}; int (*b)[5]; int i,j; b=a; printf ("sort by col 1:\n"); // 注意一下,col1 不是第一列,是第二列。从0开始! qsort (b,4,sizeof(b[0]),cmp); for (i=0; i<4; i++) { for (j=0; j<5; j++) printf ("%3d ",b[i][j]); printf ("\n"); } printf ("*************\n"); printf ("sort by col 2:\n"); col=2; qsort (b,4,sizeof(b[0]),cmp); for (i=0; i<4; i++) { for (j=0; j<5; j++) printf ("%3d ",b[i][j]); printf ("\n"); } return 0; }
最后多说几句,这里比较麻烦的是qsort的使用。
在qsort的cmp函数中,传入的两个参数分别是要排序数组的每个元素的地址。
换句话说,如果要排序a[],那么每次传入的参数就是 &a[i]
高维数组事实上就是折叠过得一维数组。也就是说,在事实上,对于2维数组b[][],我们有 (void*)&b[0] == (void*)&b[0][0]。而这两者的区别,也只是类型的不同而已。这也就是我在取值符前面,强制转换为void*的原因。
由此,我们在写cmp函数的时候,切莫将x强制转换为int**,而只需要转换为int*就好。
红字醒目
int (*b) [5] 和 int *b [5] 是不一样的。
int (*b) [5] 表示:b是一个指针,它指向一个含有5个整数的数组
int *b [5] (没有括号!)表示:b是一个有5个元素的数组,它的每个元素是一个指向整数的指针。更易懂的写法是 int* b[5]
int (*b) [5] 中,如果b是x的话,那么b+1就是x+5*int
而在没有括号的版本中,b+1其实是&b[1]
想得卻不可得 你奈人生何
該捨的捨不得 只顧著跟往事瞎扯
等你發現時間是賊了 它早已偷光你的選擇
愛戀不過是一場高燒 思念是緊跟著的好不了的咳是不能原諒 卻無法阻擋
恨意在夜裡翻牆
是空空蕩蕩 卻嗡嗡作響
誰在你心裡放冷槍
舊愛的誓言像極了一個巴掌
每當你記起一句就挨一個耳光
然後好幾年都聞不得、問不得女人香往事並不如煙 是的
在愛裡念舊也不算美德
可惜戀愛不像寫歌 再認真也成不了風格
我問你見過思念放過誰呢 不管你是累犯或是從無前科
我認識的只有那合久的分了 沒見過分久的合歲月你別催 該來的我不推
該還的還 該給的我給
歲月你別催 走遠的我不追
我不過是想弄清原委
誰能告訴我這是什麼呢
她的愛在心裡埋葬了、抹平了、幾年了仍有餘威是不能原諒 卻無法阻擋
愛意在夜裡翻牆
是空空蕩蕩 卻嗡嗡作響
誰在你心裡放冷槍
舊愛的誓言像極了一個巴掌
每當你記起一句就挨一個耳光
然後好幾年都聞不得、問不得女人香
然後好幾年都聞不得、問不得女人香
想得卻不可得 你奈人生何
想得卻不可得 情愛裡無智者
问一下,google reader的数据库里,我的blog最早一篇日志是什么时候?
如果早于2008年11月,希望可以告诉我一声,不胜感激
==========
改了……
随便用什么定阅的都可以……
抓虾就不用了……我自己就是用抓虾的……
定阅了的,汇报一下,能查阅的最早一片日志是什么时候的
谢谢
我越来越扭曲了……这貌似是我最近说的最多的一句话了……
其实,这事真的不怪我……具体理由我也懒得解释……
现在我无论看什么事情,第一反应都是,这其实是个阴谋……
譬如说前一阵子股沟的傲娇。没错!这就是傲娇!
当时我就觉得google不会这么容易走,送花的都是傻逼!
你看,你看,现在诈尸了吧!
再说水妖和陶宏开那个……
我也坚持的认为,这是水妖为了炒新书、炒自己的噱头!
而且,我也觉得,网瘾这个事挺伤人的……
再说今天这个事……
卓越那个200不到的320G硬盘。说来也巧,我今天上午10点多看到一个关于那个硬盘的测评,下午3点多,就收到福利链接。
当时没下单,一来是,当时已经缺货了(其实我第一次点开的时候,还是有货的……一个F5……就没了…………
二来,想起了早上那个测评,当时它的卖点是,摔不坏。
总之,就是觉得有阴谋……
刚刚又在群里听说有NGA的舅舅说,这个就是那个硬盘厂和卓越搞的一场营销,一共几百块,都按那个价卖,亏的远比广告费便宜。
update:据说这个硬盘23号凌晨时段上的架,手快的人已经收到卓越邮件,说发货了
好了,磨叽完了,反正我这里现在也没人来看……
就跟那个硬盘厂,负责的话,也不许负几个人.
最后说一句,我生了个新浪围脖,地址是:
http://t.sina.com.cn/sray
欢迎前往围观