C--程序的完整生命周期

C17核心语法实例

#include <stdlib.h> 
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <stdbool.h>

#define BOOL_TRUE 1  // 定义用到的宏常量与宏函数;
#define BOOL_FALSE 0
#define typename(x) _Generic((x), \
unsigned short: "unsigned short int", \
unsigned long: "unsigned long int", \
default: "unknown")

typedef enum { Host, IP } IP_ADDR_TYPE;  // 定义枚举类型 IP_ADDR_TYPE,用于表示联合中生效的字段;
typedef struct {  // 定义结构 CONN;
    size_t id;
    uint16_t port;
    bool closed;
    IP_ADDR_TYPE addr_type;
    union {
      char host_name[256];
      char ip[24];
  };
} CONN;

inline static const char* findAddr(const CONN* pip) {  // 定义函数 findAddr,用于打印 CONN 对象的信息;
    assert(pip != NULL);  // 运行时断言,判断传入的 CONN 指针是否有效;
    return pip->addr_type == Host ? pip->host_name : pip->ip;
}

int main(int argc, char* argv[]) {  // 入口函数;
    static_assert(sizeof(CONN) <= 0x400, "the size of CONN object exceeds limit.");  // 静态断言,判断 CONN 对象的大小是否符合要求;
    const CONN conns[] = {  // 构造一个数组,包含三个 CONN 对象;
      [2] = { 1, 80, BOOL_TRUE, IP, { .ip = "127.0.0.1" } },
      [0] = { 2, 8080, BOOL_FALSE, IP, { .ip = "192.168.1.1" } },
      { 3, 8088, BOOL_FALSE, Host, { .host_name = "http://localhost/" } }
  };
   for (size_t i = 0; i < (sizeof(conns) / sizeof(CONN)); ++i) {  // 遍历上述 CONN 数组,并打印其中的内容;
      printf(
        "Port: %d\n"
        "Host/Addr: %s\n"
        "Internal type of `id` is: %s\n\n",
        conns[i].port,
        findAddr(&conns[i]),
        typename(conns[i].id)
    );
  }
    return EXIT_SUCCESS; 
}

C的编程范式思考

C是一种命令式语言,命令式编程(Imperative Programming)是这样一种编程范式:使用可以改变程序状态的代码语句,描述程序应该如何运行。这种方式更关注计算机完成任务所需要执行的具体步骤。

下面我们来看一个例子。对于“从一个包含有指定数字的集合中,筛选出大于 7 的所有数字”这个需求,按照命令式编程的思路,我们需要通过编程语言来告诉计算机具体的执行步骤。以 C 语言为例,解决这个需求的步骤可能会是这样:使用数组,构造一块可以存放这些数字的内存空间;使用循环控制语句,依次检查内存中的这些数字是否满足要求(即大于 7);对于满足要求的数字,将它们拷贝到新的内存空间中,暂存为结果。对应的代码可能如下所示:

#define ARR_LEN 5
int main(void) { 
  int arr[ARR_LEN] = { 1, 5, 10, 9, 0 };
  for (int i = 0; i < ARR_LEN; ++i) {
    if (arr[i] > 7) {
      // save this element somewhere else.
    }
  }
  return 0;
}

相对于命令式编程语言,其他语言一般会被归类为“声明式”编程语言。声明式编程(Declarative Programming)也是一种常见的编程范式。不同的是,这种范式更倾向于表达计算的逻辑,而非解决问题时计算机需要执行的具体步骤。

比如说,还是刚才那个需求,在使用声明式编程语言时,对应的解决步骤可能是:构建一个容器来存放数据;按照条件对容器数据进行筛选,并将符合条件的数据作为结果返回。如果以 JavaScript 为例,对应的代码可能如下所示:

let arr = [1, 5, 10, 9, 0]
let result = arr.filter(n => n > 7)

C语言的编译和运行

C的编译语法:

gcc demo.c -o demo -Wall && ./demo
Wall-让编译器明确指出程序中运行的不恰当的地方

C代码编译的完整流程:

在这里插入图片描述

预处理阶段

编译器会移除源代码中所有注释信息并处理所有宏指令。其中包括进行宏展开、宏替换已经条件编译等

编译优化阶段

编译器会分析和优化代码,并将其编译成对应的汇编格式代码,这部分代码中含有使用汇编指令描述的原始C逻辑

汇编阶段

编译器会将上面的汇编代码编译成具有一定格式可以被操作系统使用的某种对象文件格式

连接阶段

通过连接处理,编译器会将所有程序目前需要的对象文件进行整合、设置好程序中所有调用函数的正确地址并生成对应的二进制文件。
编译结束后即可运行该文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值