有女朋友的男生的特点,看看你是不是也是这种。    

一、穷    
我想这已经是共识,没钱?那就别想谈女朋友了,别再幻想着什么纯洁无暇爱情了,都是扯淡。当你憋着小嘴愤愤不平的拿这个诅咒分手女友的无情的时候,那只能说明你无能懦夫懒惰加上小人,离开你是明智选择。给你个富婆说不定你绝情的嘴脸比谁都更丑陋。所以,男人,想讨老婆就赚钱吧不管你混B社会杀人放火贩毒contraband只要你能弄到票子女人就多得让你眼花了。    

二、丑    
经典语句,长得丑不是你的错,出来吓人就是你不对了,如果你敢说一句外表不是主要的,心灵美才是重要的,打住,那我就给你一头猪一样的恐龙做老婆我看你什么反映,己所不欲勿施与人,当你做着癞蛤蟆想吃天鹅肉的美梦时,女孩还在走着灰姑娘的神呢。    

三、薄    
这个薄是脸皮薄的意思,如果你文质彬彬,甚至会害羞,傻傻的,你如果不是内心真有点城府的话,那看来你跟异性也是绝缘了,别想着八十年代电影里女孩说傻的可爱了,时代不同了,并且进步太快了。如果你能达到不要脸的流氓地步,也是泡妞的最高境界了。    

四、专    
这里指的是在一棵树上吊死,如果你是个痴情专一的汉字,对一个MM渴望用坚持和痴情来感动,我想你离沉重打击不远了,现在的MM才不喜欢你用情专一呢,如果你能到处沾花惹草正说明你的本事,MM虽然会幽怨,其实底子里才更看得起你呢。保证你召之即来,挥之即去。    

五、笨    
这里的笨是指嘴笨,不需要你多厉害的口才,但是甜言蜜语是要会说的,哪怕你心里想着另一个MM,口里把对这个MM的感情换个名字说给那个听也行,爱的肉麻。    

六、真    
其实和五差不多,就是太真诚了,MM是要来骗和哄的,你傻傻的都说实话掏老底,嘿嘿,那你也等着MM和你拜拜吧!    

七、小    
此小非彼小,嘿嘿,是胆小,好像和三类似,但也不是,只要有机会,能拉手早拉手,拉了手了要赶快亲,亲完了赶快找地上床,不要觉得太快了,现在是个效率的社会,你不快有人比你快,也别担心MM会觉得你轻浮,她比你还急呢。不信?等上了床你就知道了。    

八、跑    
专指看贴不回贴就跑了的人,这类也是找不到女朋友的,自己掂量吧!
Linux程序设计入门--文件操作
Linux下文件的操作
前言:
我们在这一节将要讨论linux下文件操作的各个函数.
文件的创建和读写
文件的各个属性
目录文件的操作
管道文件
----------------------------------------------------------------------------
----
1。文件的创建和读写
我假设你已经知道了标准级的文件操作的各个函数(fopen,fread,fwrite等等).当然
如果你不清楚的话也不要着急.我们讨论的系统级的文件操作实际上是为标准级文件操作
服务的.
当我们需要打开一个文件进行读写操作的时候,我们可以使用系统调用函数open.使用完
成以后我们调用另外一个close函数进行关闭操作.
#i nclude <fcntl.h>
#i nclude <unistd.h>
#i nclude <sys/types.h>
#i nclude <sys/stat.h>

int open(const char *pathname,int flags);
int open(const char *pathname,int flags,mode_t mode);
int close(int fd);
open函数有两个形式.其中pathname是我们要打开的文件名(包含路径名称,缺省是认为在
当前路径下面).flags可以去下面的一个值或者是几个值的组合.
O_RDONLY:以只读的方式打开文件.
O_WRONLY:以只写的方式打开文件.
O_RDWR:以读写的方式打开文件.
O_APPEND:以追加的方式打开文件.
O_CREAT:创建一个文件.
O_EXEC:如果使用了O_CREAT而且文件已经存在,就会发生一个错误.
O_NOBLOCK:以非阻塞的方式打开一个文件.
O_TRUNC:如果文件已经存在,则删除文件的内容.
前面三个标志只能使用任意的一个.如果使用了O_CREATE标志,那么我们要使用open的第
二种形式.还要指定mode标志,用来表示文件的访问权限.mode可以是以下情况的组合.
-----------------------------------------------------------------
S_IRUSR 用户可以读 S_IWUSR 用户可以写
S_IXUSR 用户可以执行 S_IRWXU 用户可以读写执行
-----------------------------------------------------------------
S_IRGRP 组可以读 S_IWGRP 组可以写
S_IXGRP 组可以执行 S_IRWXG 组可以读写执行
-----------------------------------------------------------------
S_IROTH 其他人可以读 S_IWOTH 其他人可以写
S_IXOTH 其他人可以执行 S_IRWXO 其他人可以读写执行
-----------------------------------------------------------------
S_ISUID 设置用户执行ID S_ISGID 设置组的执行ID
-----------------------------------------------------------------
我们也可以用数字来代表各个位的标志.Linux总共用5个数字来表示文件的各种权限.
00000.第一位表示设置用户ID.第二位表示设置组ID,第三位表示用户自己的权限位,第四
位表示组的权限,最后一位表示其他人的权限.
每个数字可以取1(执行权限),2(写权限),4(读权限),0(什么也没有)或者是这几个值的和
..
比如我们要创建一个用户读写执行,组没有权限,其他人读执行的文件.设置用户ID位那么
我们可以使用的模式是--1(设置用户ID)0(组没有设置)7(1+2+4)0(没有权限,使用缺省)
5(1+4)即10705:
open("temp",O_CREAT,10705);
如果我们打开文件成功,open会返回一个文件描述符.我们以后对文件的所有操作就可以
对这个文件描述符进行操作了.
当我们操作完成以后,我们要关闭文件了,只要调用close就可以了,其中fd是我们要关闭
的文件描述符.
文件打开了以后,我们就要对文件进行读写了.我们可以调用函数read和write进行文件的
读写.
#i nclude <unistd.h>
ssize_t read(int fd, void *buffer,size_t count);
ssize_t write(int fd, const void *buffer,size_t count);
fd是我们要进行读写操作的文件描述符,buffer是我们要写入文件内容或读出文件内容的
内存地址.count是我们要读写的字节数.
对于普通的文件read从指定的文件(fd)中读取count字节到buffer缓冲区中(记住我们必
须提供一个足够大的缓冲区),同时返回count.
如果read读到了文件的结尾或者被一个信号所中断,返回值会小于count.如果是由信号中
断引起返回,而且没有返回数据,read会返回-1,且设置errno为EINTR.当程序读到了文件
结尾的时候,read会返回0.
write从buffer中写count字节到文件fd中,成功时返回实际所写的字节数.
下面我们学习一个实例,这个实例用来拷贝文件.
#i nclude <unistd.h>
#i nclude <fcntl.h>
#i nclude <stdio.h>
#i nclude <sys/types.h>
#i nclude <sys/stat.h>
#i nclude <errno.h>
#i nclude <string.h>
#define BUFFER_SIZE 1024
int main(int argc,char **argv)
{
int from_fd,to_fd;
int bytes_read,bytes_write;
char buffer[BUFFER_SIZE];
char *ptr;
if(argc!=3)
{
fprintf(stderr,"Usage:%s fromfile tofile\n\a",argv[0]);
exit(1);
}
/* 打开源文件 */
if((from_fd=open(argv[1],O_RDONLY))==-1)
{
fprintf(stderr,"Open %s Error:%s\n",argv[1],strerror(errno));
exit(1);
}
/* 创建目的文件 */
if((to_fd=open(argv[2],O_WRONLY O_CREAT,S_IRUSR S_IWUSR))==-1)
{
fprintf(stderr,"Open %s Error:%s\n",argv[2],strerror(errno));
exit(1);
}
/* 以下代码是一个经典的拷贝文件的代码 */
while(bytes_read=read(from_fd,buffer,BUFFER_SIZE))
{
/* 一个致命的错误发生了 */
if((bytes_read==-1)&&(errno!=EINTR)) break;
else if(bytes_read>0)
{
ptr=buffer;
while(bytes_write=write(to_fd,ptr,bytes_read))
{
/* 一个致命错误发生了 */
if((bytes_write==-1)&&(errno!=EINTR))break;
/* 写完了所有读的字节 */
else if(bytes_write==bytes_read) break;
/* 只写了一部分,继续写 */
else if(bytes_write>0)
{
ptr+=bytes_write;
bytes_read-=bytes_write;
}
}
/* 写的时候发生的致命错误 */
if(bytes_write==-1)break;
}
}
close(from_fd);
close(to_fd);
exit(0);
}
2。文件的各个属性
文件具有各种各样的属性,除了我们上面所知道的文件权限以外,文件还有创建时间
,大小等等属性.
有时侯我们要判断文件是否可以进行某种操作(读,写等等).这个时候我们可以使用acce
ss函数.
#i nclude <unistd.h>

int access(const char *pathname,int mode);
pathname:是文件名称,mode是我们要判断的属性.可以取以下值或者是他们的组合.
R_OK文件可以读,W_OK文件可以写,X_OK文件可以执行,F_OK文件存在.当我们测试成功时
,函数返回0,否则如果有一个条件不符时,返回-1.
如果我们要获得文件的其他属性,我们可以使用函数stat或者fstat.
#i nclude <sys/stat.h>
#i nclude <unistd.h>
int stat(const char *file_name,struct stat *buf);
int fstat(int filedes,struct stat *buf);
struct stat {
dev_t st_dev; /* 设备 */
ino_t st_ino; /* 节点 */
mode_t st_mode; /* 模式 */
nlink_t st_nlink; /* 硬连接 */
uid_t st_uid; /* 用户ID */
gid_t st_gid; /* 组ID */
dev_t st_rdev; /* 设备类型 */
off_t st_off; /* 文件字节数 */
unsigned long st_blksize; /* 块大小 */
unsigned long st_blocks; /* 块数 */
time_t st_atime; /* 最后一次访问时间 */
time_t st_mtime; /* 最后一次修改时间 */
time_t st_ctime; /* 最后一次改变时间(指属性) */
};
stat用来判断没有打开的文件,而fstat用来判断打开的文件.我们使用最多的属性是st_
mode.通过着属性我们可以判断给定的文件是一个普通文件还是一个目录,连接等等.可以
使用下面几个宏来判断.
S_ISLNK(st_mode):是否是一个连接.S_ISREG是否是一个常规文件.S_ISDIR是否是一个目
录S_ISCHR是否是一个字符设备.S_ISBLK是否是一个块设备S_ISFIFO是否 是一个FIFO文
件.S_ISSOCK是否是一个SOCKET文件. 我们会在下面说明如何使用这几个宏的.
3。目录文件的操作
在我们编写程序的时候,有时候会要得到我们当前的工作路径。C库函数提供了get
cwd来解决这个问题。
#i nclude <unistd.h>

