1. 没C++那么恶心的const

C语言中的const修饰符用于修饰一个变量是const属性的。被C语言的const修饰的变量具有只读属性,并且不能被修改。

const修饰的变量 != 常量,const修饰的变量虽然不能别修改,但是和常量还是有本质的区别的。

在定义const类型的变量的时候,必须进行初始化,当然,在const作为函数的参数的时候,是不需要初始化的。

1.1编译器对const变量的优化:

编译器通常不为普通const 只读变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。

const 定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的只读变量在程序运行过程中只有一份拷贝(因为它是全局的只读变量,存放在静态区),而#define定义的宏常量在内存中有若干个拷贝。#define宏是在预编译阶段进行替换,而const修饰的只读变量是在编译的时候确定其值。#define宏没有类型,而const修饰的只读变量具有特定的类型。

1.2当typedef碰到变量修饰符(const)

typedef struct student
{
/*code*/
}Stu_st,*Stu_pst; )const Stu_pst stu3;
)Stu_pst const stu4;

对于定义的stu3 和stu4,它们的类型一样吗?答案是一样的。为什么?

在这里我们不能想当然的认为typedef和#define一样,直接进行展开。实际上,因为const修饰的都是变量自身,const对变量进行修饰的时候,不考虑类型,也就是说1)和2)中的typedef类型都被认为是一个类型,而不是被展开。所以上述就相当于是:

const type var
      type const var

也就是说,const修饰的是变量var。

2. 不多见的volatile

volatile 关键字和const 一样是一种类型修饰符,用它修饰的变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

3. 结构体

3.1 柔性数组

柔性数组又称为0长数组(zero-length arrays),这是C99加进去的一个特性。可以这样定义一个柔性数组:

struct line {
int length;
char contents[];
}; struct line *thisline = (struct line *) malloc (sizeof (struct line) + this_length);
thisline->length = this_length;

在ISO C90中,在定义一个类似于柔性数组(在C90标准中还没有柔性数组的概念)的结构体成员的时候,contents[]在定义的时候需要定义成这样:contents[0],其中的0是必须的。

在ISO C99中,可以直接在结构体中定义一个自由数组成员,自由数组的语法如下:

  • 自由数组成员的长度为0,在定义一个数组的个数的时候,[]中的0不被包括。
  • 自由数组成员是不完全类型,所以对结构体使用sizeof操作符时不会包括自由数组成员的大小
  • 在一个自由数组前必须定义至少一个成员,不能在一个结构体中只定义一个自由数组。
  • 一个结构体如果包含了一个自由数组,或者在一个联合中包含了这种结构体,那么这种结构体或者联合不能成为结构体的成员或者是一个数组的成员。

关于GCC对柔性数组的支持,可以访问这个网站:http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html#Zero-Length

4. 在解析表达式时的贪心法则

对于这样一个表达式:

a+++b

到底表示的是什么呢?是a+ (++b)还是(a++) +b?这个就需要考虑C语言在语法分析的时候是以什么方式解析的。

在C语言的编译器进行语法分析的时候,使用的是贪心法则。也就是说在处理表达式的时候,如果当前的字符可以和前一个字符串组成一个有意义的符号,则继续读入下一个字符,直到无法组成一个有意义的字符。

也就说对于上述的表达式,在解析到a+后碰到了+,这个时候,由于a++在C语言中是合法的,那么它继续处理下一个+,由于a+++在C语言中是非法的,那么就不把+作为表达式的一部分,也就说上述的表达式就被解析为:(a++) + b。

5. 预处理

在编译的时候可以使用的一些指令,用于在编译的时候输出一些有用的信息,便于追踪编译过程,以及控制编译。

#line    //改变当前的行数和文件名称,基本语法如下:#line number["filename"]

#error   //编译程序时,如果遇到#error就会产生一个编译错误提示信息,并停止编译。

编译器在编译过程预定义了一些宏,用于输出一些编译过程的信息:

_LINE_        //编译器正在编译的行号
_FILE_ //编译器正在变异的文件名
_TIME_ //编译的时间
_STDC_ //判断该文件是不是定义成标准C程序

参考:《C语言深度剖析》

