Jan
09

阅读、练习下面的指示,舒适的使用Linux;

1. 尽量不要使用命令Ctrl+D结束会话或关闭终端D

   * set -o 忽略错误激活 Ctrl+D
* set +o 忽略错误禁用 Ctrl+D

2. 别名 — 我们给一个命令引入别名,shell 会用这个值重编码它。

3. 最近高频使用命令 —在控制台执行以下指令:

history|awk '{print $2}'|awk 'BEGIN {FS="|"} {print $1}'|sort|uniq -c|sort -rn|head -10

4. 杀死一个确定程序的所有进程 。

打开终端输入:ps aux c。如果你要杀死的程序比如是 Firefox,命令将会是这样: ps aux c | grep firefox ,然后kill -9。下一次你运行 ps aux c | grep firefox,这个程序再也不会出现了。

5. 获取基本系统信息

有些命令可以用来确定系统的基本信息,像内核版本、软件信息还有其他方面的东西。下面的命令当执行时立即显示输出。

$ cat /proc/version = "它返回一条完整的信息串"
$ uname -a = "显示系统所有信息还有系统日期和时间"

6. 使用日历

通过下面的命令你可以在不同版本的Linux上获得不同视图和显示的日历。

cal -3 = "简单显示日历"
cal 1 2008 = "此命令显示一年中特定月份的日历"
date -d fri = "显示本周或下周星期五的日期"
date --date='25 Dec' +%A = "告诉你今年圣诞节是星期几"

7. 磁盘空间

拥有充足和优化的磁盘空间是系统性能良好的重要方面。对Linux来说,这里有优化存储空间和显示硬盘空间的方法。

df -h = "此命令显示空余硬盘空间"
fdisk -l = "和Windows中显示硬盘分区相似"
ls -lSr = "显示所有文件,最大的在最后"
du -s * | sort -k1,1rn | head = "显示当然目录占用空间排名"

8. 集合操作

Linux下你可以快速操作文件。试试下面的命令,它对你操作文件会有很大的帮助。

LANG=C sort file1 file2 | uniq" = "合并不排序文件"
LANG=C sort file1 file2 | uniq -d = "截取排序文件"
LANG=C comm file1 file2 | sed 's/^t*//' = "合并排序文件"
LANG=C comm -3 file1 file2 | sed 's/^t*// = "对称排序文件的不现部分"

9. 文本操作 

文本操作是工作另一个重要的方面。让我看看Linux里的一些命令。

sed -n 's/.*.*/1/ip;T;q' = "从一个HTML页面提取标题"
sed -n '10,20p;20q' = "显示10到20行"
sed ':a; /$/N; s///; ta' = "连接相邻行"
sed 's/[ t]*$//' = "移除行尾空白"
sed 's/string1/string2/g' = "替换string1为string2"

10. 搜索文件 

在Linux平台下搜索任何东西更快的方法。

alias ll='ls -l --color=auto'page" = "快速列出目录"
ls -lrt = "按日期排列文件"
find -name '*.[ch]' | xargs grep -E 'expr' ="在当前目录及以下搜索'expr' "
find -type f ! -perm -444 = "找出不是所有人可读的文件"
locate -r 'file[^/]*.txt' = "按文件名搜索缓存索引"

11. 僵死窗口

有时候你会遇到僵死的窗口,有两种方法处理这种情况而不必关机或重启。第一,你可以试一试传统的快捷键Ctrl + Alt + Backspace。

另一个方法比前一个更复杂但是更有效。按Ctrl + Alt + F2 进入虚拟控制台。然后用你的用户名、密码登陆,输入以下命令:

ps -ax | grep startx

执行这条命令会给你系统Xserver的PID.然后用下面的命令杀死它

kill -9 PID_Number

如果你想回到每一个控制台,只要按下Alt + F1。

12. 远程操作 

通过“rexec”服务 你可以远程操作,当你在一个网络环境下工作时这非常有用。使用此服务的用户必须通过用户名和密码验证。

推荐(0)
收藏
Jan
07

MYSQL 常用函数备查
2008-01-07 1:01 pm 作者:tangfl.openid.35.com

一.             控制流程函数

1.CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END

该语句用于在不同情况时,执行不同的语句,实例如下:

Eg1. SELECT CASE WHEN 1>0 THEN 'true' ELSE 'false' END;

输出:true

Eg2. SELECT CASE BINARY 'B' WHEN 'a' THEN 1 WHEN 'b' THEN 2 END;

输出:NULL

2.IF(expr1,expr2,expr3)

如果expr1返回true,则该表达式返回expr2,否则返回expr3。

Eg1. SELECT IF(1<2,'yes ','no');

输出:'yes '

