环境搭建

环境搭建即安装前人写的一套编译器,C语言的运行需要一套编译器,即我们要安装的就是这个,win上可以使用古老的VC6,或者DEV-C++,或者CodeBlocks,这些都是自带编译器的,VSCODE不能直接编译C语言,如果需要使用VScode编译C,需要单独安装编译器,在CSDN上搜索一大堆安装教程,不过还是推荐使用linux吧,毕竟工作中嵌入式设备大多都是ARM,ARM又要在linux中使用交叉编译工具链编译,等C学完了linux的环境命也熟悉了,两全其美。

image-20240303144241876

GDB-online是一个在线编译器和调试工具:

image-20240303144339043

link: https://www.onlinegdb.com/

image-20240303144638552

第一个hello程序引申出的问题

#include <stdio.h>

int main()
{
    printf("Hello World");

    return 0;
}
  • 初学者的第一个程序大多都是这样的,hello world似乎世界通用,以上的程序引出这几个问题:
  1. include <stdio.h> 是什么? 是否可以写成#include “stdio.h”

#include <stdio.h> 是 C 语言中的预处理指令,用于包含标准输入输出头文件(Standard Input/Output header file)。这个头文件包含了进行输入输出操作(如 printfscanf 函数)所需的函数声明和宏定义。

使用尖括号(< >)和双引号(" ")在包含头文件时有不同的寻找路径意义:

  • 使用尖括号 < > 告诉编译器从标准库路径中寻找 stdio.h。这是最常用的方法,用于包含标准库或系统库的头文件。
  • 使用双引号 " " 告诉编译器先从当前工作目录或指定的包含路径开始寻找 stdio.h,如果没有找到,再按照标准库路径寻找。这种方式通常用于包含用户自定义的头文件。
  • printf 既然是标准库中 stdio.h的,我是否可以查看具体使用方法?

    在linux系统中,我们可以使用以下命令来查看printf 使用方法

    printf --help
    man printf

    printf --help 这个命令尝试显示 printf 命令的简短帮助信息。不过,需要注意的是,printf 可以指的是 shell 的内建命令或者是某些环境下可用的独立命令程序,而不仅仅是 C 语言的标准库函数。

    image-20240303152313605

man printf 显示了具体的使用方法

image-20240303152610516

man命令介绍

man是linux中常用的一个命令,使用方法如下

image-20240303153544881

man 1 可执行程序或shell命令
man 2 系统调用(内核提供的函数)
man 3库调用(程序库中的函数)
man 4特殊文件(通常在/dev中)
man 5文件格式和约定,如/etc/passwd
man 6 游戏
man 7其他(包括宏包和约定)
man 8系统管理命令(通常只针对root用户)
man 9内核例程[非标准]

如果我们想使用man 3 printf 查看库调用出现如下情况,需要安装下

在很多 Linux 发行版和类 Unix 系统中,标准 C 库函数的手册页(例如 printf 函数的手册页)可能不会默认安装。这些手册页包含在特定的包中,如 manpages-dev(对于 Debian、Ubuntu 及其衍生版本)。如果你需要这些手册页,可以通过安装相应的包来获得。对于基于 Debian 或者ubuntu的系统,可以使用以下命令安装:

sudo apt update
sudo apt install manpages-dev

image-20240303154541801

image-20240303154919838

从以上的信息可知

  • printf函数包含在头文件 <stdio.h>中
  • printf也是有返回值的
  • printf的参数类型
  • 与printf相似的函数

可见,会使用man查找增加了很多未知的知识,最常用的就是man 123

2.为什么程序的主函数总是int main()

image-20240303150719517

需要注意一下其变种:

int main() 是最常见的形式,但标准也允许一些变体,如 int main(int argc, char *argv[])

其中 argc 表示命令行参数的数量,argv 是一个指向参数字符串数组的指针

以下使用一个实际的实例来帮助理解main函数的参数,

在shell的操作中,常见运行一个命令会要求输入参数,下面来模拟一个实例, 控制电机速度使用命令speed

要求输入以下参数speed [1-100] [ABCD]

示例:

speed 20 ABC :ABC电机转动,速度为20

speed 50 ABC :A电机转动,速度为50

speed 100 ABCD :ABCD电机转动,速度为100

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
    if (argc != 4) {
        printf("Usage: %s <speed 1-100> <motors A/B/C/D>\n", argv[0]);
        return 1;
    }

    //解析命令
    char * command = argv[1];
    if(strcmp(command,"speed") != 0)
    {
         printf("not fount command\n");
         printf("Usage: %s <speed> <speed 1-100> <motors A/B/C/D>\n", argv[0]);
         return 1;

    }
    // 解析速度
    int speed = atoi(argv[2]);
    if (speed < 1 || speed > 100) {
        printf("Error: Speed must be between 1 and 100.\n");
        return 1;
    }

    // 检查电机参数
    char *motors = argv[3];
    int validMotor = 1;
    for (int i = 0; i < strlen(motors); i++) {
        if (motors[i] != 'A' && motors[i] != 'B' && motors[i] != 'C' && motors[i] != 'D') {
            validMotor = 0;
            break;
        }
    }

    if (!validMotor) {
        printf("Error: Motors must be any combination of A, B, C, and D (e.g., AB, ACD).\n");
        return 1;
    }

    // 如果一切正常,则执行相应操作
    printf("Setting speed to %d for motors %s\n", speed, motors);
    // 在这里添加实际控制电机的代码

    return 0;
                       
}

以上我们可以通过运行这段代码来体验自己写的电机控制命令

image-20240303165659681

程序是如何运行的?

预处理,编译,汇编,链接

  • 预处理:展开头文件/宏替换/去掉注释/条件编译
  • 编译:检查语法,生成汇编
  • 汇编:编译成机器码
  • 链接:链接到一起生成可执行程序

详细见以下文档(打开链接可直接下载)

https://newbie-typora.oss-cn-shenzhen.aliyuncs.com/zhongke/%E9%A2%84%E5%A4%84%E7%90%86%E7%BC%96%E8%AF%91%E6%B1%87%E7%BC%96%E9%93%BE%E6%8E%A5.pdf

编译型语言和解释型语言的区别:

image-20240303171606436

编译型语言

  • 编译过程:在程序运行之前,编译型语言需要一个单独的编译过程,将源代码转换成机器语言(或者是中间语言,然后由另一个程序转换为机器语言),这个过程通常由一个编译器完成。
  • 执行速度:编译型语言编译后生成的是直接由计算机硬件执行的机器码,因此执行速度快。
  • 平台依赖性:编译后的程序通常是针对特定的操作系统和硬件架构的,如果要在不同的平台上运行,需要重新编译。
  • 示例语言:C、C++、Go、Rust 和 Swift。

解释型语言

  • 执行方式:解释型语言通常不需要预编译成机器语言,而是在程序运行时由解释器逐行读取源代码,然后直接执行代码或将代码转换为中间表示再执行。
  • 执行速度:由于每次运行程序时源代码都需要通过解释器转换,因此解释型语言的执行速度通常比编译型语言慢。
  • 跨平台性:解释型语言的程序更容易在不同的操作系统和硬件架构上运行,只要那些平台上有对应的解释器。
  • 示例语言:Python、Ruby、JavaScript、PHP 和 Perl。

总结:编译型语言先编译完后运行,运行效率较高,解释型语言边运行边解释,运行效率较低

如果觉得我的文章对你有用,请随意赞赏