IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 程序的环境和预处理 -> 正文阅读

[C++知识库]程序的环境和预处理

(一)程序的翻译环境

(二)程序的执行环境

(三)预定义符号的介绍

(四)预处理指令#define

(五)预处理操作符#和##的介绍

(六)条件编译

(一)翻译环境:源代码被转换为可执行的机器指令 (二进制)??

   编译? +?链接? ? ? ? ? ? ? ? ? ? ? ?  运行
?text.c——————翻译环境—-------——————>text.exe-——运行环境————>

 文本文件? ? ? ? ? ? ? ? ? ? ? ? ? ? ?二进制文件

(源文件 源程序)? ? ? ? ? ? ? ? ? ? (可执行程序)
源文件1(.c)? ? ? ? ? ? ? 经过编译器生成目标文件1(.obj)
源文件2目标文件2
源文件3目标文件3
链接库链接器(目标文件通过链接器生成可执行程序(.exe))

?(1)组成一个程序的每个源文件通过编译过程分别转换为目标文件

?(2)每个目标文件由链接器捆绑在一起,形成一个单一而完整的可执行程序

(3)链接器同时也会引入标准c函数库中任何被该程序所用到的函数,而且它可以搜索个人的程序库,将所需要的函数也链接到程序中去。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? test.c? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? text.exe

? ? ? ? ? ? ?翻译环境? ? ? ? ? ? ? ? ? 运行环境
?编译? ? ? ? ? ? ? ? ? ? ? 链接? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?目标文件

?编译又可以分为三个阶段

预编译编译汇编

预编译:(文本操作)

? ? ?(1)在linux环境下: 如果输入gcc.-E text.c? 进行预编译///预处理

? ? ?(2)?#include头文件的包含在预编译系统就进去了

? ? ?(3)预编译的时候删除注释(使用空格来替换注释)

? ? ?(4) 预处理阶段也会完成#define

?编译:把c代码翻译为汇编代码?

语法分析? ? ? ? ?词法分析? ? ? ? 语义分析? ? ? ? ?符号汇总(函数名,全局变量)

? 汇编:形成符号表

? 链接:

? ? ? 1.合并段表

? ? ? 2.符号表达的合并和重定位

?合并段表:生成的目标文件(.o)有固定格式(elf),会生成好几个段,但放的内容不一样,需要将它们合并,exe的文件格式也是(elf)

? ? ? ?符号表:

? ? ? ??

add0x000
main0x200

? ? ???

add? ox100

? ? ? ? ?合并之后

addox100
main0x200

?(二)运行环境

1.程序必须要载入内存中,在有操作系统的环境中,这个一般由操作系统完成。在独立的环境中,程序的载入必须要手工安排,也可能是通过可执行代码置入只读内存中完成

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

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

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

(三)预定义符号

? _FILE_:这个对应的文件名

?_LINE_:对应的行号

? _DATE_:当前日期

? _TIME_:当前时间

? _STDC_:如果编译器遵循ANSIC,其值为1,否则未定义

#include<stdio.h>
int main()
{
  printf("%s",_FILE_);
  printf("%d",_LINE_);
}
#include<stdio.h>//编写日志
int main()
{
  int i;
  int arr[10]={10};
  FILE*pf=fopen("log.txt","w");
  for(i=0;i<10;i++)
   {
    arr[i]=i;
    fprintf(pf,"file:%s line:%d date:%s i=%d",
              _FILE_,_LINE_,_DATE_,_TIME_,i);
  }
  fclose()
  for(i=0;i<10;i++)
  {
   printf("%d",arr[i]);
  }
}
    

?(四)预处理指令

#define? ? ? ?#include? ? ?#pragma pack[4]? ? ?#pragma? ? #if? ? #endif? ? ?#itdef? ?#line

?#define:可以定义宏和标识符

?#define? reg register;//为register这个关键字创建一个简短的名字

?#define MAX 1000;

#define? CASE break;case//在case造句的时候自动把break写上

#define do_forever for(::) //用更形象的语言替换一种实现(死循环)

#define do_forever for(;;)
int main()
{
   for(;;)

     死循环的内容

           ;
   return 0;
}

#define包含了一个规定,允许把参数替换到文本中。这种实现称为定义宏。宏不可以递归。字符串中内容并不会被替换。

#define square(x) x*x
int main()
{
  int ret=square(5+1);
  return 0;
}//红的参数是替换的而不是传参的  5+1*5+1=11

#define square(x) (x)*(x)
int main()
{
  int ret=square(5+1);
  return 0;
}//(5+1)*(5+1)=36//写宏的时候不要吝啬括号

(五)#和##的区别?

? ?把参数插入字符串。#x会把内容变成”a"

#define CAT(X,Y) X##Y
int main()
{
 int class84=2020;
 printf("%d",CAT(class,84));
//等价于printf("%d",class84);
//##可以把位于它俩边的符号合成一个符号,它允许宏定义从分离的文本片段创建标识符
}
printf("woai");==printf("wo""ai");//俩个字符串会自动连在一起。

#define print(x) printf("the value of"#x"is %d\n",x)

int main()
{
  int a=10;
  int b=20;
  print(a);
  print(b);
}
//带有副作用的宏
#include<stdio.h>
#define MAX(X,Y) (X)>(Y)?(X):(Y)

int main()
{
 int a=10;
 int b=11;

 int max=MAX(a++,b++);
 //int max=(a++)>(b++)?(a++):(b++);
 
 printf("%d%d%d",max,a,b);//12 11 13
}

函数调用的时候会有函数返回和调用的开销,宏在预处理阶段就完成了替换,没有函数的调用和返回的开销。 宏与类型无关,而函数必须声明类型。但是,每次使用宏的时候,一份宏的代码插入到程序中,会增加程序的长度。并且宏没办法调试,宏与类型无关则不够严谨。宏会带来运算的优先级问题容易出错。

#define MALLOC(num,type) (type*)malloc(num*sizeof(type))
int main()
{
 int *p=MALLOC(10,int);
}

#undef:移除一个宏定义?

(六)条件编译

{#ifdef debug;//如果debug被定义过下面的句子参与编译 定义在上面用#define
 //#ifdef defined(debug)
  printf("%d",a);
#endif}
#if 常量表达式//表达式为真则编译
      //...
#endif



#if 常量表达式
  //
#elif 常量表达式
  //
#else 常量表达式
  //
#endif


#ifndef debug==#ifdef !debug

NOTE:

防止头文件被重复包含,在头文件前面写

#ifndef _test_h
#define _test_h
//头文件的内容
#endif

或者#pragma once

?

?

?

?

? ? ? ? ? ??

? ? ? ? ? ?

? ? ? ? ? ? ?

? ?

? ? ??

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-07 11:51:13  更:2021-12-07 11:51:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:45:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码