Eg2. SELECT IF(STRCMP('test','test1'),'no','yes');

上例中STRCMP(expr1, expr2)这个函数在expr1小于expr2时,返回-1,相等时返回0,其余的情况返回1,在上例中返回-1,因此上例的输出为:'yes'

3.IFNULL(expr1,expr2)

该函数在expr1为NULL时,返回expr2,否则,返回expr1。

Eg1. SELECT IFNULL(1,0);

输出:1

Eg2. SELECT IFNULL(NULL,10);

输出:10

4.NULLIF(expr1,expr2)

如果expr1=expr2,则返回NULL,否则,返回expr1。

Eg1. SELECT NULLIF(1,1);

输出:NULL

Eg2. SELECT NULLIF(3,4);

输出:3

二.             字符串函数

1.       ASCII(str)

返回值为字符串str 的最左字符的数值。假如str为空字符串,则返回值为 0 。假如str 为NULL,则返回值为 NULL。 ASCII()用于带有从 0到255的数值的字符。

Eg1. SELECT ASCII('2');

输出:50

Eg2. SELECT ASCII('de');

输出:100

2.       CONCAT(str1,str2,...) 

返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL。或许有一个或多个参数。

Eg1. SELECT CONCAT('Hello', ',', '阿蜜果');

输出:'Hello, 阿蜜果'

Eg2. SELECT CONCAT('Hello', NULL, '阿蜜果');

输出:NULL

3.       CONCAT_WS(separator,str1,str2,...)

CONCAT_WS() 代表 CONCAT With Separator ,是CONCAT()的特殊形式。   第一个参数是其它参数的分隔符。分隔符的位置放在要连接的两个字符串之间。分隔符可以是一个字符串,也可以是其它参数。如果分隔符为 NULL,则结果为 NULL。函数会忽略任何分隔符参数后的NULL值。

Eg1. SELECT CONCAT_WS(',', 'Hello', '阿蜜果');

输出:'Hello, 阿蜜果'

Eg. SELECT CONCAT_WS(',', 'Hello', NULL, '阿蜜果');

输出:'Hello, 阿蜜果'

4.       INSERT(str,pos,len,newstr)

返回字符串 str, 其子字符串起始于 pos位置和长期被字符串 newstr取代的len字符。 如果pos超过字符串长度,则返回值为原始字符串。 假如len的长度大于其它字符串的长度,则从位置pos开始替换。若任何一个参数为null,则返回值为NULL。

Eg1. SELECT INSERT('hello,Amigo', 7, 5, 'Locus');

输出:hello,Locus

5.       INTER(str, substr)

返回字符串 str中子字符串的第一个出现位置。

Eg1. SELECT INSTR('hello,Amigo', 'Amigo');

输出:7

6.       LENGTH(str)

返回值为字符串str的长度,单位为字节。一个多字节字符算作多字节。

Eg1. SELECT LENGTH('Amigo');

输出:5

7.       LOWER(str)

返回字符串 str以及所有根据最新的字符集映射表变为小写字母的字符。

Eg1. SELECT LOWER('AMIGO');

UPPER(str)函数的用法与此类似,在此不再赘述。不过它是将字符串转换为大写的。

输出:amigo

8.       LPAD(str, len, padstr)

返回字符串 str, 其左边由字符串padstr 填补到len字符长度。假如str 的长度大于len, 则返回值被缩短至len字符。

Eg1. SELECT LPAD('hi',4,'!!');

输出:'!!hi'

Eg2. SELECT LPAD('hi',1,'!!');

输出:'h'

RPAD(…)函数用法与此类似,在此不再赘述。

9.       REPEAT(str,count)

返回一个由重复的字符串str 组成的字符串,字符串str的数目等于count。 若 count <= 0,则返回一个空字符串。若str或count 为 NULL,则返回NULL。

Eg1. SELECT REPEAT('Amigo', 2);

输出:'AmigoAmigo'

10.   SUBSTRING(str,pos), SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)

       不带有len 参数的格式从字符串str返回一个子字符串,起始于位置 pos。带有len参数的格式从字符串str返回一个长度同len字符相同的子字符串,起始于位置 pos。 使用 FROM的格式为标准 SQL 语法。也可能对pos使用一个负值。假若这样,则子字符串的位置起始于字符串结尾的pos 字符,而不是字符串的开头位置。在以下格式的函数中可以对pos 使用一个负值。

Eg1. SELECT SUBSTRING('hello,Amigo',6);

输出:Amigo

Eg2. SELECT SUBSTRING('hello,Amigo', 6, 4);

输出:Amig

三.             数值函数

1.       ABS(X)

返回X的绝对值。

Eg1. SELECT ABS(-5);

输出:5

2.       FLOOR(X)