char *getcwd(char *buffer,size_t size);
我们提供一个size大小的buffer,getcwd会把我们当前的路径考到buffer中.如果buffer
太小,函数会返回-1和一个错误号.
Linux提供了大量的目录操作函数,我们学习几个比较简单和常用的函数.
#i nclude <dirent.h>
#i nclude <unistd.h>
#i nclude <fcntl.h>
#i nclude <sys/types.h>
#i nclude <sys/stat.h>
int mkdir(const char *path,mode_t mode);
DIR *opendir(const char *path);
struct dirent *readdir(DIR *dir);
void rewinddir(DIR *dir);
off_t telldir(DIR *dir);
void seekdir(DIR *dir,off_t off);
int closedir(DIR *dir);
struct dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[NAME_MAX+1]; /* 文件名称 */
mkdir很容易就是我们创建一个目录,opendir打开一个目录为以后读做准备.readdir读一
个打开的目录.rewinddir是用来重读目录的和我们学的rewind函数一样.closedir是关闭
一个目录.telldir和seekdir类似与ftee和fseek函数.
下面我们开发一个小程序,这个程序有一个参数.如果这个参数是一个文件名,我们输出这
个文件的大小和最后修改的时间,如果是一个目录我们输出这个目录下所有文件的大小和
修改时间.
#i nclude <unistd.h>
#i nclude <stdio.h>
#i nclude <errno.h>
#i nclude <sys/types.h>
#i nclude <sys/stat.h>
#i nclude <dirent.h>
#i nclude <time.h>
static int get_file_size_time(const char *filename)
{
struct stat statbuf;
if(stat(filename,&statbuf)==-1)
{
printf("Get stat on %s Error:%s\n",
filename,strerror(errno));
return(-1);
}
if(S_ISDIR(statbuf.st_mode))return(1);
if(S_ISREG(statbuf.st_mode))
printf("%s size:%ld bytes\tmodified at %s",
filename,statbuf.st_size,ctime(&statbuf.st_mtime));

return(0);
}
int main(int argc,char **argv)
{
DIR *dirp;
struct dirent *direntp;
int stats;
if(argc!=2)
{
printf("Usage:%s filename\n\a",argv[0]);
exit(1);
}
if(((stats=get_file_size_time(argv[1]))==0) (stats==-1))exit(1);
if((dirp=opendir(argv[1]))==NULL)
{
printf("Open Directory %s Error:%s\n",
argv[1],strerror(errno));
exit(1);
}
while((direntp=readdir(dirp))!=NULL)
if(get_file_size_time(direntp-<d_name)==-1)break;
closedir(dirp);
exit(1);
}
4。管道文件
Linux提供了许多的过滤和重定向程序,比如more cat
等等.还提供了< >   <<等等重定向操作符.在这些过滤和重 定向程序当中,都用到了管
道这种特殊的文件.系统调用pipe可以创建一个管道.
#i nclude<unistd.h>

