C

Knotes便签

之前一直想找一个便签,Tomboy不是我要的那种,我是希望可以像Mac地下的stickies一样,就像我们平时的便签纸一样,到处贴的那种。

今天找了一下,发现Knotes的效果正好是我想要的,比Mac下的Stickies让我更满意,呵呵,平时经常忘了一些东西,就喜欢把他贴到桌面去,这样看看桌面是不是就记起来了。

show一下我的乱七八糟的东西

screenshot

感觉还是不错的。

(4) 条评论

kernel/time.c中的mktime算法(下)

好,现在我们已经得到一个公式来计算mon月之前已经过去的日子了:
X=year/4-year/100+year/400+(year-1)*365+30*mon-30+(mon+mon/7)/2+day-1
现在我们来计算一下公元1年1月1日:
经过下面这段代码的转换之后,year=0,mon=11,day=1.。

  1. if (0 >= (int) (mon -= 2)) {
  2.         mon += 12;    /* Puts Feb last since it has leap day */
  3.         year -= 1;
  4. }

代入表达式:0-0+0+(0-1)*365 + 30 *11 -30 + (11+11/7)/2 + 1-1=365-306=-59.
这个59显而易见的是由我们将1,2月置后造成的,所以这个公式需要加上一个修正值:59.
再减去1970年离公元1年的日子719162,那么我们的mktime就完成了。
改正后的公式为:
X=year/4-year/100+year/400+(year-1)*365+30*mon-30+(mon+mon/7)/2+day-1 + 59 - 719162
让我们对这个公式进行整理吧,整理后得到:
X=year/4-year/100+year/400+year*365 + 214*mon/7 + day - 719499
和linux源码中的mktime公式并不一样!!不是原来的367*mon/12!

为什么会有这样的区别呢?让我们来回忆一样推导g(mon)的第三步:
g(mon)=30*mon -30 + (mon + mon/7)/2;
事实上,大家会发现,在这儿,这个表达式并不是唯一的!下面这个表达式也是正确的:
g(mon)=30*mon -30 + (mon + mon/6)/2;
让我们用新的g(mon)代入最后的式子,你会惊喜的发现得到的是下面的式子:
year/4-year/100+year/400+year*365 + 367*mon/12 + day - 719499
正是kernel/time.c中的mktime表达式!
阅读这篇文章的剩余部分 »

(14) 条评论

kernel/time.c中的mktime算法(上)

去年在acstar的限时比赛时写过一个程序,是计算某日到2000年1月1日的天数,当时我写的算法用了大概50行,使用的算法很烂。今天在linux内核源码中看到mktime的时候,很清楚折服于它如此简单的算法(据说是Gauss算法),同时犯糊涂。

我将源码摘抄如下:
kernel/time.c

  1. /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  2. * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
  3. * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
  4. *
  5. * [For the Julian calendar (which was used in Russia before 1917,
  6. * Britain & colonies before 1752, anywhere else before 1582,
  7. * and is still in use by some communities) leave out the
  8. * -year/100+year/400 terms, and add 10.]
  9. *
  10. * This algorithm was first published by Gauss (I think).
  11. *
  12. * WARNING: this function will overflow on 2106-02-07 06:28:16 on
  13. * machines were long is 32-bit! (However, as time_t is signed, we
  14. * will already get problems at other places on 2038-01-19 03:14:08)
  15. */
  16. unsigned long
  17. mktime(const unsigned int year0, const unsigned int mon0,
  18.        const unsigned int day, const unsigned int hour,
  19.        const unsigned int min, const unsigned int sec)
  20. {
  21.     unsigned int mon = mon0, year = year0;
  22.  
  23.     /* 1..12 -> 11,12,1..10 */
  24.     if (0 >= (int) (mon -= 2)) {
  25.         mon += 12;    /* Puts Feb last since it has leap day */
  26.         year -= 1;
  27.     }
  28.  
  29.     return ((((unsigned long)
  30.           (year/4 - year/100 + year/400 + 367*mon/12 + day) +
  31.           year*365 - 719499
  32.         )*24 + hour /* now have hours */
  33.       )*60 + min /* now have minutes */
  34.     )*60 + sec; /* finally seconds */
  35. }

阅读这篇文章的剩余部分 »

没有评论

数组和数组名取址的区别

起因是Expert C Programming的一道习题:

  1. #include <stdio.h>
  2.  
  3. char ga[14] = "abcdefghijklm";
  4.  
  5. void my_array_func( char ca[10] )
  6. {
  7.    printf(" addr of array param = %#x \n",&ca);
  8.    printf(" addr (ca[0]) = %#x \n",&(ca[0]));
  9.    printf(" addr (ca[1]) = %#x \n",&(ca[1]));
  10.    printf(" ++ca = %#x \n\n", ++ca);
  11. }
  12. void my_pointer_func( char *pa )
  13. {
  14.    printf(" addr of ptr param = %#x \n",&pa);
  15.    printf(" addr (pa[0]) = %#x \n",&(pa[0]));
  16.    printf(" addr (pa[1]) = %#x \n",&(pa[1]));
  17.    printf(" ++pa = %#x \n", ++pa);
  18. }
  19.  
  20. int main(void)
  21. {
  22.    printf(" addr of global array = %#x \n",&ga);
  23.    printf(" addr (ga[0]) = %#x \n",&(ga[0]));
  24.    printf(" addr (ga[1]) = %#x \n\n",&(ga[1]));
  25.    my_array_func( ga );
  26.    my_pointer_func( ga );
  27.     return 0;
  28. }

阅读这篇文章的剩余部分 »

(1) 条评论

可执行文件中的段

在Expert C Programming,Chapter 6,Segments,Programming Challenge中,有个关于段的实验,所以我就试了一下,记录于此。

我们知道,可执行文件中包含文件头,BSS段,DATA段(存放初始化后的全局和表态变量)以及TEXT段(存放可执行文件的指令),对任一个可执行文件使用size命令便可以得到这些数据,例如:

$ size foo
text data bss dec hex filename
1584 288 12 1884 75c process

现在我们来进行这个游戏吧:
1,编译一个”hello world”程序,执行ls -l,得到文件的总体大小,运行size得到文件中各个段的大小。

#include <stdio.h>
int main(void)
{
printf(”hello world”);
return 0;
}

然后编译它,并执行相应的命令:

$ ls -l ./a.out
-rwxr-xr-x 1 space space 6650 2007-11-19 16:55 ./a.out
$ size ./a.out
text data bss dec hex filename
868 268 4 1140 474 ./a.out

以上结果将成为下面对比的对象,以下称之为原文件。 阅读这篇文章的剩余部分 »

(8) 条评论

« 下一页