C语言总结


C语言总结
C语言的概述(自己总结)
    起源,发展,现状,特点,优缺点
数据类型
    内建:C语言自带的数据类型
        整型
            stdint.h    对数据类型进行了封装
            limits.h     各种数据类型的最大值是小值
            unsigned   
                uint8_t,uint16_t,uint32_t,uint64_t
                char,short,int,long,long long
                char 0~255  256个值
                short 0~65535 65536个值
            signed
                int8_t,int16_t,int32_t,int64_t
                char,short,int,long,long long
                char -128~127 256个值
                short    -32768~32767 65536个值               
               
        浮点型(小数点浮动)
            数据格式:符号位 指数位 尾数位
            默认小数点后六位有效,精度有限,运算效率低
            有专门针对浮点运算的CPU
            float 4
            double 8
            如何判断float类型的数据是“零值”?
            if(val<0.000001 && val>-0.000001)
            {
                //不等于0,但无效,相当于零值
            }
            如何提高浮点类型数据的准确率?
                先放大,在还原。
        布尔型
            由于C语言出现于1970年左右,布尔类型流行于1980以后,所以c语言中是没有真正的布尔类型。
            bool  stdbool.h
            true 非零值 NULL 绝大多情况小为假 ''
            false 零值
            NULL == ((void*)0)||((void*)1);
            _bool C99标准中补充的
            如何判断int,bool,int*类型的值是否为假?
            int num;           
            if(0 == num)
            if(flag)
            if(NULL==p)
        字符型
            底层采用整数存储的,整数与ASCII表的字符对应
            '' 0
            '0'    48
            'A' 65
            'a' 97

            转义字符
            a
            
           
            v
            f
           
           
            %%
            "
            \
 
        枚举
            功能受限制的int类型,防君子不防小人
            使用枚举是一直锦上添花,使用枚举可以提高程序的安全性和可读性
            有名枚举
            typedef enum CMD    {ADD,DEL,FIND};
            可以定义枚举变量
            匿名枚举
            ENUM {UP,DOWN,RIGHT,LEDT}
                使用枚举值,或者与switch配合使用
        指针:整型(整数),表示的是内存的编号
    自建:C程序自己设计的数据类型
        结构
        联合
        数组

变量(容器)与常量
   
    常量:字面值,宏常量,枚举值,初始化过并且被const修饰的全局变量
    变量:
        全局变量:普通全局变量,静态全局变量
            作用域不同
        局部变量:普通全局变量,静态全局变量
            存储位置不同:普通在栈,静态在bss
        块变量:普通块变量,静态块变量
    变量名:
        1、由数字、字母、下划线组成
        2、不能以数字开头
        3、不能与关键字重名
        4、见名知义
            功能、范围、类型
           
    输入数据
        scanf 占位符 变量地址
        scanf返回值,成功接取数据的个数
        如何不理输入缓冲区:
            getchar()
        scanf("%*[^ ]"),scanf("%*c");
        stdin->_IO_read_ptr = stdin->_IO_read_end;
    输出数据
        printf 占位符 变量名
        数据遇到什么条件才会从缓存区到达屏幕:
            1、满4k(4096byte)
            2、遇到
            3、遇到输入类型的函数
            4、手动刷新 fflush(stdin);
            5、程序结束
数组
    数组的定义:类型 数组名[数量];
        在内存的分布上优先定义数组,再定义变量
    数组的初始化:类型 数组名[数量] = {val1,val2...};
        1、初始化值过多会有警告
        2、初始化值不够补0
        3、类型 数组名[数量] ={};
        4、类型 数组名[] = {val1,val2...};
    数组的越界:
        1、脏数据
        2、段错误
        3、一切正常
    变长数组:数组的长度在编译时无法确定,在运行时可以发生变化,当执行到定义数组语句时,数组的长度就确定下来了,不可再变
        优点:根据需求在确定数据的长度,节约内存。
        缺点:不能初始化(数组的初始化是由编译器帮助完成)
    多维数组:
        一维数组:变量组成的队列
        二维数组:变量组成的方阵
        三维数组:变量组成的立方体

