10 C/C++ - 目录

C语言及函数库是自己在日常学习工作中的总结。

 

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
10GNU 编译系统http://www.cnblogs.com/elewei/p/8506182.html
11GNU makehttp://www.cnblogs.com/elewei/p/8064881.html
12GDBhttp://www.cnblogs.com/elewei/p/5996052.html
13Githttp://www.cnblogs.com/elewei/p/8275700.html

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2. 经典C/C++语言书籍

* C程序设计语言

* C和指针

* C专家编程

* C语言程序设计现代方法

* C Primer Plus

* 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程序

cc program.c

 

2)编译并链接几个C源文件

cc main.c sort.c lookup.c

 

 

3) 编译一个C源文件,并把它和现存的目标文件链接在一起

cc main.o lookup.o sort.c

 

 

4) 编译单个C源文件,并产生一个目标文件

cc -c program.c

 

 

5) 链接几个目标文件

cc main.o sort.o lookup.o

 

-lname  表示链接器会同时在name的函数库中进行查找 

 

3. 可执行文件包含两部分内容

一、程序和数据

二、相关的描述信息

 

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
 
 
编程练习
设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,
它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
 
两种实现方式:数组与链表
#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;
}

 

 

 

转载于:https://www.cnblogs.com/elewei/p/7648220.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值