C语言小笔记
1. excelp 函数
execlp(从PATH环境变量中查找文件並执行)相关函数fork,execl,execle,execv,execve,execvp
范例:
#include<unistd.h>
int main(void)
{
execlp("ls","ls","-al","/etc/passwd",(char *)0);
return 0;
}
结果:
lestat@lestat-HP-Workstation:~/workPlace/apue$ ./exec
-rw-r--r-- 1 root root 1710 10月 29 15:13 /etc/passwd
其实上面的描述很奇怪,如果能从PATH中找到第一个参数指定的文件,那何须第二个参数呢,没意义啊?然后Google了下,看到了www.lslnet.com/linux/f/docs1/i34/big5260214.htm中别人同样的质疑。这张帖子的楼主索性猜测:execlp函数在实际执行的時候根本沒有用到第二個參數。说真的,这个猜测过于草率了。楼下有一张回帖给出了一个反例:execlp("ls","flw","--help",(char *)0)这句语句在我电脑上的效果:
Usage: flw [OPTION]... [FILE]...
int main(int num_args,const char* args[] )
{
int i;
for(i=0;i<num_args;++i)
{
std::cout << args[i] << std::endl;
}
return0;
}
在终端而不是IDE里运行这个程序,运行的时候给他带点参数,结果自己打的命令出现的在args[0]的位置,后面的参数出现在了args[1],args[2],args[3]....的位置,可见C程序总会把你运行这个程序用的命令传入args[0]。这样这个问题就解开了。execlp第一个参数是让程序从PATH中找到指定程序运行,第二个参数将传入这个程序的args[0]。
而execlp("ls","flw","--help",(char *)0)出现Usage: flw,是因为ls命令在显示帮助的时候会动用args[0],这么设计很正常,因为如果用户打错了命令,总希望用最接近他命令的方式指导他怎么做才对,直接使用他的命令是最方便的。平时args[0]几乎总是等于ls,这是因为ls在PATH中,没必要指示他的位置,但如果使用/bin/ls这样的命令,就可以看出来了。
2.STDIN_FILENO 和stdin 的区别
数据类型不一致:
stdin类型为 FILE*
STDIN_FILENO类型为 int
使用stdin的函数主要有:fread、fwrite、fclose等,基本上都以f开头
使用STDIN_FILENO的函数有:read、write、close等
3. fork 函数(转载地址:http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=311067
#include <unistd.h>;
#include <sys/types.h>;
main ()
{
pid_t pid;
pid=fork();
if (pid < 0)
printf("error in fork!");
else if (pid == 0)
printf("i am the child process, my process id is %d\n",getpid());
else
printf("i am the parent process, my process id is %d\n",getpid());
}
结果是:(有可能先输出父进程)
i am the child process, my process id is 4286i am the parent process, my process id is 4285
原因:
主要的原因是,fork() 函数调用一次,返回两次。两次返回的区别是:子进程的返回值是0,父进程返回值为新子进程的进程ID。
4. chdir函数的小秘密
chdir 函数用来改变当前的工作目录,函数原型如下
#include<unistd.h>
int chdir(const char *pathname);// pathname 为新的当前工作目录。
需要注意的是:因为当前工作目录是进程的属性,所以它只影响调用chdir的进程本身,而不影响其他进程。我们用下面的例子来更直接的说明这个问题
代码如下:
#include<stdio.h>
#include<unistd.h>
int main(void)
{
if(chdir("../chapter1")< 0)
{
printf("chdir error\n");
return 0;
}
printf("chdir success!\n");
return 0;
}
执行后的结果如下:(在执行前,我们先获得当前的工作目录)
lestat@lestat-HP-Workstation:~/workPlace/apue/chapter4$ pwd
/home/lestat/workPlace/apue/chapter4
lestat@lestat-HP-Workstation:~/workPlace/apue/chapter4$ ./a.out
chdir success!
lestat@lestat-HP-Workstation:~/workPlace/apue/chapter4$ pwd
/home/lestat/workPlace/apue/chapter4
lestat@lestat-HP-Workstation:~/workPlace/apue/chapter4$
通过执行结果,我们可以看到,程序运行成功,但是当前的工作目录并没有改变,其原因是shell创建了一个子进程。由子进程具体执行程序。由此可见,为了改变shell进程自己的工作目录,shell应当直接调用chdir函数,为此cd命令的执行程序直接包含在shell程序中。
5 短路运算
bool Fun1(char* str)
{
printf("%s\n",str);
return false;
}
bool Fun2(char* str)
{
printf("%s\n",str);
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
bool res1,res2;
res1 = (Fun1("a")&& Fun2("b")) || (Fun1("c") || Fun2("d"));
res2 = (Fun1("a")&& Fun2("b")) &&(Fun1("c") || Fun2("d"));
return res1|| res2;
}
上述运算的结果是什么?
答案:打印出4行,分别是a、c、d、a。
在C/C++中,与、或运算是从左到右的顺序执行的。在计算rest1时,先计算Fun1(“a”)&& Func2(“b”)。首先Func1(“a”)打印出内容为a的一行。由于Fun1(“a”)返回的是false,无论Func2(“b”)的返回值是true还是false,Fun1(“a”)&& Func2(“b”)的结果都是false。由于func2(“b”)的结果无关重要,因此Func2(“b”)会略去而不做计算。接下来计算Fun1(“c”)|| Func2(“d”),分别打印出内容c和d的两行。在计算rest2时,首先Func1(“a”)打印出内容为a的一行。由于Func1(“a”)返回false,和前面一样的道理,Func2(“b”)会略去不做计算。由于Fun1(“a”)&& Func2(“b”)的结果是false,不管Fun1(“c”)&& Func2(“d”)的结果是什么,整个表达式得到的结果都是false,因此Fun1(“c”) || Func2(“d”)都将被忽略。
6. C语言局部和全局变量
/*
funcation: just for testing ,no sense
date:2012-11-05
*/
#include<stdio.h>
char * getString1()
{
char p[]="Hello Word\n";
return p;
}
char * getString2()
{
char *p="Hello World\n";
return p;
}
int main(void)
{
printf("getString1:%s\n",getString1());
printf("getString2:%s\n",getString2());
return 0;
}
/*Resutl:
lestat@lestat-HP-Workstation:~/workPlace$ ./a.out
getString1: �q�����Կ�\���Կ�u���q�������ԿɄ��q���(乱码)
getString2:Hello World
Reason:在getString1()函数中,p是一个局部变量的数组,函数运行结束后,p销毁
在getString2()函数中,p指向的是一个常量字符串,该常量字符串是全局的。
*/
7. 变量的存储问题1
下列代码的输出结果
int _tmain(int argc, _TCHAR* argv[])
{
char str1[] = "hello world";
char str2[] = "hello world";
char* str3 = "hello world";
char* str4 = "hello world";
if(str1 == str2)
printf("str1 and str2 are same./n");
else
printf("str1 and str2 are not same./n");
if(str3 == str4)
printf("str3 and str4 are same./n");
else
printf("str3 and str4 are not same./n");
return 0;
}
答案:输出两行。第一行是str1 and str2 are not same,第二行是str3 and str4 are same。
str1和str2是两个字符串数组。我们会为它们分配两个长度为12个字节的空间,并把"hello world"的内容分别拷贝到数组中去。这是两个初始地址不同的数组,因此比较str1和str2的值,会不相同。str3和str4是两个指针,我们无需为它们分配内存以存储字符串的内容,而只需要把它们指向"hello world“在内存中的地址就可以了。由于"hello world”是常量字符串,它在内存中只有一个拷贝,因此str3和str4指向的是同一个地址。因此比较str3和str4的值,会是相同的。
8 gdb查看数组元素的值
print *arry@len