C語言及函數庫是本身在平常學習工做中的總結。html
1. C語言技術目錄程序員
序號 |
描述 |
連接 |
01 |
類型、表達式、語句 |
http://www.cnblogs.com/elewei/p/8232737.html |
02 |
字符串、字符、字節
|
http://www.cnblogs.com/elewei/p/7658002.html |
03 |
數組、指針 |
http://www.cnblogs.com/elewei/p/5971669.html |
04 |
內存管理 |
http://www.cnblogs.com/elewei/p/7500152.html |
05 |
文件 |
http://www.cnblogs.com/elewei/p/5967353.html |
06 |
結構和聯合 |
http://www.cnblogs.com/elewei/p/7502824.html |
07 |
位操做 |
http://www.cnblogs.com/elewei/p/8149884.html |
08 |
預處理器 |
http://www.cnblogs.com/elewei/p/7501842.html |
09 |
編碼風格 |
http://www.cnblogs.com/elewei/p/5995978.html |
10 |
GNU 編譯系統 |
http://www.cnblogs.com/elewei/p/8506182.html |
11 |
GNU make |
http://www.cnblogs.com/elewei/p/8064881.html |
12 |
GDB |
http://www.cnblogs.com/elewei/p/5996052.html |
13 |
Git |
http://www.cnblogs.com/elewei/p/8275700.html |
2. 經典C/C++語言書籍編程
* C程序設計語言數組
* C和指針編程語言
* C專家編程函數
* C語言程序設計現代方法工具
* C Primer Pluspost
* C標準庫學習
* GNU Make測試
* http://blog.csdn.net/suprman/article/details/1467470
* 寫C源代碼遵循原則: http://www.ruanyifeng.com/blog/2009/06/unix_philosophy.html
* Quora - https://www.quora.com/What-is-the-best-way-to-learn-C++-on-my-own
3. 基本概念
C語言在1972年來自貝爾實驗室的Dennis Ritchie和Ken Thompson, 它們當時正在設計UNIX操做系統,
C由此而誕生。
編程語言的特性
(1) 變量與常量 - 程序處理的兩種基本數據對象。
(2) 聲明語句 - 說明變量的名字及類型,也能夠指定變量的初值
(2) 內置數據類型 - 決定該對象可取值的集合以及可對該對象執行的操做
(3) 表達式和語句 - 指定將要進行的操做
(4) 控制結構
(5) 函數
使用C語言的七個步驟:
Step 1. 定義程序目標
Step 2. 設計程序
Step 3. 編寫代碼
Step 4. 編譯
Step 5. 運行程序
Step 6. 測試與調式程序
Step 7. 維護與修改程序
Step 8. 總結
1. C源程序編譯與連接過程

第一步: hello.c 文件 進行 預處理 變成 hello.i 文件
第二步: hello.i 文件 進行 編譯 變成 hello.s 彙編文件
第三步: hello.s 文件 進行 彙編編譯 變成 hello.o 目標文件
第四步: hello.o 文件 進行 連接 變成 hello.exe 文件
2. 編譯和連接
1)編譯並連接一個徹底包含於一個源文件的C程序
2)編譯並連接幾個C源文件
cc main.c sort.c lookup.c
3) 編譯一個C源文件,並把它和現存的目標文件連接在一塊兒
cc main.o lookup.o sort.c
4) 編譯單個C源文件,併產生一個目標文件
5) 連接幾個目標文件
cc main.o sort.o lookup.o
-lname 表示連接器會同時在name的函數庫中進行查找
3. 可執行文件包含兩部份內容
1、程序和數據
2、相關的描述信息
PE格式
Win: .exe , .dll, .sys
Linux: .elf
使用PEID/PETool查看PE結構
問題:
1. 從源文件到最終生成可執行文件,要經歷哪些階段的處理?
2. 進程與程序的區別是什麼? 進程與線程的區別是什麼?
3. 理解PE文件格式,經過工具找到pe中的e_lfanew, entrypoint, 導入表地址。
4. 什麼是PE中的EOP, OEP, 什麼是ImageBase, VA, RVA?
5. PE中的Section有哪些?怎麼組織和管理的? 分別起什麼做用?
6. 試求下面VA對應的文件地址:
名稱 name Voffset Vsize Roffset rsize 標誌
.text 0000540 00069f9b 00000540 00069fc0 68000020
虛擬地址 VA=00049586 ImageBase = 00040000
求虛擬地址 VA對應的文件地址?
經典問題: main 函數執行之前,還會執行什麼代碼?
全局對象的構造函數會在main 函數以前執行。
經典問題:main 主函數執行完畢後,是否可能會再執行一段代碼,給出說明?
能夠
int fn1(void), fn2(void), fn3(void), fn4 (void); void main( void ) { String str("david"); _onexit( fn1 ); _onexit( fn2 ); _onexit( fn3 ); _onexit( fn4 ); printf( "This is executed first.\n" ); } int fn1() { printf( "next.\n" ); return 0; } int fn2() { printf( "executed " ); return 0; } int fn3() { printf( "is " ); return 0; } int fn4() { printf( "This " ); return 0; }
The _onexit function is passed the address of a function (func) to be called when the program terminates normally.
Successive calls to _onexit create a register of functions that are executed in LIFO (last-in-first-out) order. The functions passed to _onexit cannot take parameters.
4. C語言內存分配
當一個C程序載入內存後,佔用內存的起始到結束地址範圍時,會將內存分紅3個部分:
text segment(code segment): 編譯後程序佔用的內存空間
Data Segment: 分紅兩個部分,
* 初始化數據(Data Segment)
* 未初始化數據(BSS)
heap:當程序在執行期間分配內存時,內存存放在堆區 (調用malloc)
stack: 棧用來存放本地變量以及傳遞的參數 (RLIMIT_STACK)