返回不大于X的最大整数值 。

Eg1. SELECT FLOOR(2.56);

输出:2

Eg2. SELECT FLOOR(-2.56)

输出:-3

3.       MOD(N,M) , N % M N MOD M

模操作。返回N 被 M除后的余数。

Eg1. SELECT MOD(237, 10);

输出:7

Eg2. SELECT 237 % 10;

输出:7

Eg3. SELECT 237 MOD 10;

输出:7

4.       POW(X, Y),POWER(X, Y)

返回XY乘方的结果值。

Eg1. SELECT POW(2, 3);

输出:8

Eg2. SELECT POWER(2, 4)

输出:16

5.       RAND(),RAND(N)

返回一个随机浮点值 v,范围在 0 到1 之间 (即, 其范围为 0 ≤ v ≤ 1.0)。若已指定一个整数参数 N,则它被用作种子值,用来产生重复序列。

Eg1.  SELECT RAND(20);

输出:0.15888261251047

Eg2. SELECT RAND();

输出:0.9233482386203

若要在i ≤ R ≤ j 这个范围得到一个随机整数R ,需要用到表达式 FLOOR(i + RAND() * (j – i + 1))。例如, 若要在7 到 12 的范围(包括7和12)内得到一个随机整数, 可使用以下语句:

SELECT FLOOR(7 + (RAND() * 6));

6.       ROUND(X),ROUND(X,D)

返回参数X, 其值接近于最近似的整数。在有两个参数的情况下,返回 X ,其值保留到小数点后D位,而第D位的保留方式为四舍五入。若要接保留X值小数点左边的D 位,可将 D 设为负值。

Eg1. SELECT ROUND(-1.23);

输出:-1

Eg2. SELECT ROUND(2.56);

输出:3

7.       SQRT(X)

      返回非负数X的二次方根,如X为NULL时,返回NULL。

Eg1. SELECT SQRT(4);

输出:2

Eg2. SELECT SQRT(-4);

输出:NULL

四.             日期和时间函数

1. ADDDATE(date,INTERVAL expr type),ADDDATE(expr,days)

       当被第二个参数的INTERVAL格式激活后, ADDDATE()就是DATE_ADD()的同义词。相关函数SUBDATE()则是DATE_SUB()的同义词。

Eg1. SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY);

输出:'1998-02-02'

Eg2. SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY);

输出:'1998-02-02'

2. CURDATE()

将当前日期按照'YYYY-MM-DD' 或YYYYMMDD 格式的值返回,具体格式根据函数用在字符串或是数字语境中而定。

Eg1. SELECT CURDATE();

输出:'2008-01-01'

Eg2. SELECT CURDATE() + 0;

输出:20080101

3. CURTIME()

将当前时间以'HH:MM:SS'或 HHMMSS 的格式返回, 具体格式根据函数用在字符串或是数字语境中而定。

Eg1. SELECT CURTIME();

输出:'15:15:26'

4. DATE(expr)

提取日期或时间日期表达式expr中的日期部分。

Eg1. SELECT DATE('2007-12-31 23:59:59');

输出:'2007-12-31'

5. DATEDIFF(expr, expr2)

DATEDIFF() 返回起始时间 expr和结束时间expr2之间的天数。Exprexpr2为日期或 date-and-time 表达式。计算中只用到这些值的日期部分。

Eg1. SELECT DATEDIFF('1997-12-31 23:59:59','1997-12-30');

输出:1

Eg2. SELECT DATEDIFF('1997-11-30 23:59:59','1997-12-31');

输出:-31

6. DAYOFMONTH(date)

返回date 对应的该月日期,范围是从 1到31。

Eg1. SELECT DAYOFMONTH('2008-01-05');

输出:5

7. MONTH (time)

返回date对应的月份,范围时从 1 到 12。

Eg1. SELECT MONTH('2007-01-05');

输出:1

8. HOUR(time)

       返回time 对应的小时数。对于日时值的返回值范围是从 0 到 23 。

Eg1. SELECT HOUR('11:47:1');

9. MINUTE(time)

返回 time 对应的分钟数,范围是从 0 到 59。

