C的特性

1.C语言采用编译模式而不是解释模式,引入类型系统,每个变量在使用前必须先声明。

2.C语言排斥强类型,它允许程序员需要时可以在不同类型的对象间赋值。

3.C语言的基本数据类型直接与底层硬件对应。

4.表达式中的数组名可以看作是指针,但是数组和指针不是在任何情况下都是等效的。

5.register关键字:这个关键字能给编译器提供线索,就是程序中的哪些变量属于热门(经常被使用),这样就可以把它们存放到寄存器中。使用register关键字简化了编译器,却把包袱丢给了程序员。让编译器在使用各个变量时自动处理寄存器的分配工作显然比一经声明就把这类变量在生命期内始终保留在寄存器里要好。

6.C预处理所实现的功能:
字符串替换:(宏定义的常量)
头文件包含
通用代码模板的扩展:(宏定义的语句)

7.宏最好只用于命名常量,并为一些适当的结构提供简洁的记法。宏名应该大写,这样很容易与函数调用区分开来。

8.参数与原型不匹配:
编译如下代码:

void foo(const char **p) { }
int main(int argc,char **argv){
    foo(argv);
    return 0;
}

出现:
warning: passing argument 1 of 'foo' from incompatible pointer type [-Wincompatible-pointer-types]
note: expected 'const char **' but argument is of type 'char **'
因为const char **与char **并不相容,在ANSI C标准第6.3.2.2节中讲述约束条件的小节中有这么一句话:

每个实参都应该具有自己的类型,这样它的值就可以赋值给与它所对应的形参类型的对象(该对象的类型不能含有限定符)

这就是说参数传递过程类似于赋值。要使上述的赋值形式合法,必须满足下列条件之一:
a.两个操作数都是指向有限定符或无限定符的相容类型的指针。
b.左边指针所指向的类型必须具有右边指针所指向类型的全部限定符。
正是因为条件b,使得下面的代码是合法的:

char *cp;
const char *ccp;
ccp = cp;

分析:
a.左操作数是一个指向有const限定符的char指针。
b.右操作数是一个指向没有限定符的char指针。
c.char类型与char类型是相容的,左操作数所指向的类型具有右操作数所指向类型的限定符(无),再加上自身的限定符(const)。
d.反过来赋值,编译器会警告:
warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]

8.const float *类型并不是一个有限定符的类型——它的类型是“指向一个具有const限定符的float类型的指针”,也就是说const限定符是修饰指针所指向的类型,而不是指针本身。

9.关键字const并不能把变量变成常量。在一个符号前加上const限定符只是表示这个符号不能被赋值。也就是说它的值对于这个符号来说是只读的(但它并不能防止通过程序的内部或者外部的方法来修改这个值)。const最有用之处就是用它来限定函数的形参,这样该函数将不会修改实参指针所指向的数据,但其他的函数却可能会修改它。
const可以用在数据上,如:

const int limit = 10;
const int * limitp = &limit ;
int i = 27;
limitp = &i;

这段代码表示limitp是一个指向常量整型的指针。这个指针不能用于修改这个整型数,但是在任何时候,这个指针本身的值却可改变。这样,它就指向了不同的地址。const和*的组合通常只用于在数组形式的参数中模拟传值调用。它声称“我给你一个指向它的指针,但你不能修改它。”
这个约定类似于void *的用法,尽管在理论上void *可以用于任何情形,但通常被限制于把指针从一种类型转换为另一种类型。
改变const变量的值:

    const int limit = 10;
    int *limitp = &limit ;
    *limitp = 20;
    printf("%d",limit);

编译时警告:
int *limitp = &limit ;
warning: initialization discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
输出结果为:
20
而这样写:

    const int limit = 10;
    const int *limitp = &limit ;
    *limitp = 20;
    printf("%d",limit);

编译出错:
limitp = 20;
error: assignment of read-only location '
limitp'

10.算术转换:

整型升级:

char,short int或者int型位段,包括它们的有符号或无符号类型,以及枚举类型,可以使用在需要int或unsigned int的表达式中。如果int可以完整表示源类型的所有值,那么该源类型的值就转换为int,否则转换为unsigned int。