流程控制语句:
    分支
    if    else if else
    switch
        小括号中只能是整型数据
        case后必须是常量
        default 最后执行
        break 关闭执行开关
    循环
    for
        for([1];[2];[3])
        {
            [4]
        }
        for 语法灵活,1,2,3,4都可以缺少
            用循环变量i(index)引导for的运行,负责明确知道循环次数的情况       
    while
        是for的一种精简,负责只知道循环条件
    do while
        先执行循环体,在判断循环条件,直到循环

    if、for、while 如果没有大括号,默认下一行代码是它的语句体,但不建议这样使用,大括号不要省略(安全性、可扩展性),如果执行异常,记得检查小括号后面是否有多余的分号
    跳转
    goto
        goto 标签;功能是在函数内可以任意跳转,这种跳转会破坏原先的分支,循环结构
        大多数公司会禁止使用goto,禁止的方式就是把goto定义为病毒(应用层程序)
        但在驱动编程时goto非常适合用来处理异常
    break
        1、switch中关闭开关
        2、在循环中使用可以跳转一层循环
    continue
        只能在循环中使用,功能是结束本次循环进入下次循环
    return   
        1、返回函数的执行结果
        2、提前结束函数的执行

函数
    函数的声明:
        extern 返回值类型 函数名(参数类型,参数名,..);
        返回值类型 函数名(参数类型,参数名,...);
        返回值类型 函数名(参数类型1,参数类型2,...);
    函数的定义:
        返回值类型 函数名(参数类型,参数名,...);
        {
            函数体
        }

    使用函数要注意的问题:
        1、函数传参全部都是值传递(内存拷贝)
            由于数据名就是指针,以数组当函数参数时也是值传递,而且数组的长度也会丢失,
        2、函数的隐式声明
            当调用函数,如果没有提前声明,编译器会猜测函数的格式,如果猜测正确函数则正常执行如果猜错,则会执行异常。
        3、如果函数不需要参数要写void
            定义函数时如果小括号中是空的,则意味着任意类型,任意个参数都可以调用函数
        4、不写return不表示没有返回值
       
    递归:
        函数自己调用自己的行为叫递归,这种解决问题的思想:分支
        这种调用极易引发死循环,递归编写的格式:
        1、出口
        2、解决一部分问题
        3、再次调用自己
       
        递归是一种解决复杂问题的常见手段,也比较适合解决树型结构问题,容易理解但不能模拟它的执行过程

指针:
    什么是指针:一种数据类型,代表内存编号的整数
        使用它可以定义指针变量
    什么情况下使用指针:
        1、函数之间共享变量
        2、优化函数传参
        3、使用堆内存必须配合指针
      指针的使用方法:
        定义:类型* 变量名_p;
        1、指针的类型决定了,通过指针访问内存时的字节数
        2、指针不能连续定义
            int* p1,p2,p3;//p1是指针,p2是int变量
            int *p1,*p2,*p3;
        3、指针的默认是随机的(野指针),如果没有确定的值可以初始化为NULL(空指针)
        4、指针变量与普通变量的使用方法有很大区别,因此最好从名字上就能区分开,所以以p结尾
        arr,str
        赋值:指针变量名 = 内存编号
            1、类型要匹配,否则会有警告
            2、类型指针<=>void*
            3、void*不能直接使用,要转换成有类型的指针
            int* p = malloc(4);
        访问内存:*指针变量
            int *p = &num;
            *p <=>num;
            这个过程是有可能产生段错误的
            访问内存的字节数由指针的类型决定的           
    使用指针要注意的问题
        1、空指针
            指针变量的值为NULL,NULL不一定是0
            使用空指针的后果就是一定产生段错误
            0地址是操作系统的复位地址,存储了重启时要使用的数据,因此不能让应用程序访问,NULL也是应用程序的错误标志,如果函数的返回值是NULL说明函数执行错误
                使用来历不明的指针钱要先检查NULL == p
                strlen strcat strcpy strcmp
               
        2、野指针
            指针变量的值不确定
            使用野指针不一定出错,肯呢过产生的后果:
            1、脏数据
            2、段错误
            3、一切正常
            出现野指针比出现空指针的后果更严重,因此野指针无法判断
            防止野指针出错是只能从根源着手,不制造野指针:
            1、定义指针变量时一定要初始化
            2、不持有局部变量的地址
            3、堆内存一旦初始释放,指针要及时设置为空

        3、指针的运算
            因此指针变量的值就是整数,所以整数数据可以使用的运算符它基本都可以使用,但是要以实际意义为准则
       
        4、指针与数组名
            数组名:是一种常指针,他与数组的首地址是对应关系
            指针和数组名的用法是可以互换的:
                p[i] = *(p+i);
                *(arr+i) = arr[i];