Eg1. SELECT MINUTE('2007-01-05 11:51:23);

输出:51

10. SECOND(time)

返回time对应的秒数, 范围是从 0到59。

Eg1. SELECT SECOND('11:56:43);

输出:43

11. LAST_DAY(date)

获取一个日期或日期时间值,返回该月最后一天对应的值。若参数无效,则返回NULL。

Eg1. SELECT LAST_DAY('2008-02-01');

输出:29

12. NOW()

返回当前日期和时间值,其格式为 'YYYY-MM-DD HH:MM:SS' 或YYYYMMDDHHMMSS , 具体格式取决于该函数是否用在字符串中或数字语境中。

Eg1. SELECT NOW();

输出:'2007-01-05 11:54:30'

13. SUBDATE(date,INTERVAL expr type) ,SUBDATE(expr,days)

       当被第二个参数的 INTERVAL型式调用时, SUBDATE()和DATE_SUB()的意义相同。对于有关INTERVAL参数的信息, 见有关 DATE_ADD()的讨论。

Eg1. SELECT SUBDATE('2008-01-05', INTERVAL 31 DAY);

输出:2007-12-05

14. SYSDATE()

返回当前日期和时间值,格式为'YYYY-MM-DD HH:MM:SS' 或YYYYMMDDHHMMSS, 具体格式根据函数是否用在字符串或数字语境而定。

在一个存储程序或触发器中, SYSDATE()返回其执行的时间, 而非存储成都或触发语句开始执行的时间。这个NOW()的运作有所不同。

Eg1. SELECT SYSDATE();

输出:2008-01-05 12:01:41

推荐(0)
收藏
Jan
07

1949年以来的《人民日报》元旦社论目录:

1949 《将革命进行到底》 
1950 《完成胜利,巩固胜利迎接一九五○年元旦》 
1951 《在伟大爱国主义旗帜下巩面我们的伟大祖国》 
1952 《以高度的信心和坚强的意志迎接一九五二年》 
1953 《迎接一九五三年的伟大任务》 
1954 《一切为了实现国家的总路线》  
1955 《迎接一九五五年的任务》 
1956 《为全面地提早完成和超额完成五年计划而奋斗》 
1957 《新年的展望》 
1958 《乘风破浪》
1959 《迎接新的更伟大的胜利》
1960 《展望六十年代》
1961 《团结一致,依靠群众,争取世界和平和国内社会主义建设的新胜利》 
1962 《新年献词》
1963 《巩固伟大成绩,争取新的胜利》
1964 《乘胜前进》
1965 《争取社会主义事业新胜利的保证》 
1966 《迎接第三个五年计划的第一年——一九六六年》 
1967 《把无产阶级文化大革命进行到底》
1968 《迎接无产阶级文化大革命的全面胜利》 
1969 《用毛泽东思想统帅一切》
1970 《迎接伟大的七十年代》
1971 《沿着毛主席革命路线胜利前进》
1972 《团结起来,争取更大的胜利》
1973 《新年献词》
1974 《元旦献词》
1975 《新年献词》
1976 《世上无难事,只要肯登攀》 
1977 《乘胜前进》
1978 《光明的中国》
1979 《把主要精力集中到生产建设上来》 
1980 《迎接大有作为的年代》
1981 《在安定团结的基础上,实现国民经济调整的巨大任务》 
1982 《一年更比一年好,定教今年胜去年》
1983 《为我们的伟大事业增添新的光彩》
1984 《勇于开创新局面》
1985 《和衷共济搞四化》
1986 《让愚公精神满神州》
1987 《坚持四项基本原则是搞好改革、开放的根本保证》 
1988 《迎接改革的第十年》
1989 《同心同德,艰苦奋斗》
1990 《满怀信心迎接九十年代》 
1991 《为进一步稳定发展而奋斗》 
1992 《在改革开放中稳步发展》
1993 《团结奋进》
1994 《艰苦奋斗,再创辉煌》 
1995 《总揽全局,乘势前进》 
1996 《满怀信心夺取新胜利》
1997 《把握大局,再接再励,同心同德,开拓前进》 
1998 《在十五大精神指引下胜利前进》 
1999 《团结奋斗,创造新业绩》 
2000 《迎接新世纪的曙光》
2001 《迈进光辉灿烂的新世纪》
2002 《迈出中华民族伟大复兴的新步伐》
2003 《共创幸福生活美好未来》
2004 《为全面建设小康社会提供坚强的人才保证》
2005 《迈出全面建设小康社会的新步伐》
2006 《伟大的开局之年——元旦献词》
2007 《科学发展的道路越走越宽广――元旦献词》
2008 《喜迎伟大的2008年——元旦献词》

推荐(0)
收藏
Jan
03

base64
2008-01-03 4:15 pm 作者:tangfl.openid.35.com

        按照RFC2045的定义, Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。

(The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.)

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,在发送电子邮件时,服务器认证的用户名和密码需要用Base64编码,附件也需要用Base64编码。RFC2045 ~ RFC2049 上有MIME的详细规范。

Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。(为什么要这样做呢?因为以00开头的每一个8Bit字节,都是“可打印字符”;而非00开头的8Bit字节,可能会是非“可打印字符”,或者多字节字符的一部分)

我们来看一个例子:

转换前

aaaaaabb ccccdddd eeffffff

转换后

00aaaaaa 00bbcccc 00ddddee 00ffffff

上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。

转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:(摘自RFC2045)

Table 1: The Base64 Alphabet

Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w
15 P 32 g 49 x
16 Q 33 h 50 y
(pad) =

填充符'=':当需要编码的字符不是3的倍数,就会有余数1或2。这个时候就需要填充2位或1位来补齐,使转换后是4个字节,最多填充两个‘=’

让我们再来看一个实际的例子:

转换前 10101101 10111010 01110110
转换后 00101011 00011011 00101001 00110110
十进制 43 27 41 54
对应码表中的值 r b p 2

所以上面的24位编码,编码后的Base64值为 rbp2
解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。

用更接近于编程的思维来说,编码的过程是这样的:

第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符。
然后将第一个字符左移4位加上第二个字符右移4位,即获得第二个目标字符。
再将第二个字符左移2位加上第三个字符右移6位,获得第三个目标字符。
最后取第三个字符的右6位即获得第四个目标字符。

在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。

推荐(0)
收藏
Jan
03

转自:C++博客

1.引言

C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。作为一种欲与C兼容的语言,C++保留了一部分过程式语言的特点(被世人称为“不彻底地面向对象”),因而它可以定义不属于任何类的全局变量和函数。但是,C++毕竟是一种面向对象的程序设计语言,为了支持函数的重载,C++对全局函数的处理方式与C有明显的不同。

2.从标准头文件说起

某企业曾经给出如下的一道面试题:

面试题
为什么标准头文件都有类似以下的结构?

#ifndef __INCvxWorksh
#define __INCvxWorksh
#ifdef __cplusplus
extern "C" {
#endif
/*...*/
#ifdef __cplusplus
}
#endif
#endif /* __INCvxWorksh */

分析
显然,头文件中的编译宏“#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的作用是防止该头文件被重复引用。

那么

#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif

的作用又是什么呢?我们将在下文一一道来。
3.深层揭密extern "C"

extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。让我们来详细解读这两重含义。

被extern "C"限定的函数或变量是extern类型的;

extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住,下列语句:

extern int a;

仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。

通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数。

与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。

被extern "C"修饰的变量和函数是按照C语言方式编译和连接的;

未加extern “C”声明时的编译方式

首先看看C++中对类似C的函数是怎样编译的。

作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:

void foo( int x, int y );

该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。

_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。
同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

未加extern "C"声明时的连接方式

假设在C++中,模块A的头文件如下:

// 模块A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
int foo( int x, int y );
#endif

在模块B中引用该函数:

// 模块B实现文件 moduleB.cpp
#include "moduleA.h"
foo(2,3);

实际上,在连接阶段,连接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号!

加extern "C"声明后的编译和连接方式

加extern "C"声明后,模块A的头文件变为:

// 模块A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo( int x, int y );
#endif

在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:

(1)模块A编译生成foo的目标代码时,没有对其名字进行特殊处理,采用了C语言的方式;

(2)连接器在为模块B的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。

如果在模块A中函数声明了foo为extern "C"类型,而模块B中包含的是extern int foo( int x, int y ) ,则模块B找不到模块A中的函数;反之亦然。

所以,可以用一句话概括extern “C”这个声明的真实目的(任何语言中的任何语法特性的诞生都不是随意而为的,来源于真实世界的需求驱动。我们在思考问题时,不能只停留在这个语言是怎么做的,还要问一问它为什么要这么做,动机是什么,这样我们可以更深入地理解许多问题):
实现C++与C及其它语言的混合编程。
明白了C++中extern "C"的设立动机,我们下面来具体分析extern "C"通常的使用技巧。

4.extern "C"的惯用法

(1)在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理:

extern "C"
{
#include "cExample.h"
}

而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。

如果C++调用一个C语言编写的.DLL时,当包括.DLL的头文件或声明接口函数时,应加extern "C" { }。

(2)在C中引用C++语言中的函数和变量时,C++的头文件需添加extern "C",但是在C语言中不能直接引用声明了extern "C"的该头文件,应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。

如果深入理解了第3节中所阐述的extern "C"在编译和连接阶段发挥的作用,就能真正理解本节所阐述的从C++引用C函数和C引用C++函数的惯用法。对第4节给出的示例代码,需要特别留意各个细节。

推荐(0)
收藏
Dec
29

再见,2007
2007-12-29 2:15 pm 作者:tangfl.openid.35.com

这一年,从学校走出来:年初还是学生,到年底,就变成了一个十足的“社会青年”了,从西西楼搬出来,虽然住的离学校还是不远,虽然还是不时的回学校,但感觉,完全变了;

这一年,工作频繁变动:新浪播客,爱问视频搜索,搜索后台切换,抓站,到最后的新浪支付,借调,再借调,最终确定调岗,转正时的犹豫,不停的猎头诱惑,原来社会远比学校复杂;

这一年,碰上小白;

这一年,朋友们一个个也都走出了校园,开始为生计奔波。艰辛的生活慢慢疏远了彼此的联系,但关怀依旧,祝福依旧:

不常联系

并不因为忘记

偶尔有你的消息

一样惊喜

只因曾经相识相知

彼此珍惜

我的世界不大

但有一个空间

一定有你

祝所有我关心的和关心我的人们新年快乐!

推荐(0)
收藏
Dec
24

PECL :: Package :: memcache 2.1.1 版本的 Changelog 中有一条:

- Added experimental session storage support. You can use memcached as session storage.

也就是可以直接用 memcache 来作 PHP 的 session.save_handler。

1. 安装 memcached:
标准的

./configure; make; make install

注意 memcached 用 libevent 来作事件驱动,所以要先安装有 libevent。

2. 安装 pecl::memcache,用 pecl 命令行工具安装:

pecl install memcache

或直接从源码安装:

phpize
./configure
make
make install

将 php.ini 中 extension=memcache.so 打开,重启一下 apache,查看 phpinfo 中的 "Registered save handlers" 会有 "files user memcache" 这3个可用。

3. 修改配置文件,在 php.ini 中全局设置:

session.save_handler = memcache
session.save_path = "tcp://127.0.0.1:11211"

或者某个目录下的 .htaccess :

php_value session.save_handler "memcache"
php_value session.save_path "tcp://127.0.0.1:11211"

再或者在某个一个应用中:

ini_set("session.save_handler", "memcache");
ini_set("session.save_path", "tcp://127.0.0.1:11211");

使用多个 memcached server 时用逗号","隔开,并且和 Memcache::addServer() 文档中说明的一样,可以带额外的参数"persistent"、"weight"、"timeout"、"retry_interval" 等等,类似这样的:

"tcp://host1:port1?persistent=1&weight=2,tcp://host2:port2"

4. 启动 memcached:

memcached -d -l 127.0.0.1 -p 11212 -m 128

5. 在程序中使用 memcache 来作 session 存储,用例子测试一下:

session_start();
if (!isset($_SESSION['TEST'])) {
$_SESSION['TEST'] = time();
}

$_SESSION['TEST3'] = time();

print $_SESSION['TEST'];
print "<br><br>";
print $_SESSION['TEST3'];
print "<br><br>";
print session_id();

6. 用 sessionid 去 memcached 里查询一下:

$memcache = memcache_connect('localhost', 11211);
var_dump($memcache->get('19216821213c65cedec65b0883238c278eeb573e077'));

会有看到

string(37) "TEST|i:1177556731;TEST3|i:1177556881;"

这样的输出,证明 session 正常工作。

用 memcache 来存储 session 在读写速度上会比 files 时快很多,而且在多个服务器需要共用 session 时会比较方便,将这些服务器都配置成使用同一组 memcached 服务器就可以,减少了额外的工作量。缺点是 session 数据都保存在 memory 中,持久化方面有所欠缺,但对 session 数据来说也不是很大的问题。

另外,WS Memcached Session Handler for PHP 提供了另外一种用 session_set_save_handler 来利用 memcached 的方法,可以参考。

推荐(0)
收藏
Dec
21

Email 定义
2007-12-21 5:25 pm 作者:tangfl.openid.35.com

一封符合标准的 Email 大致是这个样子的:

Mail Header [define boundary "--123"]
2 eol
--123
header block 1 [define boundary "--456"]
2eol
--456
header block 1.1
2eol
content block 1.1
2eol
--456
header block 1.2
2eol
content block 1.2
2eol
--456--
2eol
--123
header block 2
2eol
content block 2
2eol
--123--
2eol

推荐(0)
收藏
Dec
17

转自:无忍则无济,有爱即有忧

在Linux中可以将一部分内存当作分区来使用,称之为RamDisk。对于一些经常被访问的文件,而它们又不会被更改,可以将它们通过 RamDisk放在内存中,即可明显地提高系统的性能(一个典型的例子是 HTTP Session)。当然这样做的一个前提是内存足够大。

RamDisk有两种,一种可以格式化,加载,在Linux内核 2.0/2.2就已经支持,其不足之处是大小固定。另一种是内核2.4才支持的,通过Ramfs或者Tmpfs来实现,它们不能被格式化,但是用起来灵活,其大小随所需要的空间而增加或减少。这里主要介绍一下Ramfs和Tmpfs。

  •         Ramfs顾名思义是内存文件系统,它工作于虚拟文件系统(VFS)层。不能格式化,可以创建多个,在创建时可以指定其最大能使用的内存大小。如果你的Linux已经将Ramfs编译进内核,你就可以很容易地使用Ramfs了。创建一个目录,加载Ramfs到该目录即可。

# mkdir -p /RAM1
# mount -t ramfs none /RAM1

缺省情况下,Ramfs被限制最多可使用内存大小的一半。可以通过maxsize(以kbyte为单位)选项来改变。

# mkdir -p /RAM1
# mount -t ramfs none /RAM1 -o maxsize=10000

以上即创建了一个限定了最大使用内存大小为10M的ramdisk。

  •         Tmpfs 是一个虚拟内存文件系统,它不同于传统的用块设备形式来实现的ramdisk,也不同于针对物理内存的Ramfs。Tmpfs可以使用物理内存,也可以使用交换分区。在Linux内核中,虚拟内存资源由物理内存(RAM)和交换分区组成,这些资源是由内核中的虚拟内存子系统来负责分配和管理。Tmpfs就是和虚拟内存子系统来"打交道"的,它向虚拟内存子系统请求页来存储文件,它同Linux的其它请求页的部分一样,不知道分配给自己的页是在内存中还是在交换分区中。Tmpfs同Ramfs一样,其大小也不是固定的,而是随着所需要的空间而动态的增减。使用tmpfs,首先你编译内核时得选择"虚拟内存文件系统支持(Virtual memory filesystem support)" ,然后就可以加载tmpfs文件系统了。

# mkdir -p /mnt/tmpfs
# mount tmpfs /mnt/tmpfs -t tmpfs

为了防止tmpfs使用过多的内存资源而造成系统的性能下降或死机,可以在加载时指定tmpfs文件系统大小的最大限制。

# mount tmpfs /mnt/tmpfs -t tmpfs -o size=32m

以上创建的tmpfs文件系统就规定了其最大的大小为32M。不管是使用ramfs还是tmpfs,必须明白的是,一旦系统重启,它们中的内容将会丢失。所以那些东西可以放在内存文件系统中得根据系统的具体情况而定。

补充:ramfs只会在物理内存中被创建,而tmpfs可能在物理内存中创建,也可能在交换分区中被创建。对于想利用内存的高速IO来提高效能的应用,最好是使用ramfs。对于只是想存放临时缓存的应用,最好是用tmpfs,以提前内存的利用率。

推荐(0)
收藏
Dec
06

01) shell编程入门及脚本测试
02) shell脚本欣赏区
03) TCSH shell编程入门
04) Bash命令行处理[详解]
05) shell命令基础
06) Linux命令大集合
07) sed/awk与unix命令等价代码欣赏
08) 如何将数字转换为大写数字?
09) 出道算术题考考你?
10) 考考你?[关于数组]
11) 如何横排变竖排?
12) 关于屏幕定位显示
13) 如果确定某个特定字符在一个字串中的位置
14) 如何用shell产生随机数组
15) 如何处理键盘输入超时
16) 1到999999999的阵列,如何用shell实现?
17) 用dd命令去备份文件指定的部分
18) 一个自动解压缩rar的脚本
19) UNIXshell/LINUXshell--实例精解源代码
20) 常用的关机和重新启动命令
21) GNU 文本实用程序教程
22) 关于array中的变量替换? [分享]
23) 在bash下实现双窗口或多窗口的方法
24) awk引用变量的问题
25) awk命令实用详解
26) RPM常用命令及RPM中文手册
27) [精彩讨论]sed/awk的新问题
28) 优先级[nice/renice实例]
29) 制作像 nvidia驱动包 那样的可执行安装包
30) Shell的命令行编辑[vi&emacs命令行技巧征集]
31) 如何把一个命令的输出放进多个管道里去,并让那些管道命令并行化
32) 有什么好办法在解压缩过程中同时获取压缩包的内容目录结构的顶层目录呢?
33) Linux Shell简介(入门)
34) BASH最常见的激活模式
35) 论坛是否有expect的技术介绍[附:Expect中文教程]
36) 变态vi问答
37) 如何产生一个随机的字母和一个一位的数字?[已解决]
38) shell编程中${ }的用法[转]
39) 适用于ADSL的连接脚本。
40) 文本模式下手动画表格的脚本
41) grep,sed,awk命令实例大练习[大力推荐]
42) 一个小脚本,帮助你清除无用的rpm包(zt)
43) 关于网络流量统计
44) bash_profile和.bashrc有什么区别?[附:几个bash配置文件的说明]
45) 一个连网的实用脚本
46) ADSL上网脚本
47) slackware添加用户adduser脚本欣赏
48) Gawk手册
49) latex2pdf的脚本
50) BASH中字符串的处理[转]

