c语言笔记

C语言小笔记

1. excelp 函数

execlp(PATH环境变量中查找文件並执行相关函数fork,execl,execle,execv,execve,execvp

文件 #include<unistd.h>
函数的定义int execlp(const char * file,const char * arg,……);
execlp()PATH环境变量中所指的目录中查找符合参数file的文件名,找到便执行文件,然后将第二参数当作文件的argv[0]、argv[1]……,最后一个参数必须用空指针(NULL)结束
返回值:如果执行行成功则函数不返回否则返回-1,失败原因记录在errno 中。
范例:
#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]...

List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort.
 
自已在终端上永远试不出这个结果,因为明明调用的是ls命令,不可能显示出Usage: flw来。再仔细看看上面关于这个函数的描述“然將第二个以后参数当作文件的argv[0]、argv[1]……”我猛然想到了以前说过main函数是可以传入参数的,我于是尝试了这样的代码:
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 4286
i 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

str1str2是两个字符串数组。我们会为它们分配两个长度为12个字节的空间,并把"hello world"的内容分别拷贝到数组中去。这是两个初始地址不同的数组,因此比较str1str2的值,会不相同str3str4是两个指针,我们无需为它们分配内存以存储字符串的内容,而只需要把它们指向"hello world“在内存中的地址就可以了。由于"hello world”是常量字符串,它在内存中只有一个拷贝,因此str3str4指向的是同一个地址。因此比较str3str4的值,会是相同的

8 gdb查看数组元素的值

print *arry@len


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值