首页 > 编程语言 >C语言——程序环境和预处理

C语言——程序环境和预处理

时间:2022-11-09 11:01:36浏览次数:49  
标签:__ int 程序 C语言 编译 printf main 预处理 define

  • 程序的翻译环境和执行环境
  • 编译+链接
  • 预处理


一.程序的翻译环境和执行环境

ANSI C标准的任何一种实现中,存在两种不同的环境:

  1. 翻译环境:该环境中 源代码 会被转换为 可执行的机器指令
  2.  执行环境:其用于实际 执行代码

C语言——程序环境和预处理_#include

二.编译+链接

2.1翻译环境

C语言——程序环境和预处理_预处理_02

  • 一个源文件经过编译器处理形成一个目标文件,目标文件被链接器链接形成可执行程序
  • 翻译环境是 编译 和 链接

2.2翻译环境的几个阶段

C语言——程序环境和预处理_预处理_03


2.3运行环境

程序执行的过程:

  1. 程序必须载入内存中。

           在有操作系统的环境中:程序的载入一般由操作系统完成。

           在独立环境中:程序的载入必须手工安排,也可能是通过可执行代码置入只读内存来完成。

2.程序的执行便开始。接着便调用 main 函数。

3.开始执行程序代码,这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(staic)内存,存储于静态内存中的变量在程序整个执行过程中一直保留它们的值。

4.终止程序。正常终止main函数,也可能是意外终止

三.预处理

3.1预定义符号

  • 在预处理阶段被处理的已经定义好的符号,可以拿来直接用

   __FILE__       // 代码所在的  源文件,路径
__LINE__ // 代码所在的 行号
__DATE__ // 程序被编译的 日期
__TIME__ // 程序被编译的 时间
__FUNCTION__ // 代码所在函数的 函数名

  • 左下和右下都是2个下划线

C语言——程序环境和预处理_#include_04

  • 如果一个工程特别复杂,这时去调试时可能会无从下手。所以需要代码在运行的过程中记录一些日志信息,即可通过日志信息看程序哪里出了问题

例子:

#include <stdio.h> 
int main()
{
int i = 0;
FILE* pf = fopen("acc.txt", "a+");
if (pf == NULL)
{
perror("fopen\n");
return 1;
}
for (i = 0; i < 10; i++)
{
fprintf(pf,"%s %d %s %d\n",__FILE__, __LINE__, __DATE__,__TIME__ );
}
fclose(pf);
pf = NULL;
return 0;
}

C语言——程序环境和预处理_预处理_05

  • 除以上5个外,还有一个 __STDC__,如果编译器遵循 ANSI C 标准则返回1,否则未定义

C语言——程序环境和预处理_#include_06

在Dev-c++上有1,表明其遵循 ANSI C 标准

3.2#define

3.2.1 #define 定义标识符

语法:​

#define name  stuff

//例子:
//#define MAX 100
//#define reg register

注意:#define 定义标识符 ,其末尾不用再加个分号

例子:

#include <stdio.h> 
#define M 100
//预处理阶段就会将M替换成100
int main()
{
int m = M;
printf("%d\n",m);
return 0;
}
//100

3.2.2  #define 定义宏

  • #define 机制有个规定,允许把参数替换到文本中,这种实现成为宏或定义宏

申明方式:

#define name( parament-list ) stuff

//name和左括号必须紧紧在一起,否则后面的参数会被当成stuff的一部分

举例:

#include <stdio.h>

#define SQUARE(X) X*X
int main()
{
printf("%d\n", SQUARE(3));//实现后为 printf("%d\n", 3*3);
return 0;
}
//9

// 先将函数中name()中的参数替换 掉宏中的参数,再将stuff的结果返回函数去 替换掉name()

特别注意:宏的参数是完全替换的,不事先计算再传参

例子:用类似上述方法得出16


#include <stdio.h>

#define SQUARE(X) X*X
int main()
{
printf("%d\n", SQUARE(3+1));
//实现后为 printf("%d\n", 3+1*3+1);
return 0;
}
//7

//这样明显不对,So在敲的时候我们可以带上()来防止出错

#include <stdio.h>

#define SQUARE(X) (X)*(X)
int main()
{
printf("%d\n", SQUARE(3+1));
return 0;
}
//16

注意下面这种情况:

#include <stdio.h>

#define SQUARE(X) (X)+(X)
int main()
{
printf("%d\n", 10 * SQUARE(4));

return 0;
}
// 实现后是 printf("%d\n", 10 * (4) + (4));
//所以结果是44

3.2.3  #define 替换规则