51) 这个脚本怎么写?[about find&xargs]
52) ulimit使用方法
53) 几个shell自动化脚本
54) 判断XDSL上网方式的用户的网络工作情况的脚本
55) 自动ftp脚本[附录ftp命令大全]
56) 关于zero及NULL设备的讨论
57) 硬连接和软连接的区别的讨论[附:ln中文文档]
58) 将某一目录下以main开头的100个文件的文件名分别改为main1到main100
59) 搜索一首歌并调用XMMS播放的脚本
60) 关于如何设定控制台的彩色显示?
61) 我用DF命令后看到这样的信息是咋回事[附:各种文件系统介绍]
62) Linux [系统管理命令中文详解][转]
63) bash脚本调试器
64) 使用 /proc 文件系统来控制系统[转贴]
65) 如何在shell中将unix时间戳转换为系统时间
66) "2>&1" 是什么意思?[重定向问题合并]
67) 拿到一个好的五笔98码表+awk一例[合并]
68) rh9自动运行X程序的方法
69) MOUNT命令中各个参数的含义
70) 如何从HTML文件中提取charset
71) BASH shell set命令详解
72) VI高级命令集锦及VIM应用实例
73) Linux/UNIX命令dd简介
74) 怎么让cp显示拷贝的进度或者速度?
75) 如何将一个输出中的若干行分别赋值给变量?
76) 修改了一下startx,用于窗口管理器的选择
77) 我想把下面的人名改成第一个字母大字,其它小写
78) 系统备份用的脚本
79) [转贴]编译APACHE+PHP+MYSQL的一个脚本
80) shell脚本是否可编译成二进制文件????<讨论>
81) 如何阻止非root用户再shell下用Ctrl+Alt+Delete重启电脑
82) tr的使用方法[转贴]
83) 设置终端--stty使用方法[转贴]
84) BASH-HOWTO文档
85) 解读startx
86) 写了一个显示目录树的脚本,可输出不对
87) 如何開一term ?K在里头顯某個文件的內容??
88) 如何在脚本中应用dialog命令<欢迎讨论>
89)
90) find和xargs使用详解[转自《shell编程和unix命令》]
91) Redhat8 下脚本的一些问题
92) 删除文件跟恢复文件系列。
93) 防止误删文件的脚本
94) 熟练运用命令所必须的<正则表达式语法>
95) linux shell trap信号表
96) shell入门基础必备
97) 如何快速把带有大写字母的文件名改为全部小写?
98) Unix Shell 介绍 (author:S. R. Bourne)
99) 技巧:提示行魔术
100) 禁止用户登录脚本