問題:描述內存分配方式以及它們的區別?
1) 從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。例如全局變量,static 變量。
2) 在棧上建立。在執行函數時,函數內局部變量的存儲單元均可以在棧上建立,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置於處理器的指令集。
3) 從堆上分配,亦稱動態內存分配。程序在運行的時候用malloc 或new 申請任意多少的內存,程序員本身負責在什麼時候用free 或delete 釋放內存。動態內存的生存期由程序員決定,使用很是靈活,但問題也最多。
寫一個函數找出一個整數數組中,第二大的數
/*
* 思路: 將數組第一個數假定爲最大值
* 遍歷後面的數,與第一個數進行比較
* 若是比最大值大,將當前最大值變成第二大值,將其變成最大值
* 若是比第二大值大,將其變爲第二大值
*/
const int MINNUMBER = -32767 ; //定義最小值
// data 爲定義的數組, count 爲數組長度
int find_sec_max( int data[] , int count) { int maxnumber = data[0] ; // 假定第一個值爲最大 int sec_max = MINNUMBER ; // 初始化第二小值 for ( int i = 1 ; i < count ; i++) { if ( data[i] > maxnumber ) // 首先跟最大值比較 { sec_max = maxnumber ; // 把當前值給第二大值 maxnumber = data[i] ; // 把最大值給maxnumber } else { if ( data[i] > sec_max ) // 而後跟第二大值比較 sec_max = data[i] ; // 若是大於當前第二大值,賦值 } } return sec_max ; }
下面的代碼輸出是什麼,爲何?
void foo(void) { unsigned int a = 6; int b = -20; (a+b > 6) puts(">6") : puts("<=6"); }
>6
緣由是當表達式中存在有符號類型和無符號類型時全部的操做數都自動轉換爲無符號類型。
所以-20變成了一個很是大的正整數,因此該表達式計算出的結果大於6。這一點對於應當頻繁用到無符號數據類型的嵌入式系統來講是豐常重要的。
評價下面代碼
unsigned int zero = 0; unsigned int compzero = 0xFFFF; //1's complement of zero
對於一個int型不是16位的處理器爲說,上面的代碼是不正確的。
unsigned int compzero = ~0;
下面的代碼輸出是什麼,爲何?
char *ptr; if ((ptr = (char *)malloc(0)) == NULL) puts( "Got a null pointer "); else puts( "Got a valid pointer ");
輸出結果是:Got a valid pointer
請問指針爲NULL時指向哪裏,分配的空間爲0時又指向哪裏?
當使用malloc後,只有在沒有足夠內存的狀況下會返回NULL,或是出現異常報告。
malloc(0),系統就已經幫你準備好了堆中的使用起始地址(不會爲NULL)。
可是你不能對該地址進行寫操做(不是不容許),若是寫了話,當調用free(ptr)就會產生異常報告(地址受損)。
NULL通常預約義爲(void *)0, 指向0地址。 malloc是在程序堆棧上分配空間,不會是0地址
malloc(0)是指分配內存大小爲零
NULL是不指向任何實體
malloc(0)也是一種存在不是NULL
兩種實現方式:數組與鏈表
#include <stdio.h> #include <stdlib.h>
int Josephu(int n, int m) { int flag, i, j = 0; int *arr = (int *)malloc(n * sizeof(int)); for (i = 0; i < n; ++i) arr[i] = 1; for (i = 1; i < n; ++i) { flag = 0; while (flag < m) { if (j == n) j = 0; if (arr[j]) ++flag; ++j; } arr[j - 1] = 0; printf("out %4d people is:%4d\n", i, j); } free(arr); return j; } int main() { int n, m; scanf("%d%d", &n, &m); printf("last winner is %d!\n", Josephu(n, m)); return 0; }
鏈表實現
#include <stdio.h> #include <stdlib.h> typedef struct Node { int index; struct Node *next; }JosephuNode; int Josephu(int n, int m) { int i, j; JosephuNode *head, *tail; head = tail = (JosephuNode *)malloc(sizeof(JosephuNode)); for (i = 1; i < n; ++i) { tail->index = i; tail->next = (JosephuNode *)malloc(sizeof(JosephuNode)); tail = tail->next; } tail->index = i; tail->next = head; for (i = 1; tail != head; ++i) { for (j = 1; j < m; ++j) { tail = head; head = head->next; } tail->next = head->next; printf("第%4d個出局的人是:%4d號/n", i, head->index); free(head); head = tail->next; } i = head->index; free(head); return i; } int main() { int n, m; scanf("%d%d", &n, &m); printf("最後勝利的是%d號!/n", Josephu(n, m)); return 0; }