在程序中扩展#define定义符号和宏时,几个步骤:

  1. 在调用宏时,首先对参数进行检查,看是否包含任何由 #define 定义的符号。如果是,它们先被替换
  2. 替换文本随后被插入到程序中原来的文本位置。对于宏,函数名被它们的值替换
  3. 再次对结果文件进行扫描,看是否包含任何由 #define 定义的符号。如果包含,就重复上述过程。

注意:

  1.  宏参数 和 #define 定义中可以出现其他 #define 定义的常量。但对于宏,不能出现递归
  2. 当预处理器 搜索 #define 定义的符号的时候,字符串常量中的内容不被搜索,即不会被替换
#include <stdio.h>

#define M 100
int main()
{
printf("M = %d\n", M);//前面的M不会被替换
return 0;
}
//100

3.3命名约定

由于一般来讲,函数和宏的使用语法相似,所以为了区分它们,用一个习惯是:宏名全部大写,函数名不要全部大写

3.4#undef

该命令用于 移除一个宏定义

语法格式:

#undef NAME

例子:

#include <stdio.h>

#define M 100
int main()
{
int a = M;
#undef M
printf("%d\n", M);

return 0;
}

3.5 条件编译

在编译一个程序时,可以用条件编译将一条语句或一组语句编译/放弃是很方便的

#include <stdio.h>

#define __DEBUG__
int main()
{
int arr[10] = {0};
int i = 0;
for (i = 0; i < 10; i++)
{
arr[i] = i;
#ifdef __DEBUG__
printf("%d ", arr[i]);//如果定义了则会编译 ,没有定义则不会参与编译
#endif
}
return 0;
}

//如果定义了则会编译 ,没有定义则不会参与编译






标签:__,int,程序,C语言,编译,printf,main,预处理,define
From: https://blog.51cto.com/u_15722538/5835127

相关文章

  • 05 uniapp/微信小程序 项目day05
    ​一.登录与支付1.1登录1.1.1条件判断当我们点击结算应当进行条件判断第一个如果没有勾选商品第二个是没选择地址第三个是未登录1.1.2页面布局应该有两个页......
  • uniapp-uview 微信小程序form中自定义校验规则失效问题。
    uniapp-uview微信小程序form中自定义校验规则失效问题。仔细阅读官方文档,发现有提示。需要兼容微信小程序,并且校验规则中含有方法等,只能通过setRules方法设置规则。如......
  • 微信共享停车场小程序开发设计方案
    随着城市的发展,人们的生活水平提高,车辆的增多,在有限的城市空间中,停车难成为了人们经常遇到的问题,附近找不到停车位置的情况时有发生,为了更好的解决这一问题,可以通过共享停车......
  • 第四十一章 构建数据库应用程序 - 带有CSP Search标签的CSP搜索页面
    第四十一章构建数据库应用程序-带有<CSP:Search>标签的CSP搜索页面search标记创建一个通用搜索页面,可以将其与绑定表单一起使用以执行查找操作。应用程序用户可以从......
  • 计算机等级考试二级C语言模拟试卷(四)
    一、选择题(每小题1分,共40分)   (1)下列关于栈叙述正确的是A)栈顶元素最先能被删除                 B)栈顶元素最后才能被删除C)......
  • Day01-3 第一个程序:HelloWorld
    HelloWorld随便新建一个文件夹,存放代码新建一个Java文件文件后缀名为,javaHello.java【注意点】系统可能没有显示文件后缀名,我们需要手动打开编写代......
  • 用 Gearman 分发 PHP 应用程序的工作负载
    尽管一个Web应用程序的大部分内容都与表示有关,但它的价值与竞争优势却可能体现在若干专有服务或算法方面。如果这类处理过于复杂或拖沓,最好是进行异步执行,以免Web服务......
  • C语言选择结构的执行条件
    在C语言中,有些细节常常被忽略:选择结构的执行条件我们知道,if()和elseif()是判断程序是否执行的函数。需要注意的是,这两个函数判断的是括号内的值是逻辑真(true)还是逻辑......
  • C语言的自增自减运算符
    简单去理解,C语言的自增自减运算符的最终结果就是对自身进行加一和减一操作。但是当++、--作为后缀时则具有延后性,可能对程序有一些副作用,并且其的优先级也会对程序产生一......
  • C语言逻辑运算符
    在C语言中,逻辑运算符有&&、||、!&&表示“与”的意思,需要两端的表达式的值都为true,该式的值才为true。||表示“或”的意思,两端的表达式的值只要有一端为true,该式的值就为t......