修饰变量的关键字
    auto    不能与static 一起用,全局不变量也不能使用
        定义自动分配,释放的变量,不加就代表加
    unsigned:定义无符号整型变量
    signed:定义有符号整型变量,不加就代表加
    const:为数据提供一种保护机制,被它修饰过的变量不能显示修改
        变量、函数参数、返回值、指针
        const 全局变量 初始化 = 常量   
        const int *p; 不能通过 *p修改内存的值
        inr const *p;同上
        int* const p; p的值不能修改
        const int* const p; 不能通过*p修改内存的值,p的值也不能修改
       
    static
        限制作用域:全局变量、函数
        改变存储位置:局部、块变量
        延长生命周期:局部、块变量
    volatile
        防止编译器优化变量的取值过程
    register
        申请把变量存储到寄存器
    extern
        声明变量、函数
程序在内存中的分布
    代码:可以执行文件会被全部加载到此段
    只读:字面值、常量
    全局:被初始化过的全局变量
    bss:静态变量、未初始化的全局变量
        程序执行前会把这段内存清理为0
    栈:局部变量、块变量
    堆:程序员自己变量、无法取名、足够大

字符串
    串:是一种数据结构,由若干个相同类型的数据组成,有一个明确的结束标志''。
    字符串字面值:
        以地址形式存储在只读内存中。
        如果在程序中已经存在一份字符串字面值,当再使用它时不会在内存中再定义一份。
        字符串可以换行写,编译器会自动把它们连接。
    定义:
        const char* str = "hehe";
        char str[] = "hehe";
    处理字符串的函数:
        输入:
            scanf
            gets
            fgets
            getstr
            fscanf
            fread
        输出:
            printf
            puts
            fpritnf
            fwirte
        string.h
            strlen
            strcat/strncat
            strcpy/strncpy
            strcmp/strncmp
           
            strchr
            strstr
            atoi
            memset
            memcpy
           
            sscanf/sprintf
            字符串-》数值 数值-》字符串
堆内存使用
    C语言中是没有提供内存管理的语句,只能靠标准库提供的库函数(stdlib.h)。
    内存芯片-》操作系统-》malloc-》a.out
   
    malloc 申请内存
    calloc 按块申请内存,并把申请的内存初始化
    realloc 调整已有内存的大小,把内存调大就相当于申请内存,把内存调小就相当于在释放内存。
    free 内存的释放。
   
    使用堆内存要注意的问题:
        1、重复释放
        2、越界:
            前续错误
            后续错误
            段错误
            脏数据
            一切正常
        3、泄漏
            谁申请,谁释放
            谁知道该释放,谁释放
           
结构、联合
    typedef struct 结构名
    {
        成员类型 成员名=-1;
        void func(void); // eroor
        void (*funcp)(void); // 允许
        char sex:1;
    }结构类型;
   
    1、在定义结构变量时struct不能省略。
    2、结构的成员不能初始值。
    3、结构的成员不能是函数,但可以是函数指针。
    4、结构变量可对结构变量直接赋值
        Student stu1 = {};
        Student stu2 = stu1;
        stu2 = stu1;
       
    结构的大小:
        补齐:结构的总字节数要是它最大成员的整数倍,如果不是则添加空白字节补齐。
        对齐:每个成员在结构中的内存起始编号,要是它自身大小的整数倍,如果不是则添加空白字节保持对齐。
        Linux和Windows系统对待补齐和对齐的区别?
            Window会严格按照补齐和对齐的规定严格执行
            Linux对待补齐和对齐时,超过4字节按4字节计算。
            补齐和对齐的字节数是可以设置的。
       
    联合:节约内存的一种手段。
    联合常考的问题:
        1、联合的字节数。
            union data
            {
                char arr[5];
                int num;
            };
           
        2、使用联合判断大、小端系统。
            0x010203 高位数据1 低位数据3
            0x18[][][][] 高位地址0x1B 低位地址0x18
            大端 0x01020304
            小端 0x04030201
文件操作:
    文件的分类:
        二进制文件:数据的补码。
        文本文件:存储的是ASCII的二进制。
       
    windows系统对待换行与Linux系统不同。
       
       
       
    文件的打开方式:
        r
        w
        a
        r+
        w+
        a+

        wb ->
        w  ->
       
    文件操作函数:
        fopen
        fscanf/fprintf
        fgets/fputs
        fread/fwrite   
        fclose
       
        fseek 调整文件位置指针
        ftell 返回文件位置指针的位置
        rewind 调整文件指针到文件的开头。





















   






附件列表

    原文地址:https://www.cnblogs.com/LyndonMario/p/9326068.html