C语言拾遗的更多相关文章

  1. C语言拾遗——strtok

    C语言拾遗——strtok 今天刷PAT的时候用到了这个strtok函数,顺手就记录一下 strtok函数包含于头文件string.h 语法:char *strtok( char *str1, con ...

  2. C语言拾遗(一)

    越来越体会到C语言的重要性,不管是在计算机底层的理解上,还是在算法数据结构上,所以遂决定重新拾起C语言,不定期更新一些知识点. 推荐博客:http://blog.csdn.net/itcastcpp ...

  3. C语言拾遗--static

    C程序一直由下列部分组成: 正文段——CPU执行的机器指令部分:一个程序只有一个副本:只读,防止程序由于意外事故而修改自身指令: 初始化数据段(数据段)——在程序中所有赋了初值的全局变量,存放在这里. ...

  4. C语言拾遗——inttypes.h

    今天偶然间看到这个头文件inttypes,好奇有什么用,去找度娘玩了一波,发现这头文件挺有意思的. 这个头文件适配于C99标准,它提供整数输入的各种进制转换的宏,这是在Ubuntu上扣下来的代码(wi ...

  5. C语言拾遗——sscanf

    今天写题用到了sscanf,怕忘赶紧记录一下 去百度了一下这玩意的函数原型好像是长这样的,微软上扣下来的  int sscanf( const char *buffer, const char *fo ...

  6. c语言,数据类型转换

    在执行算术运算时,计算机比C语言的限制更多.为了让计算机执行算术运算,通常要求操作数有相同的大小(即位的数量相同),并且要求存储的方式也相同.计算机可能可以直接将两个16位整数相加,但是不能直接将16 ...

  7. Go语言核心36讲(导读)--学习笔记

    目录 开篇词 | 跟着学,你也能成为Go语言高手 导读 | 写给0基础入门的Go语言学习者 导读 | 学习专栏的正确姿势 开篇词 | 跟着学,你也能成为Go语言高手 Go 语言是由 Google 出品 ...

  8. iOS-C基础

    iOS开发系列--C语言之基础知识 概览 当前移动开发的趋势已经势不可挡,这个系列希望浅谈一下个人对IOS开发的一些见解,这个IOS系列计划从几个角度去说IOS开发: C语言 OC基础 IOS开发(i ...

  9. 自学导航页(待续ing)

    1 博客导航1.1 linuxlinux全线教程–提供了linux教程,服务器管理教程,BSD教程,还有编程语言(C/Java/Python/Perl),以及网络等全栈学习教程 1.2 存储技术NoS ...

随机推荐

  1. 项目导入myeclipse10后jsp报错问题

    电脑重装系统装了个myeclipse10,当项目导入时发现jsp报错,原本以为是jdk版本问题,在网上找了资料才知道原来是myeclipse10相对之前版本对js的检查更加严格了.可以用以下方法解决: ...

  2. Angular js 之一些简单的js操作

    1.<div ng-if()> </div> 括号里面是布尔值  如果是false那么你ng-if的那个dom就会不显示.(感觉这是angular js中最给力的一点) 一般会 ...

  3. 浅谈对ionic项目的理解

    在思考怎么将客户端app连接到服务器的时候,就在想ionic项目的本质是什么,一开始因为ionic serve这一命令,我以为它自己就是个服务器,但是后来一细想又感觉不是这样,不然客户端又该怎么和服务 ...

  4. UnityContainer 实现DI

    DI(依赖注入) 的方式有很多种: 接口注入,属性注入,构造注入等.DI主要是为了实现代码的松耦合,方便代码的维护和扩展.(其实都是扯淡). 来说说我为啥要使用DI吧.公司有个项目,需要我一个人完成( ...

  5. BOOL和bool的区别

    一. 1.类型不同 BOOL为int型 bool为布尔型 2.长度不同 bool只有一个字节 BOOL长度视实际环境来定,一般可认为是4个字节 3.取值不同 bool取值false和true,是0和1 ...

  6. RHEL6 --部署phpMyAdmin与论坛系统

    一.rpm安装LAMP平台部署phpMyAdmin 二.搭建wordpress个人博客系统 三.搭建论坛系统 一.rpm安装LAMP平台及部署phpMyAdmin 1.phpMyAdmin简介及获取方 ...

  7. mac 下配置tomcat

    下面就是一些简单的步骤,帮你把Tomcat7安装在你的Mac上. 下载一个 二进制包: apache-tomcat-7.0.27.tar.gz ,可以在Apache的官方网站找到. 双击解压在你的下载 ...

  8. 添加网络打印机的步骤(xp和win2008)

    1.如题,设置好打印机去的ip地址和子网掩码等信息. 2 .xp不像其他新的系统那么好用那么智能...只能慢慢来 如果是xp,注意,请添加网络打印机的时候选  :添加本地打印机,,记得哦 然后如图 然 ...

  9. array_filter函数

    利用array_filter函数轻松去掉多维空值,而数组的下标没有改变, 如果自定义过滤函数返回 true,则被操作的数组的当前值就会被包含在返回的结果数组中, 并将结果组成一个新的数组.如果原数组是 ...

  10. xmlrpc实现bugzilla api调用(无会话保持功能,单一接口请求)

    xmlrpc实现bugzilla4   xmlrpc api调用(无会话保持功能,单一接口请求),如需会话保持,请参考我的另外一篇随笔(bugzilla4的xmlrpc接口api调用实现分享: xml ...