<大厂面试高频考点>程序环境和预处理

简介: <大厂面试高频考点>程序环境和预处理

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


概念介绍:

在ANSI C的任何一种实现中,都会存在两个环境。

1.翻译环境:将源代码转换成可执行的机器指令。(编译器)

2.执行环境: 实际执行代码。(操作系统)

二.详解翻译环境


即:一个源程序文件怎么转化成一个可执行程序的。

流程:多个源文件单独经过编译器处理,再经过链接器链接,最后形成一个可执行程序。

1.编译

(1)预编译(文本操作)

文本操作:文件的替换调用

a.头文件的包含

#include — 预处理指令

b.#define定义符号的替换

#define —预处理指令

c.删除注释

(2)编译(把C语言代码翻译成汇编代码)

a.语法分析

b.词法分析

c.语义分析

d.符号汇总:只汇总全局符号 例如:Add main(链接时会用到)

(3)汇编(汇编指令翻译成二进制指令)

a.形成符号表:每个源文件都是单独编译,都形成自己的符号表(包括引用的外部符号),并带有符号地址,如果是外部符号就赋一个无意义的地址

(4)链接(把多个经过编译的源文件+链接库 链接)

a.合并段表:把不同源文件的相同段进行合并

b.符号表的合并和重定位:把不同源文件形成的符号表合并,使得外部声明的符号得到其真正的地址(所以如果未定义,会在链接的时候报错:无法解析的外部符号)

三.概述运行环境


程序执行的过程

1.程序必须载入内存中。在有操作系统的环境中,载入由操作系统完成。在独立的环境中,载入到内存必须由手工安排。


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


3.开始执行代码。这个时候程序将使用一个运行时堆栈,存储函数的局部变量和返回地址。同时也就可以使用静态内存。


4.终止程序。正常终止main,也可能是异常终止。

四.预处理详解


1.预定义符号

a.__FILE__         进行编译的源文件


b.__LINE__         文件当前的行号


c.__DATE__        文件被编译的日期


d.__TIME__         文件被编译的时间


e.__STDC__        如果编译器遵循ANSI C ,其值为1,否则未定义

2.#define

(1)#define定义标识符

非常灵活,在末尾不要加;会出问题


因为宏定义是直接替换的,所以由于运算符优先级的不同,会导致一些问题。

(2)#define定义的宏

所以我们在进行宏定义的时候,要把变量都加上括号、把宏的整体也加上括号。


注意:宏参数和#define定义中可以出现其他#define定义的符号。但是宏不能递归。


          字符串中出现宏定义符号 不会被替换


          #undef NAME  这条指令用于移除一个宏定义

3.#和##

(1)# 将参数插入到字符串中

铺垫:由于C语言对于字符串的打印有一个会合并的特点。(两个打印出来效果一样)

所以

我们用宏可以实现如下效果:

演示1:

#include<stdio.h>
#define PRINT(N) printf("the value of "#N" is %d\n",N)  //无分号!
int main()
{
  int a = 10;
  PRINT(a);
  int b = 20;
  PRINT(b);
}

演示2:

#include<stdio.h>
#define PRINT(N,format) printf("the value of "#N" is "#format"\n",N)  //无分号!
int main()
{
  int a = 10;
  PRINT(a,%d);
  double b = 3.14;
  PRINT(b,%lf);
}

(2)## 可以把它两边的符号合成一个符号

其允许从分离的片段中创建标识符

演示:

#include<stdio.h>
#define CAT(name,num) name##num
int main()
{
  int class105 = 105;
  printf("%d\n", CAT(class, 105));
}

4.带有副作用的宏参数

b=a+1; 不带副作用

b=a++; 带有副作用 改变了a的值 宏替换是自左向右一步一步替换的,此时a的值已经发生改变

演示:

#include<stdio.h>
#define MAX(x,y) ((x)>(y)?(x):(y))
int main()
{
  int a = 5;
  int b = 8;
  int c = MAX(a++, b++);
  printf("%d %d %d", a, b, c);
}

5.宏和函数的对比

6.命令行定义(在编译的过程中定义符号)

当我们根据同一个源文件编译出不同版本可用命令行定义,例如:可以用来调整数组大小。

