zoukankan      html  css  js  c++  java
  • C陷阱与缺陷

    C陷阱与缺陷

    第一章 词法“陷阱”

    符号(token):指的是程序的一个基本组成单元,起作用相当于一个句子中的单词

    =不同于==

    &和|不同于&&和||

    词法分析中的“贪心法”

    C语言规则:每个符号应该包含尽可能多的字符

    整型常量

    整形常量的第一个字符是数字0,那么这个常量将被视作八进制数

    字符和字符串

    用单引号引起的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值。

    用双引号引起的字符串,代表的却是一个指向无名数组起始字符的指针


    第二章 词法“陷阱”

    理解函数声明

    构造表达式的规则:按照使用的方式来声明。

    硬件调用首地址为0位置的子例程

    (*(void(*)())0)();
    
    第一步,0为地址,对0地址取内容:
    (*0)()
    第二步,*必须要一个指针来做操作数,这个指针还应该是函数指针,因此对0作类型转换,
    转换后类型为:“指向返回值为void类型的函数的指针:
    void (*)()0
    从而得到:
    (*(void(*)())0)();
    
    若用typedef解决
    typedef void (*funcptr)();
    (*(funcptr)0)();
    

    运算符的优先级

    运算符 结合性
    () [] -> . 自左向右
    ! ~ ++ -- - (type) * & sizeof 自右向左
    * / % 自左向右
    + - 自左向右
    << >> 自左向右
    < <= > >= 自左向右
    == != 自左向右
    & 自左向右
    ^ 自左向右
    && 自左向右

    | ?: | 自右向左 |
    | assignnments | 自右向左 |
    | , | 自左向右 |

    • 任何一个逻辑运算符的优先级低于任何一个关系运算符

    • 移位运算符的优先级比算术运算符要低,但是比关系运算符要高

    注意作为语句结束标志的分号

    if(...);
        xx = xx;
    

    switch语句

    break别遗漏

    函数调用

    “悬挂”else引发的问题

    else始终与同一对括号内最近的未匹配的if结合


    第三章 语义“陷阱”

    指针和数组

    • C语言只有一维数组,而且数组的大小必须在编译期就作为一个常数确定下来。

    • 对于数组,我们能:确定数组的大小,获得只想数组下标为0的元素的指针

    • 其他的数组操作,看上去是以数组下标进行的,实际是指针进行的

    非数组的指针

    在C中,字符串常量代表了一块包括字符串中所有字符以及一个空字符(``)的内存区域的地址

    作为参数的数组声明

    避免“举隅法”

    空指针并非空字符串

    #define NULL 0
    

    绝不能被解除引用

    边界计算与不对称边界

    求值顺序

    运算符&&、||和!

    整数溢出

    如果算术运算符的一个操作数是有符号数,另一个是无符号数,那么有符号数会被转换为无符号数,”溢出“也不可能发生。但是,当两个操作数都是有符号数时,”溢出“就有可能发生。

    为函数main提供返回值


    第四章 连接

    一个c程序由多个分别编译的部分组成,这些部分通过一个叫做连接器的程序合并成一个整体。

    什么是连接器

    分别编译->整合

    连接器的输入是一组目标模块和库文件,输出是一个载入模块

    声明和定义

    extern

    命名冲突与static修饰符

    不同源文件之间相同的变量和源文件与库文件之间的命名冲突

    static是一个能够减少命名冲突的有用工具

    形参、实参和返回值

    检查外部类型

    两个不同源文件中的同名定义,类型不同时

    头文件

    规则:每个外部对象只在一个地方声明


    第五章 库函数

    返回整数的getchar函数

    getchar函数在一般情况下返回的是标准输入文件中的下一个字符,当没有输入时返回EOF(一个在头文件stdio.h中定义的值,不同于任何一个字符)

    更新顺序文件

    FILE *fp;
    fp = fopen(file, "r+");
    

    如果同时要进行输入和输出操作,必须在其中插入fseek函数调用。

    缓冲输出和内存分配

    程序输出有两种方式:一种是即时处理方式,另一种是先暂存起来,然后再大块写入的方式。

    控制写操作产生的数据输出量通过库函数setbuf实现

    setbuf(stdout, buf);
    

    所有写入到stdout的输出都应该使用buf作为输出缓冲区,直到buf缓冲区被填满或者调用fflush,buf缓冲区的内容才实际写入到stdout中。缓冲区大小由系统头文件<stdio.h>中的BUFSIZ定义

    使用errno检测错误

    很多库函数,当执行失败时会通知一个名称为errno的外部变量,通知程序该函数调用失败。

    当调用库函数时,应该先检测作为错误提示的返回值,确定程序执行已经失败,然后再检查errno来搞清楚出错原因。

    /*调用库函数*/
    if (返回的错误值)
        检查 errno
    

    库函数signal

    signal库函数作为捕获异步事件的一种方式

    #include 
    signal(signal type, handler function);//处理一个特定的信号,参数信号类型,事件处理函数
    

    signal处理函数能做的安全的事情似乎只有设置一个标置然后返回,期待主程序能够检查这个标志,发现一个信号已经发生。

    对于算术运算错误,signal处理函数的唯一安全、可移植的操作就是打印一个出错消息,然后使用longjmp或exit立即退出程序

    让signal处理函数尽可能地简单,并将它们组织在一起


    第六章 预处理器

    预处理器的重要性:

    1. 将某个特定数量在程序中出现的所有实例统统加以修改

    2. 函数调用会带来重大的系统开销

    宏只是对程序的文本起作用

    不能忽视宏定义中的空格

    预处理器从宏定义中就可以知道宏调用时是否需要参数

    宏不是函数

    最好在宏定义中把每个参数都用括号括起来

    确保宏中的参数没有副作用

    宏并不是语句

    assert宏,参数是一个表达式,如果为0,就使程序终止执行,并给出一条适当的出错信息。_FILE_和_LINE_是内建于C语言预处理器中的宏,会被扩展为所在文件的文件名和所处代码行的行号。

    #define assert(e) ((void)((e)||_assert_error(__FILE__, __LINE__)))
    

    ||运算符对两侧的操作数依次顺序求值

    宏并不是类型定义

    宏的常见用途,使多个不同变量的类型可在一个地方说明


    第七章 可移植性缺陷

    应对C语言标准变更

    函数声明的方式在不同标准中的移植性

    标识符名称的限制

    有些C语言不区分大写字母和小写字母

    整数的大小

    short int long

    • 3种类型的整数其长度是非递减的

      short型整数容纳的值肯定能够被int型整数容纳,int型整数容纳的值也肯定能够被long型整数容纳。

    • 一个普通(int类型)整数足够大以容纳任何数组下标

    • 字符长度由硬件特性决定

    字符是有符号整数还是无符号整数

    unsigned char

    移位运算符

    有符号整数的向右移位运算也不等同于除以2的某次幂。

    内存位置0

    null指针并不指向任何对象

    除法运算时发生的截断

    保证非负

    C语言只保证性质1

    随机数的大小

    RAND_MAX,rand函数的取值范围

    大小写转换

    函数的方法,时间会长一点

    宏定义的方法,不能保证传入的参数正确

    首先释放,然后重新分配

    不推荐

    可移植性问题的一个例子

  • 相关阅读:
    UIImageView的动画效果(左右移动、旋转、缩放)
    图片点击放大,再次点击回到原来状态(图片缩放)
    设置一个视图控制器为底部视图的方法
    Pods written in Swift can only be integrated as frameworks; add `use_frameworks!` to your Podfile or target to opt into using it. The Swift Pods being used are: ReactiveCocoa, ReactiveSwift, and Resul
    cocoaPod的使用
    cocoaPod安装过程
    RAC(reactivecocoa)的使用方法
    百度地图定位
    <NET CLR via c# 第4版>笔记 第11章 事件
    <NET CLR via c# 第4版>笔记 第10章 属性
  • 原文地址:https://www.cnblogs.com/luoxiao23/p/11179872.html
Copyright © 2011-2022 走看看