寻常算术转换:

许多操作数类型为算术类型的双目运算符会引发转换,并以类似的方式产生结果类型。它的目的是产生一个普通类型,同时也是运算符结果的类型。
首先,如果其中一个操作数的类型是long double,那么另一个操作数也被转换为long double。
其次,如果其中一个操作数的类型是double,那么另一个操作数也被转换为double。
再次,其中一个操作数的类型是float,那么另一个操作数也被转换为float。
否则,两个操作数进行整型升级,执行下面的规则:
如果其中一个操作数的类型是unsigned long int,那么另一个操作数也被转换为unsigned long int。
其次,如果其中一个操作数的类型是long int,而另一个操作数的类型是unsigned int,如果long int能够完整表示unsigned int的值,那么unsigned int类型操作数被转换为long int,如果long int不能完整表示unsigned int的值,那么两个操作数都被转换为unsigned long int。
再次,如果其中一个操作数的类型是long int,那么另一个操作数也被转换为long int。
再再次,如果其中一个操作数的类型是unsigned int,那么另一个操作数也被转换为unsigned int。
如果以上情况都不属于,那么两个操作数都为int。
浮点操作数和浮点表达式的值可以用比类型本身所要求的更大的精度和更广的范围来表示,而它的类型并不因此改变。

大致意思是:

当执行算术运算时,操作数的类型如果不同,就会发生转换。数据类型一般朝着浮点精度更高,长度更长的方向转换,整型数如果转换为signed不会丢失信息,就转换为signed,否则转换为unsigned。

一个微妙的bug:
#include <stdio.h>

int array[] = {23,34,12,17,204,99,16};
#define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))

int main(){
    int d=-1,x=0;
    if(d <= TOTAL_ELEMENTS -2)
        x = array[d+1];
    printf("%d",x);
    return 0;
}

编译输出警告:
if(d <= TOTAL_ELEMENTS -2)
warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
执行结果输出:
0
原因:
TOTAL_ELEMENTS所定义的值是unsigned int类型(因为sizeof()的返回类型是无符号数)。
if语句在signed int和unsigned int之间测试相等性,所以d被升级为unsigned int类型,-1转换成unsigned int的结果是一个非常大的正整数,导致表达式的值为假。
要修正这个问题,只要对TOTAL_ELEMENTS进行强制类型转换即可:

if(d <= (int)TOTAL_ELEMENTS -2)

此外,使用

#define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))

而不是

#define TOTAL_ELEMENTS (sizeof(array)/sizeof(int))

的好处在于前者可以在不修改#define语句的情况下改变数组的基本类型(比如,把int变成char)。

11.对无符号类型的建议:
a.尽量不要在代码中使用无符号类型,以免增加不必要的复杂性。尤其是,不要仅仅因为无符号数不存在负值而用它来表示数量。
b.尽量使用像int那样的有符号类型,这样在涉及升级混合类型的复杂细节时,不必担心边界情况(如-1被升级为非常大的正数)。
c.只有在使用位段和二进制掩码时,才可以用无符号数。应该在表达式中使用强制类型转换,使操作数均为有符号数或者无符号数,这样就不必由编译器来选择结果的类型。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容

  • 注:这是第三遍读《C语言深度解剖》,想想好像自从大学开始就没读完过几本书,其中谭浩强的那本《C语言程序设计(第四版...
    HavenXie阅读 1,723评论 1 6
  • C++入门基础 namespace专题讲座 namespace概念 所谓namespace,是指标识符的各种可见范...
    蔡俊宇阅读 785评论 0 2
  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,368评论 8 265
  • 骄阳似火,连同风也变得灼热。早上趁着日头还没烤热大地,顶着露湿去田地里除草、打岔。 十点左右回到家,开门进到院子里...
    喻青杨阅读 137评论 0 0
  • 1.晚上又历史重演了,觉察到情绪立马零极限调频。谢谢 2.今天发的图片还有文案朋友圈有很多人点赞.谢谢 3.今天有...
    小华华Diana阅读 156评论 0 1