网易云课堂_C语言程序设计进阶_第6周:程序结构
6.1 全局变量
6.2 编译预处理
6.3 大程序结构
6.1 全局变量
全局变量
定义在函数外面的变量是全局变量
全局变量具有全局的生存期和作用域
它们与任何函数都无关
在任何函数内部都可以使用它们
全局变量初始化
没有做初始化的全局变量会得到0值
指针会得到NULL值
只能用编译时刻已知的值来初始化全局变量
它们的初始化发生在main函数之前
被隐藏的全局变量
如果函数内部存在与全局变量同名的变量,则全局变量被隐藏
静态本地变量
在本地变量定义时加上static修饰符就成为静态本地变量
当函数离开的时候,静态本地变量会继续存在并保持其值
静态本地变量的初始化只会在第一次进入这个函数时做,以后进入函数时会保持上次离开时的值
静态本地变量
静态本地变量实际上是特殊的全局变量
它们位于相同的内存区域
静态本地变量具有全局的生存期,函数内的局部作用域
static在这里的意思是局部作用域(本地可访问)
返回指针的函数
返回本地变量的指针式危险的
返回全局变量或静态本地变量的地址是安全的
返回在函数内malloc的内存是安全的,但是容易造成问题
最好的做法是返回传入的指针
tips
不要使用全局变量来在函数间传递参数和结果
尽量避免使用全局变量
使用全局变量和静态本地变量的函数是线程不安全的
6.2 编译预处理
#开头的是编译预处理指令
它们不是C语言的成分,但是C语言程序离不开它们
#define用来定义一个宏
#define
#define<名字><值>
注意没有结尾的分号,因为不是C的语言
名字必须是一个单词,值可以是各种东西
在C语言的编译器开始编译之前,编译预处理程序(cpp)会把程序中的名字换成值
完全的文本替换
gcc--save-temps
宏
如果一个宏的值中有其他的宏的名字,也是会被替换的
如果一个宏的值超过一行,最后一行之前的行末需要加\
宏的值后面出现的注释不会被当作宏的值的一部分
#include <stdio.h>
#include <stdlib.h> #define PI2 2*PI
#define PI 3.14159 void main()
{
printf("%lf\n", PI); printf("%lf\n", PI2); system("pause");
}
没有值的宏
#define _DEBUG
这类宏是用于条件编译的,后面有其他的编译预处理指令来检查这个宏是否已经被定义过了
预定义的宏
__LINE__
在源代码中插入当前源代码行号
__FILE__
在源代码中插入当前源代码文件名
__DATA__
在源代码中插入当前编译日期〔注意和当前系统日期区别开来〕
__TIME__
在源代码中插入当前编译时间〔注意和当前系统时间区别开来〕
__STDC__
当要求程序严格遵循ANSIC标准时该标识符被赋值为1
#include <stdio.h>
#include <stdlib.h> void main()
{
printf("%s:%d\n", __FILE__, __LINE__); printf("%s,%s\n", __DATE__, __TIME__); system("pause");
}
像函数的宏
#define cube(x) ((x)*(x)*(x))
宏可以带参数
错误定义的宏
#define RADTODEG(x) (x*57.29578)
#define RADTODEG(x) (x)*57.29578
#include <stdio.h>
#include <stdlib.h> #define RADTODEG1(x) (x*57.29578) #define RADTODEG2(x) (x)*57.29578 void main()
{
printf("%lf\n", RADTODEG1( + )); printf("%lf\n", RADTODEG2( + )); system("pause");
}
带参数的宏的原则
一切都要括号
整个值要括号
参数出现的每个地方都要括号
#define RADTODEG(x) ((x)*57.29578)
带参数的宏
可以带多个参数
#define MIN(a,b) ((a)>(b)?(b):(a))
也可以组合(嵌套)使用其他宏
分号?
结尾不要加上分号;
带参数的宏
在大型程序的代码中使用非常普遍
可以非常复杂,如“产生”函数
在#和##这两个运算符的帮助下
存在中西方文化差异
部分宏会被inline函数替代
其他编译预处理指令
条件编译
error
6.3 大程序结构
多个.c文件
main()里的代码太长了适合分成几个函数
一个源代码文件太长了适合分成几个文件
两个独立的源代码文件不能编译形成可执行的程序
编译单元
一个.c文件是一个编译单元
编译器每次编译只处理一个编译单元
头文件
把函数原型放到一个头文件(以.h结尾)中,在需要调用这个函数的源代码文件(.c文件)中#include这个头文件,就能让编译器在编译的时候知道函数的原型
#include
#include是一个编译预处理指令。和宏一样,在编译之前就处理了
它把那个文件的全部文本内容原封不动地插入到它所在的地方
所以也不是一定要在.c文件的最前面#include
""还是<>
#include有两种形式来指出要插入的文件
""要求编译器首先在当前目录(.c文件所在的目录)寻找这个文件,如果没有,到编译器指定的目录去找
<>让编译器只在指定的目录去找
编译器自己知道自己的标准库的头文件在哪里
环境变量和编译器命令行参数也可以指定寻找头文件的目录
#include的误区
#include不是用来引入库的
stdio.h里只有printf的原型,printf的代码在另外的地方,某个.lib(Windows)或.a(Unix)中
现在的C语言编译器默认会引入所有的标准库
#include <stdio.h>只是为了让编译器知道printf函数的原型,保证你调用时给的参数值是正确的类型
头文件
在使用和定义这个函数的地方都应该#include这个头文件
一般的做法就是任何.c都有对应的同名.h,把所有的对外公开的函数原型和全局变量的声明都放进去
不对外公开的函数
在函数前面加上static就使得它成为只能在所在的编译单元中被使用的函数
在全局变量前面加上static就使得它成为只能在所在的编译单元中被使用的全局变量
变量的声明
int i;是变量的定义
extern int i;是变量的声明
声明和定义
声明是不产生代码的东西
函数原型
变量声明
结构声明
宏声明
枚举声明
类型声明
inline声明
定义是产生代码的东西
头文件
只有声明可以被放在头文件中
是规则不是法律
否则会造成一个项目中多个编译单元里有重名的实体
某些编译器允许几个编译单元中存在同名的函数,或者用weak修饰符来强调这种存在
重复声明
同一个编译单元里,同名的结构不能被重复声明
如果你的头文件里有结构的声明,很难这个头文件不会在一个编译单元里被#include多次
所以需要“标准头文件结构”
标准头文件结构
#ifndef __LIST_HEAD__
#define __LIST_HEAD__ #include "node.h" typedef struct _list
{
Node *head;
Node *tail;
}List; #endif // !
运用条件编译和宏,保证这个头文件在一个编译单元中只会被#include一次
#pragma once也能起到相同的作用,但是不是所有的编译器都支持
网易云课堂_C语言程序设计进阶_第6周:程序结构的更多相关文章
- 网易云课堂_C语言程序设计进阶_第三周:结构:结构、类型定义、联合
3.1 枚举 3.2 结构 3.3 类型定义 3.1 枚举 枚举是一种用户定义的数据类型,它用关键字enum以如下语法来表明: enum 枚举类型名字{名字0,...,名字n}; 枚举类型名字通常并不 ...
- 网易云课堂_C语言程序设计进阶_第8周:图形交互程序
8.2函数指针 8.2函数指针 #include <stdio.h> #include <stdlib.h> void f(int i) { printf("void ...
- 网易云课堂_C语言程序设计进阶_第七周:文件:文件访问、格式化输入输出、二进制输入输出
7.1文件 7.2底层操作 7.1文件 格式化的输入输出 printf %[flags][width][.prec][hIL]type Flag 含义 - 左对齐 + 在前面放+或- (space) ...
- 网易云课堂_C语言程序设计进阶_第5周:链表_1逆序输出的数列
1 逆序输出的数列(10分) 题目内容: 你的程序会读入一系列的正整数,预先不知道正整数的数量,一旦读到-1,就表示输入结束.然后,按照和输入相反的顺序输出所读到的数字,不包括最后标识结束的-1. 输 ...
- 网易云课堂_C语言程序设计进阶_第5周:链表
5.1可变数组 5.2链表 5.1可变数组 Resizable Array Think about a set of functions that provide a mechanism of res ...
- 网易云课堂_C语言程序设计进阶_期末考试编程题部分
1 字符串循环右移(5分) 题目内容: 输入一个字符串和一个非负整数N,要求将字符串循环右移N次. 输入格式: 输入在第1行中给出一个字符串,以'#'表示结束,‘#’不是字符串的一部分,字符串的长度未 ...
- 网易云课堂_C语言程序设计进阶_第二周:指针:取地址运算和指针、使用指针、指针与数组、指针与函数、指针与const、指针运算、动态内存分配_2信号报告
2 信号报告(5分) 题目内容: 无线电台的RS制信号报告是由三两个部分组成的: R(Readability) 信号可辨度即清晰度. S(Strength) 信号强度即大小. 其中R位于报告第一 ...
- 网易云课堂_C语言程序设计进阶_第一周:数据类型:整数类型、浮点类型、枚举类型_1计算分数精确值
1 计算分数精确值(10分) 题目内容: 由于计算机内部表达方式的限制,浮点运算都有精度问题,为了得到高精度的计算结果,就需要自己设计实现方法. (0,1)之间的任何浮点数都可以表达为两个正整数的商, ...
- 网易云课堂_C语言程序设计进阶_第四周:ACL图形库
创建ACLLib程序 #include"acllib.h" #include<stdio.h> int Setup1() { initWindow(, );//初始化窗 ...
随机推荐
- td太多内容显示...
table style="table-layout:fixed;"td style="text-overflow: ellipsis;white-space: nowra ...
- IO-03. 求整数均值
/** *A3-IO-03. 求整数均值(10) *C语言实现 *测试已通过 */ #include "stdio.h" int main() { int a,s,d,f; sca ...
- Oracle EBS-SQL (INV-5):检查期间拉式物料领用记录数.sql
select FU.description 操作者, KK.DESCRIPTION ...
- Oracle EBS-SQL (MRP-1):检查期间内计划完成的任务.sql
/*期间内车间任务下达记录数不包含配件任务*/ select WE.DESCRIPTION 任务说 ...
- js数值转换
先来几个题吧: var num1 = Number("123blue");var num2 = Number("");var num3 = Number([]) ...
- SSH25个命令 + 深入SSH端口转发细节
OpenSSH是SSH连接工具的免费版本.telnet,rlogin和ftp用户可能还没意识到他们在互联网上传输的密码是未加密的,但SSH是加密的,OpenSSH加密所有通信(包括密码),有效消除了窃 ...
- Hibernate、批量操作数据
Hibernate 批量操作数据可以使用两种方法实现 1.分批更新,每一小批同步一次数据: public void saveEmployee2(){ Session s=HibernateSessio ...
- jQuery-瀑布流 布局 (处理页面滚动和AJAX加载延迟问题)
瀑布流:这种布局适合于小数据块,每个数据块内容相近且没有侧重.通常,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部. 一.功能分析: 1.判断图片是否进入可视区域: 2.用AJAX ...
- SQL整理1 数据类型
Character 字符串: 数据类型 描述 存储 char(n) 固定长度的字符串.最多 8,000 个字符. N的范围1-8000 varchar(n) 可变长度的字符串.最多 8,000 个字符 ...
- bootstrap-js(5)工具提示tooltip
实例 当您想要描述一个链接的时候,工具提示(Tooltip)就显得非常有用.工具提示(Tooltip)插件是受 Jason Frame 写的 jQuery.tipsy 的启发.工具提示(Tooltip ...