【编程基础】聊聊C语言-兵马未动粮草先行(1)

上一篇我们讲的聊聊C语言-我的地盘我做主,相信大家对变量的存储类型和变量的作用域有了一定的了解。现在我们马上公布上期的答案如下:

#include<stdio.h>

int a=1;//存储在程序的数据段

int b;//存储在程序的bss段

int main(void)

{

auto int a=2;//存储在栈中

static int c=2;//存储在数据段

{

int c=3;//存储在栈中

int b=4;//存储在栈中

}

printf("a=%d b=%d c=%d\n",a,b,c);

return0;

}

打印输出为:a=2 b=0 c=2

亲们不知道做对没有?呵呵

接下来进入我们这篇的主题-聊聊C语言中预处理功能中的宏定义。

C代码如何变成可执行程序?

一般来说一段代码变成一个可以运行的程序是需要编译器进行处理的,而编译器对C语言的处理的过程包括四个:预处理-> 编译->汇编->链接。经过这四个步骤你的代码就可以变成可执行文件。预处理主要是对宏定义,文件包含,条件编译进行处理;编译是把汇编语言编译成汇编文件;汇编是把生成的汇编代码汇编成目标文件;链接是把我们的目标文件链接成一个可执行文件。编译器对于宏的处理是放在第一阶段的,可见它的重要性。

什么是宏?

一般说来,宏是一种规则或模式或称语法替换 ,用于说明某一特定输入(通常是字符串)如何根据预定义的规则转换成对应的输出(通常也是字符串)。这种替换在预编译时进行,称作宏展开。C语言的宏预处理器的工作只是简单的文本搜索和替换。

C语言怎么定义宏?

在C语言中定义宏我们用的关键字是#define

C语言中宏定义的分类

  • 不带参数的宏定义 格式:#define 标识符 字符串 其中的标识符就是所谓的符号常量,也称为“宏名”。 如:#define PI 3.1415926
  • 带参数的宏定义 格式:#define宏名(参数表)字符串 如:#define S(a,b) a*b

C语言中宏定义需要注意的问题

  1. 宏名一般用大写
  2. 预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。
  3. 宏定义末尾不加分号;
  4. 宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。
  5. 可以用#undef命令终止宏定义的作用域
  6. 宏定义可以嵌套
  7. 字符串""中永远不包含宏
  8. 宏定义不分配内存,变量定义分配内存。
  9. 宏名和参数的括号间不能有空格
  10. 宏替换只作替换,不做计算,不做表达式求解
  11. 函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存
  12. 宏定义不存在类型,也没有类型转换。
  13. 宏展开使源程序变长,函数调用不会
  14. 宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)

C语言中宏的使用

  • 用无参宏定义一个简单的常量 例:#define LEN 20
  • 带参宏一般用法 例:#define MAX(a,b)((a)>(b)?(a):(b))
  • 有参宏定义中#的用法 #用于把宏定义中的参数两端加上字符串的"" 如:#define STR(str) #str 那么STR(coder_online)会被替换成"coderonline"
  • 有参宏定义中##的用法 ##用于将字符链接起来 如:如果有#define FUN(a,b) co##on##b 那么FUN(der,line)会被替换成coderonline
  • 多行宏定义 用"\"链接多行 如:#define NAME coder \ _online

我们的宏定义就讲到这里,大家有什么不明白的或者有什么意见可以关注下面的微信公众号,我们一起在线讨论。下面是针对这篇小编为留的练习题,请实现如下宏答案会在下一篇公布:

  1. 用宏定义一个字符串常量
  2. 用带参数的宏实现求两个数的最小值
  3. 用带##的宏实现两个字符串的链接

原文发布于微信公众号 - 程序员互动联盟(coder_online)

原文发表时间:2015-07-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏肖洒的博客

前端入门学习--JavaScript

大概了解了HTML和CSS,到了前端的精华JavaScript。 学习笔记,ALL FROM 廖雪峰的官方网站

642
来自专栏人工智能LeadAI

共享变量 tensorflow解读

你可以在怎么使用变量中所描述的方式来创建,初始化,保存及加载单一的变量.但是当创建复杂的模块时,通常你需要共享大量变量集并且如果你还想在同一个地方初始化这所有的...

1022
来自专栏地方网络工作室的专栏

GO语言学习笔记(一)一些基础常识以及实现生成随机密码小程序

GO语言学习笔记(一)一些基础常识以及实现生成随机密码小程序 之前用 nodejs 和 shell 分别实现过生成随机密码的小程序。最近,准备入门一下 gola...

1696
来自专栏sunseekers

初探 TypeScript函数基本类型泛型接口类内置对象

前段时间有朋友和我推荐 TypeScript ,他说写起来特别爽,让我去试一试,那时候我还在那是啥高深莫测的东西。刚好那段时间忙,一直没有时间看。最近也很忙,还...

432
来自专栏SeanCheney的专栏

Python基础回顾基本数据类型和运算容器分支和循环函数、生成器和类map, reduce和filter列表生成(list comprehension)字符串文件操作和pickle异常多进程(mult

Python shell输入import this 可以看到The Zen of Python 基本数据类型和运算 基本数据类型 Python中最基本的数据类...

3837
来自专栏Google Dart

Dart语言指南(一) 顶

此文着重展示如何使用Dart语言的每一个主要功能,从变量和操作符到类和库,假设您已经知道如何用另一种编程语言。

812
来自专栏calmound

javascript闭包

## 定义 **闭包:**有权访问另一个函数作用域中的变量的函数。 ## 解析 相信刚看到这个定义,很多人肯定很迷糊,现在给出示例。 ``` function ...

2567
来自专栏向治洪

数据结构之堆和栈

内存分配策略     按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的.  静态存储分配是指在编译时就能确定每个数据目标...

1889
来自专栏Java3y

HashMap就是这么简单【源码剖析】

1653
来自专栏PHP技术

12个非常实用的JavaScript小技巧

在这篇文章中将给大家分享12个有关于JavaScript的小技巧。这些小技巧可能在你的实际工作中或许能帮助你解决一些问题。 使用!!操作符转换布尔值 有时候我们...

3428

扫码关注云+社区