101) 一个自动挂载dos分区的脚本
101) bash快捷键盘使用心得,非转载~~~
102) 几个可以加在SHELL配置脚本里面的小函数
103) 如何用bash提取网卡ip地址?
104) shell技巧交流区
105) 适合初学练习的一组小脚本
106) Linux 终端的彩色显示
107) 一个自动解压缩rar的脚本
108) 一道算术题
109) 如何把一个文件倒着读出来?
110) source命令的一个妙用
111) 压缩-分段-备份的实现
112) 设置命令提示符下的热键[转]
113) BASH教学实例
114) 用sed/awk合并两行
115) stty中文手册
116) VIM速查手册
117) VIMset选项详解
118) 自动mount各类分区的脚本
119) shell十三问(简体版PDF)
120) dialog中文man手册
121) 怎样得到终端的参数如长宽行数?
122) 判断一个数是否2的幂[讨论awk的扩展用途]
123) tr:超级工具:为数据做外科手术(dd, head, tail...)
124) 服务器诊所: Expect 超出预期
125) 再来一个tree脚本(原创)
126) 几种shell里的小括号,大括号结构和有括号的变量,命令的用法
127) bash中字符串的处理(参阅CU一贴后重整理)
128) Linux与unix shell编程学习体会(根据书和其他帖子整理)
129) 管理脚本语言
130)***sed新手使用进阶全功略!***
131) Linux解释器原理
132) RE,grep,sed,awk论坛题目总结!(不断整理中......)

待续...

推荐(0)
收藏
得到OpenID
使用OpenID提供商
35OpenID 35OpenID MyOpenID MyOpenID Flickr Flickr
Google Google Yahoo Yahoo! AOL AOL
Blogger Blogger LiveJournal LiveJournal Verisign Verisign
ClaimID ClaimID Technorati Technorati Vidoop Vidoop
OpenID OpenID 帮助
您还没有登录,请登录后继续操作。
提示:您必需打开Cookie才能使用本系统
请输入您的 OpenID OpenID 登录:
例如:http://yourname.openid.35.com
close