《C专家编程》1-2章阅读收获

一、

C诡异离奇,缺陷重重,却获得了巨大的成功。


·编译器设计:效率(几乎)就是一切。编译器的效率包括两个方面:运行效率(代码的运行速度)和编译效率(产生可执行代码的速度)。

除了开发和学习环境外,运行效率起决定作用。


·数组下标0的开始。这个编译器的设计者的选择,因为偏移量的概念在他们心中已经根深蒂固。

·C语言的基本数据类型与底层硬件相对应。

·auto关键字是摆设(在C++11后,auto已经变成自动类型判定这一强大功能)

·C程序员要自己管理动态内存的使用,创建各种大小的数组,测试数组边界。并且自己进行范围检查。

C++引入一些新方法,使得宏这种预处理器几乎无用武之地。(这句话并不理解)

编译限制:在代码移植的时候应该不同编译器之间的差距。

·“安静的改变”   算术的转换  ,2个操作数的类型不同将会被转换。

                   数据类型朝着浮点精度更高、长度更长的方向转换,整形数如果转换为signed不会丢失信息,就转换为signed,否则转换unsigned。

               当无符号数unsigned int 和signed int比较的时候,在标准C(ANCI C),有符号数将被自动转换为无符号数。(注意当出现比较的时候,可能出现bug)

【尽量不要使用无符号数】包括年龄,国债等。


·二、这不是bug,而是语言特性


·switch: 1、 如果没有default,而且所有的case都不匹配,那么将跳过这个switch代码段。

 2、一条switch最多有257个标签(256个可能的值和一个EOF)

       3、把default打成defau1t(把“l”打成“1”),一般的lint程序检测不出

               4、const并不是常量

               5、一般来说case后面要加break,不然将顺序执行case 语句(fall through错误)


在定义C函数的时候,在缺省情况下函数的名字是全局可见的。

在函数前加extern的缺省存储类型说明符是冗余的。

想要限制对这个函数的访问必须在函数前加一个static。


多义符号(多用符号)

static在函数内部,表示该变量的值在各个调用中保持延续性
在函数这一级,表示该函数只对本文件可见
extern用于函数定义,表示全局可见(属于冗余的)
用于变量,表示它在其他地方定义
void作为函数的返回类型,表示不返回任何值
在指针声明中,表示通用的指针声明
位于参数列表中,表示没有参数
*乘法运算符
用于指针,间接引用
位于参数列表中,表示没有参数
&位的AND操作符
取地址操作符

优先级问题表达式可能误以为的结果实际结果
.的优先级高于*
(->操作符用于解决这个问题)
*p.fp所指对象的字段f
(*p).f
对p取f偏移,作为指针,然后进行接触引用操作
[]高于*int *ap[]ap是个指向int数组的指针
int(*ap)[]
ap是个元素为int指针的数组
int *(ap[])
函数( )高于*int *fp()fp是个函数指针,所指向的
函数返回int
fp是个函数,返回值是个int*类型
==和!=高于位运算符(val&mask!=0)(val&mask)!=0val&(mask!=0)
算术运算符高于移位运算符msb<<4+lsb(msb<<4)+lsbmsb<<(4=lsb)
逗号运算符优先级最低   

有一条很实用的建议:乘法和除法优于加法和减法,在涉及其他操作符是一律加上括号。


运算符的结合性:结合性只用于表达式中同时出现2个相同的优先级操作符的情况,用于消除歧义。

例如a=b=c;  =具有右结合性,所以该句语句等同于,b=c;a=b;

 (不如分开或是用括号,不要自找麻烦)

                                                                                                                                                           

 在函数中返回一个数组例如下面的代码

char * localize_time(char * filename)
{
    char buffer[20];
    //do something
    return buffer;
}

buffer是一个自动分配内存的变量,也就是函数的局部变量,当控制流离开声明局部变量的范围时,自动变量将失效。

返回一个指向局部变量的指针,当函数结束,该变量已经被销毁,谁也不知道这个指针指向地址的内容是什么。

解决方案:

A、使用全局声明的数组

          简单易用,任何人都有可能修改这个数组。

          函数的下一次调用会覆盖当前的数据。、

B、使用静态数组  :static char buffer[20];

        将修改范围限定在函数范围

        函数的下一次调用会覆盖当前的数据

C、显示的分配内存

char * func()
{
    char * s = malloc(120);
    //....
    return s;
}
     防止函数外的修改

     每次调用不会覆盖以前的返回值

    适合多线程

    程序员要承担内存管理的责任,必须记得要释放内存,以免造成内存泄漏

    在同一代码块中进行malloc和free操作,可以更为轻松进行内存管理

lint程序

   lint程序是一个检测工具,可以检查出bug和一些不可靠的编码风格。后来为了编译器做得更小、更快、更简单,

把lint程序从编译器中抽出来了。





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值