int pipe(int fildes[2]);
pipe调用可以创建一个管道(通信缓冲区).当调用成功时,我们可以访问文件描述符fild
es[0],fildes[1].其中fildes[0]是用来读的文件描述符,而fildes[1]是用来写的文件描
述符.
在实际使用中我们是通过创建一个子进程,然后一个进程写,一个进程读来使用的.
关于进程通信的详细情况请查看进程通信
#i nclude <stdio.h>
#i nclude <stdlib.h>
#i nclude <unistd.h>
#i nclude <string.h>
#i nclude <errno.h>
#i nclude <sys/types.h>
#i nclude <sys/wait.h>
#define BUFFER 255
int main(int argc,char **argv)
{
char buffer[BUFFER+1];
int fd[2];
if(argc!=2)
{
fprintf(stderr,"Usage:%s string\n\a",argv[0]);
exit(1);
}
if(pipe(fd)!=0)
{
fprintf(stderr,"Pipe Error:%s\n\a",strerror(errno));
exit(1);
}
if(fork()==0)
{
close(fd[0]);
printf("Child[%d] Write to pipe\n\a",getpid());
snprintf(buffer,BUFFER,"%s",argv[1]);
write(fd[1],buffer,strlen(buffer));
printf("Child[%d] Quit\n\a",getpid());
exit(0);
}
else
{
close(fd[1]);
printf("Parent[%d] Read from pipe\n\a",getpid());
memset(buffer,'''',BUFFER+1);
read(fd[0],buffer,BUFFER);
printf("Parent[%d] Read:%s\n",getpid(),buffer);
exit(1);
}
}
为了实现重定向操作,我们需要调用另外一个函数dup2.
#i nclude <unistd.h>

int dup2(int oldfd,int newfd);
dup2将用oldfd文件描述符来代替newfd文件描述符,同时关闭newfd文件描述符.也就是说
,
所有向newfd操作都转到oldfd上面.下面我们学习一个例子,这个例子将标准输出重定向
到一个文件.
#i nclude <unistd.h>
#i nclude <stdio.h>
#i nclude <errno.h>
#i nclude <fcntl.h>
#i nclude <string.h>
#i nclude <sys/types.h>
#i nclude <sys/stat.h>
#define BUFFER_SIZE 1024
int main(int argc,char **argv)
{
int fd;
char buffer[BUFFER_SIZE];
if(argc!=2)
{
fprintf(stderr,"Usage:%s outfilename\n\a",argv[0]);
exit(1);
}
if((fd=open(argv[1],O_WRONLY O_CREAT O_TRUNC,S_IRUSR S_IWUSR))==-1)
{
fprintf(stderr,"Open %s Error:%s\n\a",argv[1],strerror(errno));
exit(1);
}
if(dup2(fd,STDOUT_FILENO)==-1)
{
fprintf(stderr,"Redirect Standard Out Error:%s\n\a",strerror(errno));
exit(1);
}
fprintf(stderr,"Now,please input string");
fprintf(stderr,"(To quit use CTRL+D)\n");
while(1)
{
fgets(buffer,BUFFER_SIZE,stdin);
if(feof(stdin))break;
write(STDOUT_FILENO,buffer,strlen(buffer));
}
exit(0);
}
好了,文件一章我们就暂时先讨论到这里,学习好了文件的操作我们其实已经可以写出一
些比较有用的程序了.我们可以编写一个实现例如dir,mkdir,cp,mv等等常用的文件操作
命令了.
想不想自己写几个试一试呢?

4)程序设计入门--时间概念
前言:Linux下的时间概念
这一章我们学习Linux的时间表示和计算函数
时间的表示
时间的测量
计时器的使用
1。时间表示 在程序当中,我们经常要输出系统当前的时间,比如我们使用date命令
的输出结果.这个时候我们可以使用下面两个函数
#i nclude <time.h>

time_t time(time_t *tloc);
char *ctime(const time_t *clock);
time函数返回从1970年1月1日0点以来的秒数.存储在time_t结构之中.不过这个函数的返
回值对于我们来说没有什么实际意义.这个时候我们使用第二个函数将秒数转化为字符串
.. 这个函数的返回类型是固定的:一个可能值为. Thu Dec 7 14:58:59 2000 这个字符串
的长度是固定的为26
2。时间的测量 有时候我们要计算程序执行的时间.比如我们要对算法进行时间分析
..这个时候可以使用下面这个函数.
#i nclude <sys/time.h>

int gettimeofday(struct timeval *tv,struct timezone *tz);
strut timeval {
long tv_sec; /* 秒数 */
long tv_usec; /* 微秒数 */
};
gettimeofday将时间保存在结构tv之中.tz一般我们使用NULL来代替.
#i nclude <sys/time.h<
#i nclude <stdio.h<
#i nclude <math.h<
void function()
{
unsigned int i,j;
double y;
for(i=0;i<1000;i++)
for(j=0;j<1000;j++)
y=sin((double)i);
}
main()
{
struct timeval tpstart,tpend;
float timeuse;
gettimeofday(&tpstart,NULL);
function();
gettimeofday(&tpend,NULL);
timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+
tpend.tv_usec-tpstart.tv_usec;
timeuse/=1000000;
printf("Used Time:%f\n",timeuse);
exit(0);
}
这个程序输出函数的执行时间,我们可以使用这个来进行系统性能的测试,或者是函数算
法的效率分析.在我机器上的一个输出结果是: Used Time:0.556070
3。计时器的使用 Linux操作系统为每一个进程提供了3个内部间隔计时器.
ITIMER_REAL:减少实际时间.到时的时候发出SIGALRM信号.
ITIMER_VIRTUAL:减少有效时间(进程执行的时间).产生SIGVTALRM信号.
ITIMER_PROF:减少进程的有效时间和系统时间(为进程调度用的时间).这个经常和上面一
个使用用来计算系统内核时间和用户时间.产生SIGPROF信号.
具体的操作函数是:
#i nclude <sys/time.h>
int getitimer(int which,struct itimerval *value);
int setitimer(int which,struct itimerval *newval,
struct itimerval *oldval);
struct itimerval {
struct timeval it_interval;
struct timeval it_value;
}
getitimer函数得到间隔计时器的时间值.保存在value中 setitimer函数设置间隔计时器
的时间值为newval.并将旧值保存在oldval中. which表示使用三个计时器中的哪一个.
itimerval结构中的it_value是减少的时间,当这个值为0的时候就发出相应的信号了. 然
后设置为it_interval值.
#i nclude <sys/time.h>
#i nclude <stdio.h>
#i nclude <unistd.h>
#i nclude <signal.h>
#i nclude <string.h>
#define PROMPT "时间已经过去了两秒钟\n\a"
char *prompt=PROMPT;
unsigned int len;
void prompt_info(int signo)
{
write(STDERR_FILENO,prompt,len);
}
void init_sigaction(void)
{
struct sigaction act;
act.sa_handler=prompt_info;
act.sa_flags=0;
sigemptyset(&act.sa_mask);
sigaction(SIGPROF,&act,NULL);
}
void init_time()
{
struct itimerval value;
value.it_value.tv_sec=2;
value.it_value.tv_usec=0;
value.it_interval=value.it_value;
setitimer(ITIMER_PROF,&value,NULL);
}
int main()
{
len=strlen(prompt);
init_sigaction();
init_time();
while(1);
exit(0);
}
这个程序每执行两秒中之后会输出一个提示.

5)Linux程序设计入门--信号处理
Linux下的信号事件
前言:这一章我们讨论一下Linux下的信号处理函数.
Linux下的信号处理函数:
信号的产生
信号的处理
其它信号函数
一个实例
1。信号的产生
Linux下的信号可以类比于DOS下的INT或者是Windows下的事件.在有一个信号发生时
候相信的信号就会发送给相应的进程.在Linux下的信号有以下几个. 我们使用 kill -l
命令可以得到以下的输出结果:
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD
18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN
22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO
30) SIGPWR
关于这些信号的详细解释请查看man 7 signal的输出结果. 信号事件的发生有两个来源
:一个是硬件的原因(比如我们按下了键盘),一个是软件的原因(比如我们使用系统函数或
者是命令发出信号). 最常用的四个发出信号的系统函数是kill, raise, alarm和setit
imer函数. setitimer函数我们在计时器的使用 那一章再学习.
#i nclude <sys/types.h>
#i nclude <signal.h>
#i nclude <unistd.h>
int kill(pid_t pid,int sig);
int raise(int sig);
unisigned int alarm(unsigned int seconds);
kill系统调用负责向进程发送信号sig.
如果pid是正数,那么向信号sig被发送到进程pid.
如果pid等于0,那么信号sig被发送到所以和pid进程在同一个进程组的进程
如果pid等于-1,那么信号发给所有的进程表中的进程,除了最大的哪个进程号.
如果pid由于-1,和0一样,只是发送进程组是-pid.
我们用最多的是第一个情况.还记得我们在守护进程那一节的例子吗?我们那个时候用这
个函数杀死了父进程守护进程的创建
raise系统调用向自己发送一个sig信号.我们可以用上面那个函数来实现这个功能的.
alarm函数和时间有点关系了,这个函数可以在seconds秒后向自己发送一个SIGALRM信号
.. 下面这个函数会有什么结果呢?
#i nclude <unistd.h>
main()
{
unsigned int i;
alarm(1);
for(i=0;1;i++)
printf("I=%d",i);
}
SIGALRM的缺省操作是结束进程,所以程序在1秒之后结束,你可以看看你的最后I值为多少
,来比较一下大家的系统性能差异(我的是2232).
2。信号操作 有时候我们希望进程正确的执行,而不想进程受到信号的影响,比如我
们希望上面那个程序在1秒钟之后不结束.这个时候我们就要进行信号的操作了.
信号操作最常用的方法是信号屏蔽.信号屏蔽要用到下面的几个函数.
#i nclude <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set,int signo);
int sigdelset(sigset_t *set,int signo);
int sigismember(sigset_t *set,int signo);
int sigprocmask(int how,const sigset_t *set,sigset_t *oset);
sigemptyset函数初始化信号集合set,将set设置为空.sigfillset也初始化信号集合,只
是将信号集合设置为所有信号的集合.sigaddset将信号signo加入到信号集合之中,sigd
elset将信号从信号集合中删除.sigismember查询信号是否在信号集合之中.
sigprocmask是最为关键的一个函数.在使用之前要先设置好信号集合set.这个函数的作
用是将指定的信号集合set加入到进程的信号阻塞集合之中去,如果提供了oset那么当前
的进程信号阻塞集合将会保存在oset里面.参数how决定函数的操作方式.
SIG_BLOCK:增加一个信号集合到当前进程的阻塞集合之中.
SIG_UNBLOCK:从当前的阻塞集合之中删除一个信号集合.
SIG_SETMASK:将当前的信号集合设置为信号阻塞集合.
以一个实例来解释使用这几个函数.
#i nclude <signal.h>
#i nclude <stdio.h>
#i nclude <math.h>
#i nclude <stdlib.h>
int main(int argc,char **argv)
{
double y;
sigset_t intmask;
int i,repeat_factor;
if(argc!=2)
{
fprintf(stderr,"Usage:%s repeat_factor\n\a",argv[0]);
exit(1);
}
if((repeat_factor=atoi(argv[1]))<1)repeat_factor=10;
sigemptyset(&intmask); /* 将信号集合设置为空 */
sigaddset(&intmask,SIGINT); /* 加入中断 Ctrl+C 信号*/
while(1)
{
/*阻塞信号,我们不希望保存原来的集合所以参数为NULL*/
sigprocmask(SIG_BLOCK,&intmask,NULL);
fprintf(stderr,"SIGINT signal blocked\n");
for(i=0;i<repeat_factor;i++)y=sin((double)i);
fprintf(stderr,"Blocked calculation is finished\n");
/* 取消阻塞 */
sigprocmask(SIG_UNBLOCK,&intmask,NULL);
fprintf(stderr,"SIGINT signal unblocked\n");
for(i=0;i<repeat_factor;i++)y=sin((double)i);
fprintf(stderr,"Unblocked calculation is finished\n");
}
exit(0);
}
程序在运行的时候我们要使用Ctrl+C来结束.如果我们在第一计算的时候发出SIGINT信号
,由于信号已经屏蔽了,所以程序没有反映.只有到信号被取消阻塞的时候程序才会结束.
注意我们只要发出一次SIGINT信号就可以了,因为信号屏蔽只是将信号加入到信号阻塞
集合之中,并没有丢弃这个信号.一旦信号屏蔽取消了,这个信号就会发生作用.
有时候我们希望对信号作出及时的反映的,比如当拥护按下Ctrl+C时,我们不想什么事情
也不做,我们想告诉用户你的这个操作不好,请不要重试,而不是什么反映也没有的. 这个
时候我们要用到sigaction函数.
#i nclude <signal.h>

int sigaction(int signo,const struct sigaction *act,
struct sigaction *oact);
struct sigaction {
void (*sa_handler)(int signo);
void (*sa_sigaction)(int siginfo_t *info,void *act);
sigset_t sa_mask;
int sa_flags;
void (*sa_restore)(void);
}
这个函数和结构看起来是不是有点恐怖呢.不要被这个吓着了,其实这个函数的使用相当
简单的.我们先解释一下各个参数的含义. signo很简单就是我们要处理的信号了,可以是
任何的合法的信号.有两个信号不能够使用(SIGKILL和SIGSTOP). act包含我们要对这个
信号进行如何处理的信息.oact更简单了就是以前对这个函数的处理信息了,主要用来保
存信息的,一般用NULL就OK了.
信号结构有点复杂.不要紧我们慢慢的学习.
sa_handler是一个函数型指针,这个指针指向一个函数,这个函数有一个参数.这个函数就
是我们要进行的信号操作的函数. sa_sigaction,sa_restore和sa_handler差不多的,只
是参数不同罢了.这两个元素我们很少使用,就不管了.
sa_flags用来设置信号操作的各个情况.一般设置为0好了.sa_mask我们已经学习过了
在使用的时候我们用sa_handler指向我们的一个信号操作函数,就可以了.sa_handler有
两个特殊的值:SIG_DEL和SIG_IGN.SIG_DEL是使用缺省的信号操作函数,而SIG_IGN是使用
忽略该信号的操作函数.
这个函数复杂,我们使用一个实例来说明.下面这个函数可以捕捉用户的CTRL+C信号.并输
出一个提示语句.
#i nclude <signal.h>
#i nclude <stdio.h>
#i nclude <string.h>
#i nclude <errno.h>
#i nclude <unistd.h>
#define PROMPT "你想终止程序吗?"
char *prompt=PROMPT;
void ctrl_c_op(int signo)
{
write(STDERR_FILENO,prompt,strlen(prompt));
}
int main()
{
struct sigaction act;
act.sa_handler=ctrl_c_op;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
if(sigaction(SIGINT,&act,NULL)<0)
{
fprintf(stderr,"Install Signal Action Error:%s\n\a",strerror(errno));
exit(1);
}
while(1);
}
在上面程序的信号操作函数之中,我们使用了write函数而没有使用fprintf函数.是因为
我们要考虑到下面这种情况.如果我们在信号操作的时候又有一个信号发生,那么程序该
如何运行呢? 为了处理在信号处理函数运行的时候信号的发生,我们需要设置sa_mask成
员. 我们将我们要屏蔽的信号添加到sa_mask结构当中去,这样这些函数在信号处理的时
候就会被屏蔽掉的.
3。其它信号函数 由于信号的操作和处理比较复杂,我们再介绍几个信号操作函数.

#i nclude <unistd.h>
#i nclude <signal.h>
int pause(void);
int sigsuspend(const sigset_t *sigmask);
pause函数很简单,就是挂起进程直到一个信号发生了.而sigsuspend也是挂起进程只是在
调用的时候用sigmask取代当前的信号阻塞集合.
#i nclude <sigsetjmp>
int sigsetjmp(sigjmp_buf env,int val);
void siglongjmp(sigjmp_buf env,int val);
还记得goto函数或者是setjmp和longjmp函数吗.这两个信号跳转函数也可以实现程序的
跳转让我们可以从函数之中跳转到我们需要的地方.
由于上面几个函数,我们很少遇到,所以只是说明了一下,详细情况请查看联机帮助.
4。一个实例 还记得我们在守护进程创建的哪个程序吗?守护进程在这里我们把那个
程序加强一下. 下面这个程序会在也可以检查用户的邮件.不过提供了一个开关,如果用
户不想程序提示有新的邮件到来,可以向程序发送SIGUSR2信号,如果想程序提供提示可以
发送SIGUSR1信号.
#i nclude <unistd.h>
#i nclude <stdio.h>
#i nclude <errno.h>
#i nclude <fcntl.h>
#i nclude <signal.h>
#i nclude <string.h>
#i nclude <pwd.h>
#i nclude <sys/types.h>
#i nclude <sys/stat.h>
/* Linux 的默任个人的邮箱地址是 /var/spool/mail/ */
#define MAIL_DIR "/var/spool/mail/"
/* 睡眠10秒钟 */
#define SLEEP_TIME 10
#define MAX_FILENAME 255
unsigned char notifyflag=1;
long get_file_size(const char *filename)
{
struct stat buf;
if(stat(filename,&;buf)==-1)
{
if(errno==ENOENT)return 0;
else return -1;
}
return (long)buf.st_size;
}
void send_mail_notify(void)
{
fprintf(stderr,"New mail has arrived7\n");
}
void turn_on_notify(int signo)
{
notifyflag=1;
}
void turn_off_notify(int signo)
{
notifyflag=0;
}
int check_mail(const char *filename)
{
long old_mail_size,new_mail_size;
sigset_t blockset,emptyset;
sigemptyset(&;blockset);
sigemptyset(&;emptyset);
sigaddset(&;blockset,SIGUSR1);
sigaddset(&;blockset,SIGUSR2);
old_mail_size=get_file_size(filename);
if(old_mail_size<0)return 1;
if(old_mail_size>0) send_mail_notify();
sleep(SLEEP_TIME);
while(1)
{
if(sigprocmask(SIG_BLOCK,&;blockset,NULL)<0) return 1;
while(notifyflag==0)sigsuspend(&;emptyset);
if(sigprocmask(SIG_SETMASK,&;emptyset,NULL)<0) return 1;
new_mail_size=get_file_size(filename);
if(new_mail_size>old_mail_size)send_mail_notify;
old_mail_size=new_mail_size;
sleep(SLEEP_TIME);
}
}
int main(void)
{
char mailfile[MAX_FILENAME];
struct sigaction newact;
struct passwd *pw;
if((pw=getpwuid(getuid()))==NULL)
{
fprintf(stderr,"Get Login Name Error:%s\n\a",strerror(errno));
exit(1);
}
strcpy(mailfile,MAIL_DIR);
strcat(mailfile,pw->pw_name);
newact.sa_handler=turn_on_notify;
newact.sa_flags=0;
sigemptyset(&;newact.sa_mask);
sigaddset(&;newact.sa_mask,SIGUSR1);
sigaddset(&;newact.sa_mask,SIGUSR2);
if(sigaction(SIGUSR1,&;newact,NULL)<0)
fprintf(stderr,"Turn On Error:%s\n\a",strerror(errno));
newact.sa_handler=turn_off_notify;
if(sigaction(SIGUSR1,&;newact,NULL)<0)
fprintf(stderr,"Turn Off Error:%s\n\a",strerror(errno));
check_mail(mailfile);
exit(0);
}
信号操作是一件非常复杂的事情,比我们想象之中的复杂程度还要复杂,如果你想彻底的
弄清楚信号操作的各个问题,那么除了大量的练习以外还要多看联机手册.不过如果我们
只是一般的使用的话,有了上面的几个函数也就差不多了. 我们就介绍到这里了.

来源:http://bianbian.org/technology/295.html
用PHP生成结构体:
http://bbs.chinaunix.net/viewthread.php?tid=1034276
尽管php是用C语言开发的,不过令我不解的是php没有提供对结构体struct的直接支持。
不过php提供了pack和unpack函数,用来进行二进制数据(binary data)和php内部数据的互转:

  1. string pack ( string $format [, mixed $args [, mixed $...]] )
  2. //Pack given arguments into binary string according to format.
  3. array unpack ( string $format, string $data )
  4. //Unpacks from a binary string into an array according to the given format.

其中,$format跟perl里的pack格式类似,有如下一些(中文是我加的,有不准确的欢迎提出):
a NUL-padded string,即“\0”作为“空字符”的表示形式
A SPACE-padded string,空格作为“空字符”的表示形式
h Hex string, low nibble first,升序位顺序
H Hex string, high nibble first,降序位顺序
c signed char,有符号单字节
C unsigned char,无符号单字节
s signed short (always 16 bit, machine byte order)
S unsigned short (always 16 bit, machine byte order)
n unsigned short (always 16 bit, big endian byte order)
v unsigned short (always 16 bit, little endian byte order)
i signed integer (machine dependent size and byte order)
I unsigned integer (machine dependent size and byte order)
l signed long (always 32 bit, machine byte order)
L unsigned long (always 32 bit, machine byte order)
N unsigned long (always 32 bit, big endian byte order)
V unsigned long (always 32 bit, little endian byte order)
f float (machine dependent size and representation)
d double (machine dependent size and representation)
x NUL byte,实际使用的时候作为跳过多少字节用,很有用
X Back up one byte,后退1字节
@ NUL-fill to absolute position,实际使用的时候作为从开头跳到某字节用,很有用

实际使用发现:C里的“\0”(即字符串终止符)在php里并不是终止符,而是作为了字符串的一部分。因此,必须对“\0”进行特殊处理,才能进行struct和php内部数据的完美互转。比如 char name[10]; 如果实际数据是“62 69 61 6E 00 62 69 61 6E 00”,在C语言里第5个位置有终止符,name应该是“bian”;而用了unpack转换以后在php里的name却是“bian\0bian\0”。
一开始我用了strpos函数找到“\0”的位置,然后进行substr截取:

  1. $name = substr($name, 0, strpos($name, "\0"));

不过很Faint的事情发生了,不知道是strpos的bug还是substr的bug(其实测试一下就知道,懒得试),有些字符串没问题,有些字符串却只能得到空值(即$name == ”)。很是郁闷,后来找了个strtok函数,这下没有问题了:

  1. $name = strtok($name, "\0");

难为大家看了那么多,下面写个完整的php读取二进制数据流(C语言结构体struct数据)文件的示例代码:
首先是C的struct定义示例,为了演示,我就写个简单点的,实际对照上面那个$format格式表应该没有问题:

  1. struct BIANBIAN {
  2. char name[10];
  3. char pass[33];
  4. int age;
  5. unsigned char flag;
  6. };

比如有个“bianbian.org”文件,内容就是上面的N个BIANBIAN结构体构成的。读取的php代码:

  1. //下面根据struct确定$format,注意int类型跟机器环境有关,我的32位Linux是4个长度
  2. $format = 'a10name/a33pass/iage/Cflag';
  3. //确定一个struct占用多少长度字节,如果只是读取单个结构体这是不需要的
  4. $length = 10 + 33 + 4 + 1;
  5. //也可以用fopen + fread + fclose,不过file_get_contents因为可以mmap,效率更高
  6. $data = file_get_contents('bianbian.org', 'r');
  7. for ($i = 0, $c = strlen($data); $i < $c; $i += $length) {
  8. $bianbian = unpack("@$i/$format", $data);
  9. //reference传递是php 5才支持的,如果用php4,得用其他办法
  10. foreach ($bianbian as &$value) {
  11. if (is_string($value)) {
  12. $value = strtok($value, "\0");
  13. }
  14. }
  15. print_r($bianbian);
  16. }
  17. //输出为array,即类似:
  18. Array
  19. (
  20. [name] => 'bianbian'
  21. [pass] => 'bianbian.org'
  22. [age] => 100
  23. [flag] => 0
  24. )
  25. ...

pack应该跟unpack相反






==================================================
实际使用发现:C里的“\0”(即字符串终止符)在php里并不是终止符,而是作为了字符串的一部分。因此,必须对“\0”进行特殊处理,才能进行 struct和php内部数据的完美互转。比如 char name[10]; 如果实际数据是“62 69 61 6E 00 62 69 61 6E 00”,在C语言里第5个位置有终止符,name应该是“bian”;而用了unpack转换以后在php里的name却是“bian\0bian \0”。
一开始我用了strpos函数找到“\0”的位置,然后进行substr截取.
不过很Faint的事情发生了,不知道是strpos的bug还是substr的bug(其实测试一下就知道,懒得试),有些字符串没问题,有些字符串却只能得到空值(即$name == ”)。很是郁闷,后来找了个strtok函数,这下没有问题了.
难为大家看了那么多,下面写个完整的php读取二进制数据流(C语言结构体struct数据)文件的示例代码:
首先是C的struct定义示例,为了演示,我就写个简单点的,实际对照上面那个$format格式表应该没有问题:
struct TEST{
    char name[10];
    char pass[33];
    int  age;
    unsigned char flag;
};
比如有个“file.dat”文件,内容就是上面的N个BIANBIAN结构体构成的。读取的php代码:
         //下面根据struct确定$format,注意int类型跟机器环境有关,我的32位Linux是4个长度  
     $format = 'a10name/a33pass/iage/Cflag';  
     //确定一个struct占用多少长度字节,如果只是读取单个结构体这是不需要的  
     $length = 10 + 33 + 4 + 1;  
     //也可以用fopen + fread + fclose,不过file_get_contents因为可以mmap,效率更高  
     $data = file_get_contents('file.dat', 'r');  
     for ($i = 0, $c = strlen($data); $i < $c; $i += $length) {  
         $bianbian = unpack("$format", $data);  
         //reference传递是php 5才支持的,如果用php4,得用其他办法  
         foreach ($bianbian as &$value) {  
             if (is_string($value)) {  
                 $value = strtok($value, "\0");  
             }  
         }  
         print_r($bianbian);  
     }  
    ?>
pack应该跟unpack相反。
顺便附上生成结构体文件的C语言代码:
    #include   
    #include   
    struct example        
    {      
        char name[10];  
        char pass[33];  
        int  age;  
        unsigned char flag;  
    };  
    int main()      
    {  
        example test;  
        example read;      
        FILE *fp;  
        test.age = 111;      
        test.flag = 10;  
        strcpy(test.name, "Hello World!");  
        strcpy(test.pass, "zbl110119");  
        fp = fopen("file.dat", "w+");  
        if (!fp)  
        {  
            printf("open file error!");  
            return -1;  
        }  
        rewind(fp);  
        fwrite(&test, sizeof(example), 1, fp);  
        rewind(fp);  
        fread(&read, sizeof(example), 1, fp);  
        printf("%d, %s\n", read.age, read.name);  
        fclose(fp);  
        return 0;  
    }
首先你要对你的环境进行配置

配置TomCat环境
1、到我的机器(IP为192.1.168.7,用户为Guest,口令没有)上的"共享"目录中,拷贝j2sdk-1_4_2_02-windows-i586-p.exe、jakarta-tomcat-5.0.14.zip、jakarta-struts-1.1.zip三个压包文件。
2、先双击j2sdk-1_4_2_02-windows-i586-p.exe安装jdk,最好安装到一个根目录下。在此假设安装在D:j2sdk1.4.2_02下。
3、安装TOMCAT。TOMCAT不用安装,只用直接解压jakarta-tomcat-5.0.14.zip到硬盘上。假设解压到D:TOMCAT下。
4、配置环境变量。右键点击"我的电脑"图标,选择"高级"子项,点击"环境变量"按扭。在"系统变量"中新建如下几个环境变量:
名称 键值 说明
JAVA_HOME D:j2sdk1.4.2_02 就是你的JDK的安装目录
CLASSPATH .;%JAVA_HOME%LIB
5、解压jakarta-struts-1.1.zip到任一目录,将其中jakarta-struts-1.1webapp目录下的struts-example.war文件拷贝到TOMCAT下的 omcatwebapps中
6、进入 omcatin目录,点击startup.bat以启动TomCat。(TomCat启动后点击shutdown.bat可关闭)
7、让TomCat在后台运行,打开ie,在地址栏中输入http://localhost:8080/可进入TomCat的主页,输入http://localhost:8080/struts-example可进入struts的一个例子。

祝大家安装顺利 :)

然后,我们来看一下STRUTS例子中的最重要的两个文件,这两个都是配置文件,

struts-config.xml(具体配置的情况我作了注释)

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<!--
This is the Struts configuration file for the example application,
using the proposed new syntax.
-->


<struts-config>

<!-- ========== Form Bean Definitions =================================== -->
<!-- FormBean是struts的一个概念,本质是JavaBean,用来自动存储页面表单中各个域的值,并在适当的时候回填表单域,不需要象传统那样request.getParameter("fieldName");,常被action-mappings中的action 使用 -->
<form-beans>
<!-- 稍后我们会新增一个GetparameterForm类,用来存储用户信息 -->
<form-bean name="GetParameterForm" type="beans.GetParameterForm"/>
</form-beans>

<!-- ========== Global Forward Definitions ============================== -->
<!--这里存放整个系统都可以使用的全局转向中转(Forward)地址 -->
<!-- 一般情况下,一个Action处理完毕后,会转发到一个JSP页面进行显示。这也是JSP中的MVC的实现的要点。-->
<global-forwards>
<!--failed.do和success.do将被当成servlet请求,到action-mappings中寻找对应的action处理。-->
<forward name="success" path="/success.do"/>
<forward name="fail" path="/fail.do"/>
</global-forwards>

<!-- ========== Action Mapping Definitions ============================== -->
<!--web.xml中后缀为.do的请求被转到这里处理。这里相当于struts的Model部分,Model部分是struts中比较灵活的地方。-->
<action-mappings>
<!--处理showinput.do的请求,使用的FormBean是GetparameterForm,既beans.GetParameterForm类,当处理过程发生错误时将返回index.jsp-->
<action path="/showinput" type="beans.ShowAction" name="GetParameterForm" scope="request" input="/index.jsp" />
<action path="/success" forward="/success.jsp"/>
<action path="/fail" forward="/error.jsp" />
</action-mappings>

</struts-config>

web.xml(具体配置的情况我作了注释)

<!-- Action Servlet Mapping -->
<!--该系统的servlet可以映射成.do为后缀的文件,后缀名可以改成任何名称.-->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

<!-- The Welcome File List -->
<!--该系统的默认首页是index.jsp,可以有多个,系统按次序找,类似IIS-->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<!-- Application Tag Library Descriptor -->
<!-- 定义标签库 -->
<!--
<taglib>
<taglib-uri>/WEB-INF/app.tld</taglib-uri>
<taglib-location>/WEB-INF/app.tld</taglib-location>
</taglib>
-->

</web-app>

这两个文件是我们用JDK+TOMCAT+STRUTS的基本配置,注意:在更改了这个配置后需要对TOMCAT进行重新启动!

在你的目录中存放你的.JSP文件,他们的编写你可以使用HTML或FRONGPAGE等工具编写,对于大家这个是比较简单的,在此我就不再觜书,代码如下:

INDEX.JSP

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.util.*,java.sql.*,java.text.*,java.io.*"%>

<form name="form1" method="post" action="showinput.do">
输入success将返回到"success"页面,否则返回到"fail"页面<br><br>
input:<input type="text" name="valu">  <input type="submit" value="submit">
</form>
<br>
<a href="success.do">success</a><br>
<a href="fail.do">fail</a>

SUCCESS.JSP

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.util.*,java.sql.*,java.text.*,java.io.*"%>

success!

ERROR.JSP

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.util.*,java.sql.*,java.text.*,java.io.*"%>

error page!

再在你的文件夹WEB-INFclasseseans中我们编写需要处理消息请求的类。具体代码如下:

GetParameterForm.java

package beans;
import org.apache.struts.action.ActionForm;
public class GetParameterForm extends ActionForm
{
private String valu="null";

public GetParameterForm() {
}

public void setValu(String s) {
valu = s;
}
public String getValu() {
return valu;
}
}

ShowAction.java

package beans;
import java.lang.reflect.InvocationTargetException;
import java.util.Locale;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.*;
import org.apache.struts.util.*;

public final class ShowAction extends Action
{
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
Locale locale = getLocale(request);
MessageResources messages = getResources(request);
HttpSession session = request.getSession();
GetParameterForm userform = (GetParameterForm) form;
if(userform.getValu().equals("success")) {
return(mapping.findForward("success"));
}
else {
System.out.println(userform.getValu());
return(mapping.findForward("fail"));
}
}
}


最后你可以运行了。

在TOMCAT中地址中填写http://localhost:8080/你的文件夹/

这是一个简单的例子,希望大家能喜欢,不知道我的讲解是否正确,请指教!
http://www.cnfug.org/journal/systems/2004/000081.html
#include <iostream>
class A
{
public:
    A(int i)
    {
        m_A = i;
    }
    ~A()
    {

    }
    static void print()
    {
        std::cout<< "A" <<std::endl;
    }
    friend class B;
protected:
    int m_A;
private:
};
class B
{
public:
    B(int i)
    {
        m_B = i;
    }
    static void print()
    {
        std::cout<< "B" << std::endl;
    }
    void show(B b)
    {
        b.a->m_A = 3;
        b.m_B = 2;
    }
protected:
private:
    A* a;
    int m_B;
};
template<class T1, class T2>
class CTestTemplate
{
public:
    CTestTemplate(T1 t)
    {
        m_number = t;
    }
    void print()
    {
        T2::print();
        std::cout<< m_number<< std::endl;
    }
protected:
private:
    T1 m_number;
};
int main(int argc, char* argv[])
{
    CTestTemplate<int, B> testtem(3);
    testtem.print();
}
IE浏览器里输入:javascript.document.cookie="name=xiangdong"
chrome里读取:
console.log(document.cookie)
language1=zh; uin=7srsOd27A3NlR3MU5LVzWg%3D%3D
chrome里设置:
document.cookie="name=xiangdong"
"name=xiangdong"
console.log(document.cookie)
name=xiangdong; language1=zh; uin=7srsOd27A3NlR3MU5LVzWg%3D%3D
===============================================
<script langrage=javascript>
// writeCookie("myCookie", "my name", 24);
// Stores the string "my name" in the cookie "myCookie" which expires after 24 hours.
// The hours parameter is optional; if hours is left out, the cookie value expires at the end of the visitor's browser session.
function writeCookie(name, value, hours)
{
  var expire = "";
  if(hours != null)
  {
    expire = new Date((new Date()).getTime() + hours * 3600000);
    expire = "; expires=" + expire.toGMTString();
  }
  document.cookie = name + "=" + escape(value) + expire;
}

// Example:
// alert( readCookie("myCookie") );

function readCookie(name)
{
  var cookieValue = "";
  var search = name + "=";
  if(document.cookie.length > 0)
  {
    offset = document.cookie.indexOf(search);
    if (offset != -1)
    {
      offset += search.length;
      end = document.cookie.indexOf(";", offset);
      if (end == -1) end = document.cookie.length;
      cookieValue = unescape(document.cookie.substring(offset, end))
    }
  }
  return cookieValue;
}
</script>
<body>
<script>
writeCookie("name","xiangdong2",24);
alert( readCookie("name") );
</script>
</body>
function forIn(o){
  var a = [];
  for(var k in o){
    a.push(k + "=" + o[k]);
  }
  return a.join("\n");
}

alert(forIn(document.del.elements));
alert(document.del.action);
http://photo.163.com/photos/82865538/
http://www.thss.tsinghua.edu.cn/faculty_xiangd_cn.asp


向东 教授

清华大学 教授 博士生导师
电子邮件: dxiang@tsinghua.edu.cn
办公电话: 86-10-62795434
  

主要经历:

于1987及1990年毕业于重庆大学获计算机科学学士学位及硕士学位。

1993年于中国科学院计算技术研究所获得计算机工程博士学位。

1994-1995为加拿大,Concordia大学电子工程系博士后,

1995-1996为美国Illinois大学,Urbana Champaign, 电子工程系(Coordinated Science Lab.)博士后。

1996.10 -2003.3为清华大学,微电子学研究所副教授。

2003.3-2004.12为清华大学软件学院副教授。

2003.4-2003.9为日本奈良先端科大JSPS研究员。

现为清华大学软件学院教授, 博士生导师。


研究领域:

  数字系统测试与设计:可测试性设计,可测试性分析,低成本测试,自测试,测试码产生;容错计算,并行/分布式计算,计算机网络通讯



主要奖励:

2003: JSPS fellowship;

2004: 国家杰出青年基金;

2004:IEEE Senior Member。


获得专利

1.向东,孙家广,降低非扫描可测试性设计管脚开销的方法,国家发明专利,专利号:ZL 02 1 46776.5, 2004.12。

2.D. Xiang, J. Sun, M. Chen, and S. Gu, Cost-Effective Scan Architecture and a Test Application Scheme, US Patent US 6,959,426 B2, Oct. 25, 2005.

3.向东,孙家广,李开伟, A New Test Point Architecture for High-Quality Testability Design, US Patent,US 7,051,302 B2 , May 23, 2006.

4.向东,孙家广,李开伟, 基于扫描森林的扫描测试方法, 国家发明专利,ZL02159931.9, (2006.8)。

另有三项国家发明专利获批。申请了10余国家发明专利,及三项美国国际发明专利。


目前开设课程

1.分布式系统 (着重介绍互连网络高性能,无死锁及容错通讯,教材,J. Duato, L. Ni, S. Yalamanchili, Interconnection Networks: An Engineering Approach, IEEE Press, 1997, 及2002版本, 每年秋季)。


主要在研项目:

1.采用新的扫描链构造技术提高BIST的测试效率,国家自然科学基金(负责人,2004.1-2006.12)。

2.数字系统可测试性设计理论研究, 国家杰出青年基金(负责人,2005.1- 2008.12)。

3.基于路由技术多计算机网络的容错组播及广播, 国家自然科学基金(负责人,2006.1-2008.12)。

4.大规模自组织无线网络低功耗,高可靠性路由技术, 国家863 探索导向类项目 (负责人, 2007.1-2009.12).


专业任职:

期刊杂志:
IEEE Senior Member, IEEE Trans. Computers, IEEE Trans. Computer-Aided Design, IEEE Trans. Parallel and Distributed Systems, J. of Parallel and Distributed Computing,IEEE Trans. VLSI Systems, IEEE Trans. Reliability, IEEE Int. Test Conference, ACM/IEEE Design Automation Conference, Int. Conf. on Parallel Processing, IEE Proc. Part E, Inform. Sci.等杂志及会议评审人;《中国科学》等审稿人.

会议:
[1] 12th , 14th , 16th, 17th IEEE Asian Test Symposium(2008) 程序委员会委员;
[2] 11th , 12th , 13th, 14th IEEE Pacific Rim Dependable Computing Conf.(2008), 程序委员会委员;
[3] 28th IEEE Int. Conference on Distributed Computing Systems,2008, 程序委员会委员;
[4] 19th IEEE Int. Conference on Computer Communications and Networks, 2008, 程序委员会委员;
[5] 8th Int. Conf. on Young Computer Scientists, 2008, 程序委员会委员;
[6] Int. Conf. on Algorithms and Architectures for Parallel Processing, 2008, 程序委员会委员; 
[7] 10th IEEE Int. Conf. on High-Performance Computing and Communication, 2008, 程序委员会委员。
[8] 19th IEEE Asian Test Symp.(2010), 15th IEEE Pacific Rim Dependable Computing Symposium(2009), 程序委员会主席。
[9] Int. Conf. on Reliability and Safety Engineering2005 and INCRESE2006, 及INCRESE2007 指导委员会委员;
[10] IEEE Int. Workshop on RTL and High- Level Testing指导委员会委员;
A keynote address at INCRESE2005(India)。

有代表性的论著:

非扫描可测试性设计:

[1] D. Xiang, Y. Xu, and H. Fujiwara, “Non-scan design for testability for synchronous sequential circuits based on conflict resolution,” IEEE Trans. on Computers, vol. 52, no. 8, pp. 1063-1075, 2003.


[2] D. Xiang and H. Fujiwara, “Handling the pin overhead problem for high quality and at-speed test,” IEEE Trans. on Computer-Aided Design of Integrated Circuits and Systems, vol. 21, no. 9, pp. 1105-1113, 2002.


[3] D. Xiang and Y. Xu, “Cost-effective non-scan design for testability for synchronous sequential circuits,” Proc. of 19th? IEEE Int. Conference on Computer Design, pp.154-159 , Austin, USA, Sept, 2001.


[4] D. Xiang and Y. Xu, “Partial reset for synchronous sequential circuits using almost independent reset signals,” Proc. of 19th? IEEE VLSI Test Symposium, pp.82-87, Los Angels, April, 2001.


[5] D. Xiang, S. Gu, and H. Fujiwara, “Non-scan design for testability based on fault-oriented conflict analysis,”? Proc. of? 11th? IEEE Asian Test Symposium, Guam, USA, Nov., 2002.


[6] D. Xiang, S. Gu, and H. Fujiwara, “Non-scan design for testability for? mixed RTL circuits with both data paths and controller via conflict analysis,” Proc. of 12th IEEE Asian Test Symposium, pp. 300-303, 2003.


[7] D. Xiang, S. Gu, and H. Fujiwara, “Non-scan design for testability for synchronous sequential circuits based on fault-oriented conflict analysis,” IEICE Trans. on Information and Systems, vol.E86-D, pp. 2407-2417, Nov., 2003.

低成本扫描测试:

[8] D. Xiang, S. Gu, J. Sun, and D. Wu, “Cost-effective scan design with non-scan test application cost and test power,” in Proc. of ACM/IEEE Design Automation Conference, pp. 744-747, June, Anaheim, 2003.


[9] D. Xiang, K. Li, and H. Fujiwara, “Design for scan testing with low test application cost and low test data volume by reconstructing scan flip-flops,”? in Proc. of 14th IEEE Asian Test Symposium, pp. 318-321, Dec., 2005.


[10] D. Xiang, K. Li, and H. Fujiwara, “Localizing test power consumption for scan testing,” in Proc. of 6th IEEE Int. Workshop on RTL and High Level Testing, pp. 18-23, 2005.


[11] D. Xiang and K. Li, “Low Power Scan testing using a two-stage scan architecture,”? Chinese Journal of Computers, pp. 786-791, no. 5, 2006 (in Chinese).


[12] K. Li and D. Xiang, “Scan testing with low power, test application time and reduced test data volume,” Journal of Tsinghua University, pp. 98-101, no. 1, 2006(in Chinese).


[13] D. Xiang, K. Li, J. Sun, and H. Fujiwara, “Reconfigured scan forest for test application cost, test data volume and test power reduction,” IEEE Trans. on Computers, vol. 56, no. 4, pp. 557-562, April 2007.


[14] D. Xiang, K. Li, H. Fujiwara, K. Thulasiraman, and J. Sun, “Constraining transition propagation for low power scan testing using a two-stage scan architecture,” ?IEEE Trans. Circuits and Systems-II, vol. 54, no. 5, pp. 450-454, May 2007.


[15] Q. Xu, D. Hu, and D. Xiang, “Pattern-directed circuit partitioning for test power reduction,” accepted to appear in Proc. of IEEE Int. Test Conference, Santa Clara, Oct. 2007.

部分扫描设计

[16] D. Xiang and J.H.Patel, “Partial scan design based on valid state information and functional information,” IEEE Trans. on Computers, vol.53, no.3, pp.276-287, 2004.


[17] D. Xiang and Y. Xu, “A multiple phase partial scan design method,” Proc. of 10th??IEEE Asian Test Symposium, Kyoto, pp.17-22, Nov., 2001.


[18]D. Xiang and J. Patel, “A global algorithm for the partial scan design problem using circuit state information,” in ?Proc. of IEEE Int. Test Conference, pp. 548-557, Nov., 1996.

自测试

[19] D. Xiang, M. J. Chen, J. G. Sun, and H. Fujiwara, “Improving the effectiveness of scan-based BIST using scan chain partitioning,” IEEE Trans. on Computer-Aided Design, vol. 24, no. 6, pp.916-927, 2005.


[20] D. Xiang, M. J. Chen, J. Sun, and H. Fujiwara, “Improving test quality of scan-based BIST by scan chain partitioning,” Proc. of 12th IEEE Asian Test Symposium, pp.12-17, 2003.


[21] D. Xiang, M. Chen, K. Li, and D. Wu, “Scan-based BIST using an improved scan forest architecture,” ?in Proc. of ?13th IEEE Asian Test Symposium, pp. 88-93, Nov., 2004.


[22] D. Xiang, D. Z. Wei, and S. S. Chen, “A global test point placement algorithm for combinational circuits,” Proc. of 5th? IEEE Int. Conf. on VLSI Design, pp. 227-232, 1992.


[23] D. Xiang and D. Z. Wei, “Global: A design for random testability algorithm,” J. of Computer Science and Technology, vol. 9, no. 2, pp. 182-192, 1994.


[24] D. Xiang, D. Z. Wei, and S. S. Chen, “Probabilistic models for estimation of random and pseudorandom test length,” J. of Computer Science and Technology, vol. 7, no.2, pp. 164-174, 1992.


[25] D.Xiang,“Knowledge-based design for testability,”ActaElectronica Sinica, vol. 19, no. 3,pp. 106-109, 1991(in Chinese).


[26] D. Xiang, M. Chen, and H. Fujiwara, “Using weighted scan enable signals to improve test effectiveness of scan-based BIST,”? in? Proc. 14th IEEE Asian Test Symposium, pp. 126-131, Dec., 2005.


[27] D. Xiang, Y. Zhao, K. Chakrabarty, J. Sun, and H. Fujiwara, “Compressing test data for deterministic BIST using a reconfigurable scan architecture,” in ?Proc. of 15th IEEE Asian Test Symposium, Japan, pp.299-304, Nov., 2006.


[28] D. Xiang, M. Chen, and J. Sun, “Using weighted scan enable signals to improve the test effectiveness of scan-based BIST,” Science in China, vol. 36, no. 8, pp. 902-911, 2006 (in Chinese).


[29] D. Xiang, M. Chen, and J. Sun, “Improving test effectiveness of scan-based BIST by using weighted scan enable signals,” accepted to appear in Science in China (English version), 2006.


[30] D. Xiang, M. J. Chen, and H. Fujiwara,“Using weighted scan enable signals to improve test effectiveness of scan-based BIST,”accepted to appear in IEEE Trans. On Computers, 2007.


[31] D. Xiang, Y. Zhao, K. Chakrabarty, and H. Fujiwara, “A reconfigurable scan architecture with weighted scan enable signals for deterministic BIST,” accepted to appear in IEEE Trans. on Coputer-Aided Design, 2008.



可测试性分析

[32] D. Xiang, Y. Xu, and H. Fujiwara, “Non-scan design for testability for synchronous sequential circuits based on conflict analysis,” Proc. of IEEE Int. Test Conference, Atlantic City, pp. 420-429, Oct., 2000.


[33] D. Xiang, S. Venkataraman, K. Fuchs, and J. Patel, “Partial scan design based on circuit state information,” Proc. 33th?? of ACM/IEEE Design Automation Conference, pp. 807-8l2, Las Vegas, l996.


[34] D. Xiang, “SCTM: A conflict oriented testability measure,” Chinese Journal of Computers, vol. 16,? no. 4,? pp. 273-280, 1993 (in Chinese).


[35] D. Xiang and D. Z. Wei,? “On functional circuit testability analysis,”? Chinese Journal of Computers,? vol. 16, no. 1, pp. 35-44, 1993 (in Chinese).

延迟测试
[36] D. Xiang, K. Li, H. Fujiwara, and J. Sun, “Generating compact robust and non-robust tests for complete coverage of path delay faults based on stuck-at tests,” in Proc. of 24th IEEE Int. Conference on Computer Design, pp. 446-451, 2006.


[37] D. Xiang, Y. Zhao, K. Li, and H. Fujiwara, “Fast and effective fault simulation for path delay faults based on selected testable paths,” accepted to appear in Proc. of IEEE Int. Test Conference, Santa Clara, Oct. 2007.


[38] D. Xiang, K. Chakrabarty, D. Hu, and H. Fujiwara, “Scan testing for complete coverage of path delay faults with reduced test data volume, test application time and hardware,” accepted to appear in Proc. of 16th IEEE Asian Test Symposium, Oct. 2007.

容错计算

[39] D. Xiang, “Fault-tolerant routing in hypercube multicomputers using local safety information,” IEEE Trans. on Parallel and Distributed Systems, vol. 12, no. 9, pp. 942-951, 2001.


[40] D. Xiang and A. Chen, “Reliable broadcasting in wormhole-routed? hypercube -connected networks using local safety information,”IEEE Trans. on Reliability, pp. 245-256, vol. 52, no. 2, June, 2003.


[41] D. Xiang, A. Chen, and J. Wu, “Fault-tolerant broadcasting for hypercubes? based on local safety information,” Proc. of 9th? IEEE Int. Conf. on Parallel and Distributed Systems,? pp. 31-36, Taiwan, Dec.,? 2002.


[42] D. Xiang and J. Wu, “Reliable multicasting for hypercube multicomputers using local safety information,” Proc. of? 13th? Int. Conf. on Parallel and Distributed Computing Systems, Las Vegas, Aug., pp. 529-534, 2000.


[43] D.Xiang, A.Chen, and J. Wu, “Local-safety-information-based broadcasting in hypercube multicomputers with node and link faults,” Int. Journal of Interconnection Networks, vol. 2,no. 3, World Scientific Publishers, pp. 365-378, 2001(invited? paper).


[44] D. Xiang and J. Wu, “Reliable unicasting in faulty hypercubes using local safety information,” Proc. of 4th? IEEE Int. Conf. on? Algorithms and Architectures for Parallel Processing,? Hong Kong,? Dec., 2000.


[45] D. Xiang, “Partial path set-up for fault-tolerant? routing in hypercube multicomputers,” Future Generation Computer Systems, vol. 22, pp. 812-819, Elsevier Scientific Press, Aug., 2006.


[46] D. Xiang, A. Chen, and J. Wu,“Local-safety-information-based ?fault-tolerant broadcasting in hypercubes,” J. of Inform. Sci. and Eng., vol. 19, no. 3, pp.467-478, June, 2003.


[47] D. Xiang and A. Chen, “Fault-tolerant routing in hypercubes based on partial path set-up, ” in Proc.of 2003 IEEE Int. Workshop on PMEO-PDS03 (with IPDPS03), IEEE Computer Society Press.


[48] D. Xiang,? A. Chen, and J. Sun,? “Fault-tolerant routing in 3D meshes/tori based on locally formed fault blocks,”? Chinese Journal of Computers,? vol. 27,? no. 5,? pp. 611-618, 2004 (in Chinese).


[49] D. Xiang, A. Chen, and J. G. Sun, “Fault-tolerant multicasting in hypercube multicomputers using local safety information,” Journal of Parallel and Distributed Computing, vol. 66, no. 2, ?pp. 248-256, 2006.

并行/分布式计算
[50] D. Xiang, Y. Zhang, Y. Pan, and J. Wu, “Deadlock-free adaptive routing in meshes based on cost-effective deadlock avoidance schemes,”accepted to appear in 36th IEEE Int. Conference on Parallel Processing, Sept. 2007.


[51] D. Xiang, A. Chen, and J. Sun, “Fault-tolerant routing and multicasting for hypercube multicomputers based on partial path set-up,”? Parallel Computing, Elsevier Science Press, vol.31, no. 1,? pp. 389-411, 2005.


[52] D. Xiang, J. Sun, J. Wu, and K. Thulasiraman, “Fault-tolerant routing in meshes /tori using planarly constructed fault blocks,”? in Proc. of 34th IEEE Int Conference on Parallel Processing, pp. 577-584, Oslo, Norway, 2005.

[53] D. Xiang and A. Chen, “Fault-tolerant routing in 2D meshes/tori using limited -global-safety information,” Proc. of 31th? IEEE Int. Conf. on Parallel Processing, pp. 231-238,? Vancouver, Aug.,? 2002.



[54] 向东,张跃鲤,mesh网高效无死锁路由算法,《计算机学报》,vol. 30, no. 11, pp. 1954-1963, 2007.


[55] Z. Li , Y. Zhao, Y. Cui, and D. Xiang, “A density adaptive routing protocol for large-scale Ad hoc networks,” accepted to appear in Proc. of IEEE Wireless Communications and Networking Conference, 2008.


[56] D. Xiang, Y. Pan, Q. Wang, and Z. Chen, “Deadlock-free fully adaptive routing in 2-dimensional tori based on a new virtual network partitioning scheme,” accepted to appear in Proc. of 28th IEEE Int. Conference on Distributed Computing Systems, 2008.

http://happycun.com/aboutplayer/player/js/../../../jie/bgsound/bgsound.wma
http://happycun.com/aboutplayer/player/js/../../../mymusic/whatyourname.mp3
http://happycun.com/aboutplayer/player/js/../../../mymusic/feilongzaitian.wma
星期天,闲着没事,又把最爱的碟片《教父》翻出来品尝,还是一样有味道。不愧被誉为史上最经典的影片,经典得益于演员的精湛演出,把一部关于美国黑帮社会,关于男人的奋斗史演绎得淋漓尽致,丝丝入扣,入木三分。这部影片包含了男人的全部智慧,是男人生命的经典,是值得用一生来领会的电影。经典的电影当然就会有经典的对白,让我们静下心来重温里面那经典的对白吧。

1.巨大财富的背后,都隐藏着罪恶--------教父开篇,引用  

2.让朋友低估你的优点,让敌人高估你的缺点。

3.不要憎恨你的敌人,那会影响你的判断力 ( 永远不要恨你的敌人 ,因为这会影响你的判断力。)

4.离你的朋友近些,但离你的敌人要更近,这样你才能更了解他

5.迈克对文森特说:永远别让别人知道心中所想! (敌人会向你最喜欢的人下手)

6.这个世界本身就没有所谓的清白而言,你能坦言,你从来就没说过慌,这是自欺欺人.

7.我为自己的家族工作,拒绝成为大人物手下的傀儡
这个却让我反思了bog,但是我认为一定的交流是必须的,研究需要的是交流

8.最经典的:我将给他一个他无法拒绝的理由/条件 (要么答应,要么被杀)

9.一个人只有一个命运。

严重同意,我相信有时命运当你遇上了什么样的命运,你就必须有个使命来完成.

10.你花时间和你的家人在一起吗? 我当然有. 很好!不照顾家人的男人,根本算不上是个男人!

11.伟大的人不是生下来就伟大的,而是在成长过程中显示其伟大的
什么样,是否能给你很多的启发,有人天生就是领导,但是更多的是时间,时间会造就一切.

12.一个提着公文包的律师所抢到的钱比一千个拿着冲锋枪的抢到抢到的钱还要多

13.如果一个人很慷慨,那他就必须把自己的慷慨表现得充满感情”——马里傲普佐原文

14. 友谊可以筑起一道坚实的防线
没有人会怀疑他的

15.不要让别人知道你的想法!!

16. 如果你认为我不知道其中的真相 那就是在侮辱我的智慧
千万别小看你身边的人,沉默并不代表我没有意见,只是有时觉得不说更好些

17.不要把私人的感情带到商界,这不利于发展,即使有解决不了的,靠你的能力,你的智慧来解决.

18.我花了一辈子 ,就学会了小心 ,女人和小孩能够粗心大意 ,但男人不行
我更倾向与把他理解为一种做男人的使命,男人不应该你让你身边所爱的人伤心,只有更加小心.

19.“我绝不会把友谊强加给不需要友谊——认为我无足轻重的人”
对,友谊是真诚的,没有互信,什么都不要说.

20.在一秒钟内看到本质的人和花半辈子也看不清一件事本质的人,自然是不一样的命运.

21.生命是如此的美丽……(教父临终语)
我一直这样认为,我希望到我临终我还可以说这样一句话:生命是如此的美丽

不顾家庭的男人不是真正的男人

如果生活告诉了我们什么,历史教育了我们什么,那就是你可以杀了任何人

22.我是个迷信的人,若是他不幸发生意外,或被警察开枪打死,或在牢里上吊,或是他被闪电击中,那我会怪罪这个房间里的每一个人,到那时候我就不会再客气了

23. 这张和约书上会留下两样东西:一是你的名字,再就是你的脑浆……
24. 不要憎恨你的敌人,那会影响你的判断力
25. 这是生意上的事,没有私人恩怨.
26. 一个人只有一个命运。“如果一个人很慷慨,那他就必须把自己的慷慨表现得充满感情”
27.你花时间和你的家人在一起吗? 我当然有. 很好!不照顾家人的男人,根本算不上是个男人!
28. 复仇是一道冷却后的美餐。
29. 只有女人和小孩可以粗心,男人却不能。
30. 我会给他一个无法拒绝的条件
31. 你不该拒绝我的友谊
32. 我只可能被杀害,但永远不可能被捕——迈克
33.如果你不和家人在一起,你就永远无法成为真正的男人.
34.如果我收下你的信,那在法律上就意味着我清楚迈克的下落
35.“Politics and crime is the same thing!” 政治和犯罪是一回事!
36.你们说出了我想说的
37.最猛烈的拥抱是用来抱断敌人的肋骨的
38.我用一辈子的学会了小心
39. 不要说不可能,没有什么不可能
40.遇到事情,从别人的角度考虑一下吧(没有什么不可能)
41.当制片厂老板拒绝了教父的请求,他的手下在离开时说:科里昂尼是个坚持要听到坏消息的人
42.你是我的兄长我爱你但我绝对不允许你做对不起家族的事 帮外人
43. 这种权利我没有,要是我有,我一定比上帝慈仁。
44. 我相信友谊,并且愿意首先表示出我的友谊.
45. 如果你这么老实的人都受别人欺负的话,你的敌人就是我的.到时侯他们会怕你.
46.麦克:你还没有教会我怎样说不。
    教父:首先,你不能对你所热爱的人说不。
47.政治与犯罪本是一回事情----金融就是枪政治就是抠动扳机的时候
48.无法掌控权利的人将被权利毁灭!!!
49. 世界上有什么事情能那么肯定??只有一个---复仇!
50.现在,只留下我们之间可贵的友谊.
51们开出的条件你是无法拒绝的,要么是你的签字,要么是把你的手指留下。
if (document.xiaozu.xiaozu.value.indexOf(" ")>=0)
{
  alert("小组名前后不能有空格字符.");
  return false;
}
点击在新窗口中浏览此图片
背景:指针传入函数和变量传入函数也一样,变量有变量本身,及变量的地址,而指针也一样,有指针本身,和指针的地址,下面根据代码来实践一下这个问题。
C语言指针传递详解:http://www.cnblogs.com/archimedes/p/c-transfer-point.html
从函数返回对象经常使用以下两种技术:
使用malloc在函数内部分配内存并返回其地址,调用者负责释放返回的内存
传递一个对象给函数,让函数修改它,这样分配和释放对象的内存都是调用者的责任

先讲难度大一点的,指针的地址传入函数里,传递指针的指针-将指针传递给函数的时候,传递的是值,如果希望修改原指针而不是指针的副本,就需要传递指情况一,针的指针,如下,allocateArray.c :

gcc -g -o allocateArray allocateArray.c

[root@test pointerparam]# ./allocateArray
45
45
45
45
45
用gdb看一下其指针地址,为何这样就能实现在函数里malloc后,在外面依然能够获取到malloc里的值呢?是因为传入的指针的地址,相当于这个malloc的内存根本没有退出函数后销毁,而且传入的地址是指针的地址,不是指针,这两点保证了其地址是同一个地址,不是副本,所以,函数退出后还在,需要外面作free(;vector),vector=NULL:
(gdb) b 4
Breakpoint 1 at 0x40053a: file allocateArray.c, line 4.
(gdb) b 18
Breakpoint 2 at 0x4005ad: file allocateArray.c, line 18.
(gdb) r
Breakpoint 2, main () at allocateArray.c:18
18          allocateArray(&vector,5,45);
(gdb) p &vector
$1 = (int **) 0x7fff3cb989f0         //函数外的地址: 0x7fff3cb989f0
(gdb) c
Continuing.

Breakpoint 1, allocateArray (arr=0x7fff3cb989f0, size=5, value=45) at allocateArray.c:5
5           *arr = (int*)malloc(size*sizeof(int));
(gdb) p arr
$2 = (int **) 0x7fff3cb989f0    //这个地址在函数里也一直是传入的地址: 0x7fff3cb989f0
(gdb) n
6           if(*arr != NULL){
(gdb) p arr
$4 = (int **) 0x7fff3cb989f0
(gdb) n
7               if(*arr != NULL){
(gdb) n
8                   for(i=0;i<size;i++){
(gdb) n
9                       *(*arr+i) = value;
(gdb) n
main () at allocateArray.c:19
............next............
19          for(i = 0; i < 5; i++) {
(gdb) n
20              printf("%d\n", vector[i]);
(gdb) p &vector
$6 = (int **) 0x7fff3cb989f0     //发现没到函数里转一圈后,这个地址一直是: 0x7fff3cb989f0
(gdb) n
45
19          for(i = 0; i < 5; i++) {//打印出函数里赋的值是没有问题的..正常运行结束。


情况二:下面这个版本的allocateArray函数传递了一个数组指针、数组的长度和用来初始化数组元素的值,返回指针只是为了方便

[root@test pointerparam]# gcc  allocateArray3.c
[root@test pointerparam]# ./a.out
45
45
45
45
45
这个值是变了,但指针是没有变的,也就是说指针做了它该做的工作,并没有像第一种那样:  allocateArray(&vector,5,45);实现对指针本身地址通过函数进行了修改,这儿只是对指针里的值做了修改,是不一样的。
用gdb来跟踪一下这个指针的传指针值的操作:
[root@test pointerparam]# gdb allocateArray3
(gdb) b 15
Breakpoint 1 at 0x400571: file allocateArray3.c, line 15.
(gdb) b 5
Breakpoint 2 at 0x400536: file allocateArray3.c, line 5.
(gdb) r
Starting program: /tmp/pointerparam/allocateArray3
Breakpoint 1, main () at allocateArray3.c:15
15          int* vector = (int*)malloc(5 * sizeof(int));
(gdb) p vector
$1 = (int *) 0x0   //此时是光一个指针还没有分配指针指和的malloc真实数据地址
(gdb) n
16          allocateArray(vector, 5, 45);
(gdb) p vector
$2 = (int *) 0xb447010 //分配地址:0xb447010 这个值会带入进去,并在里面对其作赋值操作,出函数后这个值还在,因为在传入前就已经分配好空间,在函数里只是赋值,把东西放进这个空间,函数返回后空间并没有销毁,因为是在函数外。
(gdb) c
Continuing.
Breakpoint 2, allocateArray (arr=0xb447010, size=5, value=45) at allocateArray3.c:6
6           if(arr != NULL) {
(gdb) c
Continuing.
45
45
45
45
45


情况三,指针值传入函数里面,这样会出现一个segment default的,情况三作一下修改:
allocateArray2.c

gcc -g -o allocateArray2 allocateArray2.c
[root@test pointerparam]# ./allocateArray2
Segmentation fault


如这样写呢?     *arr = (int*)malloc(size*sizeof(int));

如果想这样,编译都会报错,如下:
porinter.c:6:10: 警告:赋值时将指针赋给整数,未作类型转换 [默认启用]

因为文件名传入的是一个指针,而*arr是一个值,不再是一个指针了。
而传入的是指针的指针就不一样了,如前面的例子1:void allocateArray(int ** arr,int size,int value){
那么因为函数int ** arr是指针的指针,也就是这个指针是可以修改的,这个*arr它不是一个值了,而是一个指针,所以,它可以给它malloc一个空间,并把这个空间给到*arr这个脂针地址里去,这块一定要区分开来,否则指向指针这一块的概念就没彻底理解清楚。
再理解前面引用的Url里的这一段话,加强深入理解传入指向指针的指针是可以修改指针的地址,指针也理一个数据,和int char是一样的东西,它也是能被修改的,而一维指针可以修改int char,int这样的值,但指针地址不变,而指针的指针它的地址都能被修改,这就是指针的精华人所在,摘录如下:
传递指针可以让多个函数访问指针所引用的对象,而不用把对象声明为全局可访问,要在某个函数中修改数据,需要用指针传递数据,当数据是需要修改的指针的时候,就要传递指针的指针,传递参数(包括指针)的时候,传递的是它们的值,也就是说,传递给函数的是参数值的一个副本,也就是说这儿数据是需要修改的指针的时候,就要传递指针的指针,而咱们只传了指针,修改后退出函数这个指针并没有变,销毁函数后,没有对指针作出修改,等于空做了一次运算,像做梦一样,函数并没改变什么,所以出现错误。

为何会出现segment default的情况?是因为指针传入函数后进行了malloc,而这个指针是在函数里经过malloc时给修改了指向地址,而这个malloc的空间因为函数退出而回收了指针传值地址,也就是其并没有记得下来,其malloc出来的存放整数的空间还在,但退出函数时就丢了,为此,在外面打印一个不存在的地址,当然会出现了segment default的情况,gdb分析如下:
(gdb) b 18
Breakpoint 1 at 0x40059a: file allocateArray2.c, line 18.
(gdb) b 19
Breakpoint 2 at 0x4005ad: file allocateArray2.c, line 19.
(gdb) b 4
Breakpoint 3 at 0x40053a: file allocateArray2.c, line 4.
(gdb) r
Starting program: /tmp/pointerparam/allocateArray2

Breakpoint 1, main () at allocateArray2.c:18
18          allocateArray(vector,5,45);
(gdb) n

Breakpoint 3, allocateArray (arr=0x0, size=5, value=45) at allocateArray2.c:5 //arr传入是0x0,也就是副本vector的地址。
5           arr = (int*)malloc(size*sizeof(int));
(gdb) n
6           if(arr != NULL){
(gdb) p arr
$1 = (int *) 0x14c3c010 //经malloc后是0x14c3c010
(gdb) c
Continuing.

Breakpoint 2, main () at allocateArray2.c:19
19          for(i = 0; i < 5; i++) {
(gdb) p vector //返回main函数后,这个vector还是0x0,并没有经过函数而改变,当然,下面对其进行打印会Segmentation fault.
$2 = (int *) 0x0
(gdb) n
20              printf("%d\n", vector[i]);
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x00000000004005c3 in main () at allocateArray2.c:20
20              printf("%d\n", vector[i]);

回顾总结:
allocateArray.c                    allocateArray2.c                  
#include <stdio.h>                   #include <stdio.h>                                          
#include <stdlib.h>                   #include <stdlib.h>                                          
void allocateArray(int *arr,int size,int value){           void allocateArray(int ** arr,int size,int value){      
    int i;                           int i;                                                            
    arr = (int*)malloc(size*sizeof(int));                 *arr = (int*)malloc(size*sizeof(int));                
    if(arr != NULL){                       if(*arr != NULL){                                          
        if(arr != NULL){                     if(*arr != NULL){                                      
            for(i=0;i<size;i++){                       for(i=0;i<size;i++){                              
                arr[i] = value;                     *(*arr+i) = value;                              
            }                             }                                                          
        }                         }                                                              
    }                             }                                                                  
}                         }                                                                      
                                                                                                      
int main(){                       int main(){                                                        
    int i;                           int i;                                                            
    int *vector = NULL;                       int *vector = NULL;                                      
    allocateArray(vector,5,45);                   allocateArray(&vector,5,45);                          
    for(i = 0; i < 5; i++) {                     for(i = 0; i < 5; i++) {                                    
        printf("%d\n", vector[i]);                 printf("%d\n", vector[i]);                            
    }                             }                                                                  
    free(vector);                         free(vector);                                                  
}                         }                                                                      
结论是malloc在函数里都得销毁掉,详细如下所述:
C语言是传值调用的,左边的你传递进去vector的地址,右边的是你传递了vector这个指针的地址值,所以左边的allocateArray函数内对arr的修改不会对函数外vector的值有什么影响,但是右边就不一样了,对arr的修改就是对vector变量所在的空间中的值的修改,也就是修改了vector的值,所以左边的allocateArray函数内对arr的修改不会对函数外vector的值有什么影响,那这个左边的malloc有没有运行完后还在呢? 右边这个如果不free会有内存泄漏的呀。
两边的都要销毁,只是左边的你在函数外没办法销毁。
【活跃】回忆未来-向东-Jàck 15/3/18 星期三 11:13:40
哈哈,了解了,多谢兄弟啊,相当感谢,我都说这malloc这玩意用时要注意才是。搞不好就泄漏了呢。
11:13:53
【潜水】Now&Fight 15/3/18 星期三 11:13:53
嗯嗯

阅读全文
生命中,不断地有人离开或进入。

遇见了许多人,然后遗忘了一部分。

于是,看见的,看不见了;

仿若春天过去纷纷扬扬飘落的樱花,被泥土隐埋覆盖。

因为记住的,遗忘了。

就像那年夏天的那个微笑,曾一度忘记过。

生命中,不断地有得到和失落。

于是,看不见的,看见了;

幻梦泡影突然变得如此真实可触碰。

樱花虽然被封埋,最精华的养分却渗进了泥土。

遗忘的,记住了。

因为渗进了心的最深处,所以无法忘记,反而深深刻进心里。

然而,看不见的,是不是就等于不存在?

欺骗自己肉眼看不到的则心里藏不住,瞒不了的那是自己的心。

记住的,是不是永远不会消失?

以为永远存在无法抹去的,或许会不知不觉灰飞烟灭。

有时候以为可以拥有某些东西一辈子,却可能在瞬间瓦解。

有时候以为已经彻底放下不会再忆起,却发现并不是易事。

生命的变化虽然太大太快,但每一模糊的开始,

都有可能充满着无限的美丽期待……



人不是鱼,怎会了解鱼的忧愁。

鱼不是鸟,怎会了解鸟的快乐。

鸟不是人,怎会了解人的荒唐。

人不是鸟,怎会了解鸟的自由。

鸟不是鱼,怎会了解鱼的深沉。

鱼不是人,怎会了解人的幼稚。

你不是我,怎会了解我。



向日葵告诉我,

只要面对着阳光努力生长,

日子就会变得单纯而美好……



所有的悲伤,总会留下一丝欢乐的线索。

所有的遗憾,总会留下一处完美的角落。

我在冰封的深海,找寻希望的缺口。

却在午夜惊醒时,蓦然瞥见绝美的月光。



掉落深井,我大声呼喊,等待救援……

天黑了,黯然低头,才发现水面满是闪烁的星光。

我总是在最深的绝望里,遇见最美丽的惊喜。



有时,一分钟很长,

有时,却又很短。

有时我可以了解这世界,

有时却一点也不懂。

爱你时,一切美好,

怨你时,人生灰暗。

为何欢乐过后,

只剩下一片悲凉?



我不了解我的寂寞来自何方,但我真的感到寂寞。

你也寂寞,世界上每个人都寂寞,只是大家的寂寞都不同吧。



窗外放晴了。屋内仍继续下雨。

我微笑。并不等于我快乐。

我撑伞,并非只是为了避雨。

你永远都不懂我在想什么。

我想拥抱每个人,但我得先温暖我自己,请容忍我。

因为我已在练习容忍你。

我的心常下雪,不管天气如何。

它总是突然的冻结,无法商量。

我望向繁花盛开的世界,固定缺席。

我的心开始下雪,雪无声的覆盖了所有。

湮灭了迷茫,骄傲和哀痛。

当一切归于寂静,世界突然变的清凉明朗。

所以,别为我忧伤,我有我的美丽。

它正要开始。



如果想飞得高就该把地平线忘掉



我们习惯在远远的地方望着你

就像仰望天上的星星一般

从不敢奢望能真正接近你

你说要我们永远记得你

你也会永远记得我们

你说谎,但我们原谅你

现在你真的变成天上的一颗星星了吗

一定要快乐的发出闪闪光亮喔!



我站在大树上

学习像鸟一样飞翔

当然知道有些事情不可能成真,

但,我还是想试试!

风来了,我努力挥动着双手,

临风飞舞......

感到无比的幸福



很多努力也许真的不会有结果。

可是努力过,那不是最美的过程吗?

我不为我有多美的梦想而幸福,而为我曾努力付出过而感觉幸福。
拖动到快速启动:
鼠标右键(注意是右不是左)点桌面图标后不放,拖动到下面(在这之前就要留好任务栏左边的空隙)操作如下:在下面的左侧有一个快说启动的(有时因为锁定了任务栏会变得得窄看不到),得在任务栏里取消锁定任务栏,再拉长一点儿,这样就能看到桌面图标了。

有人把“显示桌面”按钮删除了,不知道怎么恢复,可以采用如下方法:

打开“记事本”,在里面输入下面内容:

[Shell]

Command=2

IconFile=explorer.exe,3

[Taskbar]

Command=ToggleDesktop

把这个文件保存为:“显示桌面.scf”.随便放到一个地方(比如桌面).

然后把它拖到"快速启动"栏里即可。

在运行里面输入“regsvr32 /n /i:u shell32”回车,在弹出框点击“确定”。

当系统提示“shell32中的dllinstall成功”时,再次点击“确定”。




不知道什么时候,在快速查看有关“启动”的文章">启动栏的显示桌面的快捷方式不见了。

没有了他很不方便。

先新建一个txt文件,用记事本打开,填入如下内容

[Shell]
Command=2
IconFile=explorer.exe,3
[Taskbar]
Command=ToggleDesktop

保存为“显示桌面.scf”,然后把他拖到快速启动栏,就能用了。

但这仅仅是能用,显示桌面.scf的存放位置放哪,万一哪天被删除了,不就又没了。

我们要找到快速启动栏的文件目录位置

Documents and Settings\用户名\Application Data\Microsoft\Internet Explorer\Quick Launch

存放在这里就安全了。

分页: 285/338 第一页 上页 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 下页 最后页 [ 显示模式: 摘要 | 列表 ]