7.条件编译

(1)#if

#if 常量表达式  如果为真 进入编译

......


#endif  结束编译


(2)多个分支的条件编译

#if 常量表达式


...


#elif 常量表达式


...


#endif


(3) 判断是否被定义

a.如果定义了 就为真 参与编译


#if defined(NAME)


...


#endif

#ifdef NAME

...

#endif

b.如果没定义  参与编译

#if !defined(NAME)

...

#endif

#ifndef NAME

...

#endif

(4)嵌套指令

与if语句嵌套相同,不过每组条件编译语句都要用#endif来结束

8.文件包含

(1)头文件被包含的方式

a.本地文件包含


#include "filename"


查找策略:两步走:先在源文件所在目录下查找,如果未找到,就像查找库函数头文件一样在标准位置查找头文件。


b.库函数包含


#include


查找策略:直接去标准路径下查找


(2)防止重复包含

a.


#ifndef __NAME_H__   (名字随便写 它只是判断这条语句之前有没有走过)


#define __NAME_H__


.......


#endif


b.


#pragma once


目录
相关文章
|
14天前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
28 1
|
26天前
|
SQL 存储 前端开发
程序技术好文:面试知识点六:JavaWeb
程序技术好文:面试知识点六:JavaWeb
14 1
|
14天前
|
设计模式 安全 Java
Java面试题:如何实现一个线程安全的单例模式,并确保其在高并发环境下的内存管理效率?如何使用CyclicBarrier来实现一个多阶段的数据处理任务,确保所有阶段的数据一致性?
Java面试题:如何实现一个线程安全的单例模式,并确保其在高并发环境下的内存管理效率?如何使用CyclicBarrier来实现一个多阶段的数据处理任务,确保所有阶段的数据一致性?
13 0
|
14天前
|
设计模式 并行计算 安全
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
16 0
|
14天前
|
存储 安全 Java
Java面试题:假设你正在开发一个Java后端服务,该服务需要处理高并发的用户请求,并且对内存使用效率有严格的要求,在多线程环境下,如何确保共享资源的线程安全?
Java面试题:假设你正在开发一个Java后端服务,该服务需要处理高并发的用户请求,并且对内存使用效率有严格的要求,在多线程环境下,如何确保共享资源的线程安全?
22 0
|
14天前
|
存储 安全 Java
Java面试题:请解释Java内存模型,并说明如何在多线程环境下使用synchronized关键字实现同步,阐述ConcurrentHashMap与HashMap的区别,以及它如何在并发环境中提高性能
Java面试题:请解释Java内存模型,并说明如何在多线程环境下使用synchronized关键字实现同步,阐述ConcurrentHashMap与HashMap的区别,以及它如何在并发环境中提高性能
12 0
|
14天前
|
存储 安全 Java
Java面试题:如何在Java应用中实现有效的内存优化?在多线程环境下,如何确保数据的线程安全?如何设计并实现一个基于ExecutorService的任务处理流程?
Java面试题:如何在Java应用中实现有效的内存优化?在多线程环境下,如何确保数据的线程安全?如何设计并实现一个基于ExecutorService的任务处理流程?
16 0
|
14天前
|
安全 Java 调度
Java面试题:Java内存优化、多线程安全与并发框架实战,如何在Java应用中实现内存优化?在多线程环境下,如何保证数据的线程安全?使用Java并发工具包中的哪些工具可以帮助解决并发问题?
Java面试题:Java内存优化、多线程安全与并发框架实战,如何在Java应用中实现内存优化?在多线程环境下,如何保证数据的线程安全?使用Java并发工具包中的哪些工具可以帮助解决并发问题?
14 0
|
18天前
|
Java 调度 Windows
Java面试之程序、进程、线程、管程和并发、并行的概念
Java面试之程序、进程、线程、管程和并发、并行的概念
15 0
|
2月前
|
Python
2024年最新【Python】程序的组织结构:顺序结构,2024年最新46道面试题带你了解中高级Python面试
2024年最新【Python】程序的组织结构:顺序结构,2024年最新46道面试题带你了解中高级Python面试
2024年最新【Python】程序的组织结构:顺序结构,2024年最新46道面试题带你了解中高级Python面试