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; }