# learn-c-the-hard-way **Repository Path**: demokn/learn-c-the-hard-way ## Basic Information - **Project Name**: learn-c-the-hard-way - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2015-09-02 - **Last Updated**: 2022-09-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ** static 变量 在 C 语言中,static 关键字不仅可以用来修饰变量,还可以用来修饰函数。在使用 static 关键字修饰变量时,我们称此变量为静态变量。 静态变量的存储方式与全局变量一样,都是静态存储方式。但这里需要特别说明的是,静态变量属于静态存储方式,属于静态存储方式的变量却不一定就是静态变量。例如,全局变量虽然属于静态存储方式,但并不是静态变量,它必须由 static 加以定义后才能成为静态全局变量。 *** 隐藏与隔离的作用 上面已经阐述过,全局变量虽然属于静态存储方式,但并不是静态变量。全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,全局变量在各个源文件中都是有效的。 如果我们希望全局变量仅限于在本源文件中使用,在其他源文件中不能引用,也就是说限制其作用域只在定义该变量的源文件内有效,而在同一源程序的其他源文件中不能使用。这时,就可以通过在全局变量之前加上关键字 static 来实现,使全局变量被定义成为一个静态全局变量。这样就可以避免在其他源文件中引起的错误。也就起到了对其他源文件进行隐藏与隔离错误的作用,有利于模块化程序设计。 *** 保持变量内容的持久性 有时候,我们希望函数中局部变量的值在函数调用结束之后不会消失,而仍然保留其原值。即它所占用的存储单元不释放,在下一次调用该函数时,其局部变量的值仍然存在,也就是上一次函数调用结束时的值。这时候,我们就应该将该局部变量用关键字 static 声明为“静态局部变量”。 当将局部变量声明为静态局部变量的时候,也就改变了局部变量的存储位置,即从原来的栈中存放改为静态存储区存放。这让它看起来很像全局变量,其实静态局部变量与全局变量的主要区别就在于可见性,静态局部变量只在其被声明的代码块中是可见的。 静态局部变量一般的使用场景: - 需要保留函数上一次调用结束时的值。 - 如果初始化后,变量只会被引用而不会改变其值,则这时用静态局部变量比较方便,以免每次调用时重新赋值。 *** 默认初始化为 0 在静态数据区,内存中所有的字节默认值都是 0x00。静态变量与全局变量也一样,它们都存储在静态数据区中,因此其变量的值默认也为 0。 #+begin_src c :tangle tmp/static_variable.c #include void count(); void accumulate(int); static int sum; //静态全局变量, 类似全局变量, 但作用域仅在当前文件内有效 // 在静态数据区, 内存中所有的字节默认值都是 0x00, // 所以其变量的值默认也是 0. int main(void) { int i = 0; for (i = 0; i < 5; i++) { count(); accumulate(i); } return 0; } void count() { // 静态局部变量, 类似全局变量, 只会被初始化一次, 作用域仅在当前函数内有效 static int num = 0; num++; printf("count: %d\n", num); } void accumulate(int i) { sum += i; printf("accum: %d\n", sum); } #+end_src ** popen 函数 #+begin_src c :tangle tmp/popen.c #include int main(void) { FILE *cmdf = popen("pwd", "r"); /* if (!cmdf) { */ if (NULL == cmdf) { perror("Error to popen"); return 1; } char output[100]; if (NULL == fgets(output, 100, cmdf)) { perror("Error to fgets"); pclose(cmdf); return 2; } pclose(cmdf); printf("output: %s", output); return 0; } #+end_src ** fork 函数 #+begin_src c :tangle tmp/fork.c #include #include #include #include int main(void) { int i; printf("init, pid=%d\n", getpid()); for (i=0; i<2; i++) { pid_t pid = fork(); if (pid == 0) { /* 0 表示子进程 */ printf("child: i=%d. pid=%d ppid=%d\n", i, getpid(), getppid()); } else if (pid > 0) { /* 大于 0 表示父进程, 返回值为fork 出的子进程的 pid */ printf("parent: i=%d. pid=%d ppid=%d\n", i, getpid(), getppid()); wait(NULL); } else { /* 小于 0 表示出错 */ perror("Error to fork"); return 1; } } return 0; } #+end_src ** execvp 函数 #+begin_src c :tangle tmp/execvp.c #include #include #include int main(int argc, char** argv) { int des_p[2]; if(pipe(des_p) == -1) { perror("Pipe failed"); exit(1); } if(fork() == 0) { //first fork close(STDOUT_FILENO); //closing stdout dup(des_p[1]); //replacing stdout with pipe write close(des_p[0]); //closing pipe read close(des_p[1]); const char* prog1[] = { "ls", "-l", 0}; execvp(prog1[0], prog1); perror("execvp of ls failed"); exit(1); } if(fork() == 0) { //creating 2nd child close(STDIN_FILENO); //closing stdin dup(des_p[0]); //replacing stdin with pipe read close(des_p[1]); //closing pipe write close(des_p[0]); const char* prog2[] = { "wc", "-l", 0}; execvp(prog2[0], prog2); perror("execvp of wc failed"); exit(1); } close(des_p[0]); close(des_p[1]); wait(0); wait(0); return 0; //close(STDOUT_FILENO); const char* cmd[] = { "ls", "-l", NULL}; execvp(cmd[0], cmd); //直接输出到 stdout perror("Error to execvp"); return -1; } #+end_src ** pipe 函数 #+begin_src c :tangle tmp/pipe.c #include #include #include void getcmd() { int fd[2]; pipe(fd); if (fork() == 0) { close(fd[0]); dup2(fd[1], STDOUT_FILENO); close(fd[1]); execl("/bin/sh", "sh", "-c", "pwd", (char *)NULL); exit(EXIT_FAILURE); } char output[500]; read(fd[0], output, 500); printf("Read from pipe: %s----------", output); } int main(int argc, char** argv) { getcmd(); return 0; } #+end_src