這一章主要是要解決這麼幾個問題:數組
當執行程序時,main函數是如何被調用的?ide
main函數的原型是:函數
int main(int argc, char *argv[]);佈局
其中argc是命令個數,argv則是字符指針,指向字符串(命令)。spa
當內核執行一個C程序的時候,是由一個特別的起始例程(exex函數族的一個)來調用main函數的。命令行
命令行參數是如何傳遞給執行程序的?線程
當執行一個程序時,調用exec的進程可將命令行參數傳遞給該新程序。argc[argc]是NULL。指針
典型的存儲器佈局是什麼樣式的?code
一個C程序由這麼幾個segment(段)組成:text segment, data segment, bss segment, stack segment, heap等。對象
bss段就是用來存放全局變量等不在函數內聲明的變量。(因此你定義了一個全局變量,但沒有初始化,你打印出來會是等於0的。由於exec會幫你初始化爲0)
如何分配額外的存儲空間?
ISOC指定了三個用於動態分配內存的函數:
(1)malloc,分配指定字節數的存儲區。此存儲區的字節的初始值不肯定。
(2)calloc,爲指定數量和指定字節數的對象分配存儲空間,該空間中的每一位都初始化爲0。
(3)realloc,更改之前分配區的長度(增長或減小),當增長時,則是移向一塊更加的新區域,新增的部分的初始值不肯定。
#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj, size_t size);
void *realloc(void *ptr, size_t newsize);
三個函數返回值:成功返回非NULL指針,失敗返回NULL指針
void free(void *ptr);
對於上面的這四個函數,我是對malloc和free比較熟悉。下面再說點,其實實際得到的空間會比要求的會多一些出來,多出來的會用來存儲這個空間的一些參數,好比說:分配空間的大小,指向下一個分配空間的指針等等。
因此使用這些函數通常比較多犯的兩個錯誤是:1.像數組那樣,越界,日後面寫東西,這樣會致使一些很嚴重的錯誤,可能下一個分配空間的指針指向的空間就找不到了。
2.沒有free調那些不用的空間,那麼就會形成泄漏或者free掉一個空指針。
這兩個錯誤都是很難檢測出來的,因此要特別當心。
進程如何使用環境變量?
介紹幾個用於環境變量操做的函數:
#include <stdlib.h>
char *getenv(const char *name);
找到則指向該環境變量的指針,不然返回NULL
int putenv(char *str);
int setenv(const char *name, const char *value, int rewrite);
int unsetenv(const char *name);
三個函數返回值:成功返回0,出錯返回非0
getenv()函數就是得到某個環境變量的值;
putenv()取形式爲name = value的,並將其放入環境表中。若是name已經存在,則先刪除原來的定義字符串。
setenv()將name設置爲value。若是環境中name已經存在,則若rewrite非0,則首先刪除現有的定義;若rewrite爲0,則不刪除現有定義(什麼都不幹)。
unsetenv()則刪除name的定義,即便不存在也不出錯。
各類不一樣的進程終止方式(由於如今還不太懂,因此也只是簡單的說一下)
有8種方式使進程終止,其中5種是正常終止
1.從main返回
2.調用exit
3.調用_exit或_Exit
4.最後一個線程從其啓動例程返回
5.最後一個線程調用pthread_exit
異常終止有3種方式
6.調用abort
7.接到一個信號並終止
8.最後一個縣城對取消請求做出響應
longjmp和setjmp函數以及它們和棧的交互做用
咱們都知道,棧是保存用來保存函數的一些信息的,以便返回時可以找到以前的那個函數。好比這麼一個例子,main函數裏調用do_line函數,do_line函數裏調用cmd_add函數,則當調用到cmd_add函數時,棧是這樣的:
要是在cmd裏遇到錯誤,想返回到main函數時怎麼辦?那就要用到setjmp函數和longjmp函數了。
#include <setjmp.h>
int setjmp(jmp_buf env);
返回值:直接調用返回0,不然就返回longjmp的val值
void longjmp(jmp_buf env, int val);
簡單來講,在嵌套調用的函數中,若是遇到了longjmp函數,則會立刻返回到調用setjmp函數的那個函數。好比說我在cmd_add函中調用了longjmp函數,在main函數中設置setjmp函數。當我在cmd_add函數中由於錯誤而觸發到longjmp函數,那麼就會立刻返回到具備setjmp函數的main函數了。當返回去了,而在棧裏各個函數的變量的值會變得怎樣呢?
下面給出例子:
1 #include "apue.h" 2 #include <setjmp.h> 3 4 static void f1(int, int, int, int); 5 static void f2(void); 6 7 static jmp_buf jmpbuffer; 8 static int globval; 9 10 int main(void) 11 { 12 int autoval; 13 register int regival; 14 volatile int volaval; 15 static int statval; 16 17 globval = 1; 18 autoval = 2; 19 regival = 3; 20 volaval = 4; 21 statval = 5; 22 23 if (setjmp(jmpbuffer) != 0) 24 { 25 printf("after longjmp\n"); 26 printf("globval = %d, autoval = %d, regival = %d, volaval = %d, statval = %d\n", 27 globval, autoval, regival, volaval, statval); 28 exit(0); 29 } 30 31 /* 32 * Change variables after setjmp, but before longjmp. 33 */ 34 globval = 95; 35 autoval = 96; 36 regival = 97; 37 volaval = 98; 38 statval = 99; 39 40 f1(autoval, regival, volaval, statval); /* never return */ 41 exit(0); 42 43 } 44 45 static void f1(int i, int j, int k, int l) 46 { 47 printf("in f1():\n"); 48 printf("globval = %d, autoval = %d, regival = %d, volaval = %d, statval = %d\n", 49 globval, i, j, k, l); 50 f2(); 51 } 52 53 static void f2() 54 { 55 longjmp(jmpbuffer, 1); 56 }
書上說這變量變不變是看狀況,你能夠在你本身的電腦上試一試。