C\C++\python对比_概览(1)

0、前言:

  • 对C、C++、python的学习有了专项笔记,现在需要进行对比,对比的目的是熟悉掌握这三种语言。
  • 这个文章我计划是放在知识蒸馏系列当中,我认为真正掌握一门知识的体现,就是"书越读越薄",所以从概览的角度总结这三门语言的区别,对于对比记忆很有帮助。
  • 我担心这部分对比可能不是很全面,所以文章题目后面加了(1),后续针对概述的每个部分进行真实测试和梳理汇总,加深了解,同时完成对这篇概览文章的优化和迭代,以后就可以直接通过这篇文章梳理自己对这三门语言的记忆框架,达到提纲挈领的目的。

0.1、C和C++以及python的用途对比:

  • C:面向过程、底层、高性能,用途(操作系统、嵌入式、驱动、高性能工具);
  • C++:面向过程 + 面向对象、兼顾底层与上层,用途(游戏引擎、音视频、大型软件、高性能计算);
  • Python:解释型、高开发效率,用途(数据分析、爬虫、Web 开发、AI、自动化脚本)。

0.2、环境配置、运行方式、代码执行流程之间的对比:

  • 运行方式(C/C++:编译型,需编译链接;Python:解释型,直接运行);
  • 环境搭建(C/C++ 需编译器如 GCC/VS,Python 需解释器 + pip;IDE 选择);
  • 代码执行流程(C/C++:编写→编译→运行;Python:编写→直接运行)。
  • 说明:C和C++是编译型语言,编译型语言的特点就是要先整体编译成机器码,再执行,执行速度快,但是对于不同的平台需要重新编译(CPU架构和操作系统,这两者有一个不一样,就要重新编译,CPU架构不同,指令集就不同,操作系统不同,生成的可执行文件格式就不同)因此可移植性低,编译耗时(开发效率低);而python是解释型语言,通过解释器,一边解释一边运行,执行速度慢,源代码可以跨平台运行(只要每个平台配对应的解释器即可)因此可移植性高,开发效率高(一边写一边运行)。

0.3、基于windows环境在vs code中配置运行的方式区别:

  • 给vs code部署python
    1、根据平台环境下载对应版本python的解释器,在终端中测试python是否正常安装:python -v
    2、在vs code中安装python拓展Python extension for Visual Studio Code
    3、在vs code中创建项目文件夹,然后在项目文件夹路径下通过:python -m venv .venv 使用venv模块创建虚拟环境,运行venv的Scripts中的activate或者Activate.ps1激活虚拟环境,激活后终端前面会有(.venv)
    4、选择python解释器,在vs code中按住ctrl+shift+P选择venv\Scripts\python.exe作为解释器
    5、然后就可以写程序了,程序写好之后,可以直接点击运行按钮,也可以在终端通过"调用操作符"【& python解释器路径 执行程序路径】
  • 给vs code部署C/C++
    1、安装 MinGW-w64(编译器)。
    2、把编译器路径添加到系统PATH。
    3、在终端中输入:g++ -v查看是否正确安装。
    4、在vs code中安装C/C++ extension for Visual Studio Code插件。
  • python和C++在依赖管理上有很大差别【具体可以参考本文第三节】
    1、Python有虚拟环境和pip,而C++主要通过 构建系统(CMake)、包管理器(类似于python中的pip)、手动安装库(下载库源码、编译、放到系统路径【usr\include或者usr\lib】)三种方法来解决库依赖,但是手动安装库项目依赖混乱。
    2、现在很多都是CMake+vcpkg进行C++项目开发。
    3、C++常用的包管理工具也支持C语言库,但C语言还有一些更轻量化的专属工具,比如vcpkg,它是跨平台的,支持C/C++,微软维护,库比较全,易用,pkg-config是linux\macOS原生的,轻量,无需安装额外工具,还有apt、yum、brew这些系统级包管理工具。

1、基础对比:

1.1、基本语句结构对比

  • C和C++每条语句后面要有分号,python主要靠缩进。
1.1.1、格式化输出对比
  • C语言输出:printf
    主要靠占位符,printf("格式字符串", 参数),例如:printf("x=%d\n", x);
  • C++输出:cout和printf
    cout << + 流操纵符(setprecision 等) 或 std::format (C++20) / printf 也能用,例如:cout << "x=" << x; cout << std::format("x={}\n", x);
  • python输出:print
    f-string(推荐)、str.format、%,例如:print(f"x={x}")
1.1.2、条件语句和其他控制语句的区别
  • C和C++靠括号括条件,花括号括条件体;python靠空格区分条件,靠冒号和缩进区分条件和条件体。
  • python三元运算符:真值 if 条件 else 假值
  • 其他控制语句:循环语句(for/while 用法,如 Python 的for-in vs C/C++ 的for(初始化;条件;更新)),C/C++ 和 Python 的 while 循环区别,与 if 语句的区别基本一致;跳转语句(break/continue 通用,C/C++ 有goto,Python 无)。
1.1.3、其他差异
  • 变量与类型(C/C++:静态类型、需声明;Python:动态类型、无需声明);
  • 代码块标识(C/C++:大括号{};Python:缩进);
  • 输入输出(C:printf/scanf;C++:cout/cint/兼容C;Python:print/input);
  • 注释语法(C/C++://或/* */;Python:#或两对三个连续的双引号配对)。

1.2、常用数据结构对比



  • C:无内置高级结构,需手动实现数组 / 链表(仅原生数组),只有基础类型 + 自定义结构体,复杂度高;
  • C++:STL 容器(vector/map/set/string),性能高,抽象能力强,库丰富;
  • Python:内置列表 / 元组 / 字典 / 集合,开箱即用,性能相对低,但开发速度极快。

2、关键差异总结:

2.1、语法风格

  • C: 面向过程、需要显式类型声明(复杂,抽象程度高)
  • C++: 兼顾面向过程与面向对象,支持泛型、智能指针(基本同C)
  • Python: 动态类型、依赖缩进、代码可读性极高(简洁,更像伪代码)

2.2、内存管理

  • C:手动管理(malloc/free),需关注内存泄漏 / 野指针;
  • C++:手动(new/delete)+ 部分自动化(智能指针);
  • Python:自动垃圾回收(GC),无需手动管理。

2.3、易用性 vs 性能

  • C → 性能最高,但开发负责度高
  • C++ → 性能高,抽象能力强,库丰富
  • Python → 性能相对低,但开发速度极快

3、第三方库 / 标准库:

3.1、概览:

  • 标准库(C:极简(stdio.h/stdlib.h);C++:STL + 标准库;Python:丰富内置库);
  • 第三方库获取(C:手动编译;C++:CMake / 包管理器;Python:pip 一键安装);
  • 典型基础库(如 C 的math.h,C++ 的iostream,Python 的math/random)。

3.2、关于C和C++引入第三方库的核心机制详述:

  • ★★★C和C++引入第三方库的方式,就和编译过程有关系了,通过预编译展开头文件、通过编译生成目标文件、通过

    源代码 (.c/.cpp)

    【预编译】处理 #include, #define, 条件编译,文本替换,只是复制粘贴头文件内容(函数声明、宏、类型定义)

    【编译】生成汇编代码 (.s),语法检查 + 生成汇编

    【汇编】生成目标文件 (.o/.obj),汇编代码 → 机器码

    【链接】合并目标文件 + 库文件 → 可执行程序,链接之前,给程序声明画饼都可以,在这个阶段就要兑现。对于静态库(windows中是lib后缀)会把库代码复制进可执行文件,可执行文件会比较大,对于动态库(windows中是so后缀),在运行时加载,可执行文件会比较小。

  • C和C++的多文件项目,如果要引入第三方库(包含自己写的带头文件的程序源码),用IDE会比较方便, IDE 的"方便"是封装了 Makefile,不是取代了它。

  • 介绍自研库、静态库、动态库的区别:

    ✅ 自研库 = 静态 / 动态库的源码阶段:

    自研库本质是未打包的源码(.h 声明 + .c 实现),是构建静态 / 动态库的 "原材料"------ 你可以把自研库编译成静态库,也可以编译成动态库。

    ✅ 静态库 = 编译时 "拷贝进可执行文件":

    链接阶段会把静态库的二进制代码完整复制到最终的可执行文件里,运行时完全不依赖外部库文件,可执行文件是 "自给自足" 的。

    ✅ 动态库 = 编译时 "只声明依赖":【运行时是否依赖原始库文件------ 依赖则是动态库,不依赖则是静态库】

    链接阶段只在可执行文件里记录 "我需要 xxx 动态库",不拷贝任何库代码;运行时操作系统会根据这个声明,去系统路径里找对应的动态库文件(如 libcurl.so),找到才能运行,找不到就报错。

    ❗ 在 Python 中,自研库、静态库、动态库的核心逻辑是相通的,但具体形态、名称和使用方式和 C/C++ 有很大差异(因为 Python 是解释型语言,没有编译链接的强区分)。Python 里的 "自研库" 就是你自己写的 .py 源码文件 / 文件夹,和 C/C++ 自研库的 "源码阶段" 完全对应。将自研的 .py 代码打包成编译后的字节码包 (.pyc)或源码归档包(.egg/.whl),安装时会把包的代码 "完整拷贝" 到 Python 的 site-packages 目录(发生了拷贝,运行时不依赖原始库文件),运行时解释器直接加载本地拷贝的代码,不依赖外部源文件;Python 经常调用 C 编写的扩展库(如 numpy/pandas 的核心模块),这些库本质是 C 语言的动态库(.so/.dll)。

    bash 复制代码
    # 把自研库打包成 .whl(等价于静态库)
    python setup.py bdist_wheel
    # 安装后,代码被拷贝到本地,主程序运行时无需原源码文件
    pip install my_lib-1.0.0-py3-none-any.whl
    
    # 调用 C 写的动态库(运行时依赖 libnumpy.so 存在,等价于动态库)
    import numpy
  • 以C项目为例说明自研库、静态库、动态库:

    1、头文件声明:在 main.c 中通过 #include "mathlib/mathlib.h" 引入函数声明,让编译器知道函数的名称、参数和返回值类型。

    2、代码实现:mathlib.c 中实现了头文件里声明的函数,编译后会生成目标文件(.o)或打包成库文件。

    3、链接阶段:Makefile 会将 main.o 和 mathlib.o(或 libmathlib.a)链接在一起,把函数调用的地址填充到最终可执行文件中,让主程序能找到并执行库内的实现。

  • 以python项目为例说明自研库、静态库、动态库:

    1、Python 解释器在运行时会按「自研库(本地路径)→ 静态库(site-packages)→ 动态库(系统路径 / 本地路径)」的顺序查找库,三者的加载逻辑互不冲突,可同时存在。

    2、自研库:依赖本地 my_self_lib/ 源码文件夹;静态库:依赖 site-packages 里的拷贝文件(和自研库源码无关);numpy 动态库:依赖系统的 numpy/core/_multiarray_umath.so 等动态库文件;三者的依赖路径不同,不会互相干扰。

    3、自研库:写业务逻辑(如数据清洗函数);静态库:安装公司内部封装的工具包(打包成 .whl,无需源码);动态库:调用 numpy/pandas/scipy(都是 C 写的动态库,依赖 .so/.pyd)。


4、异常 / 错误处理:

4.1、C的异常报错机制

  • C:无原生异常机制,靠返回值 /errno 处理错误;
  • 核心示例:文件操作错误处理
c 复制代码
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main() {
    FILE *fp;
    // 尝试打开一个不存在的文件
    fp = fopen("不存在的文件.txt", "r");
    // 检查返回值是否为 NULL(错误指示)
    if (fp == NULL) {
        // 错误处理:读取 errno 获取具体错误码
        printf("open default!\n");
        printf("error : %d\n", errno);
        printf("error infor: %s\n", strerror(errno));  // 转换为可读字符串
        // 根据 errno 做具体处理
        if (errno == ENOENT) {
            printf("reason: file not here\n");
        } else if (errno == EACCES) {
            printf("reason: have no power\n");
        }
        return 1;  // 返回非0,表示运行失败
    }
    // 正常操作...
    fclose(fp);
    return 0;
}

4.2、C++的异常报错机制

  • C++:try-catch-throw 异常体系;
cpp 复制代码
#include <iostream>
#include <stdexcept>  // 标准异常类

double divide(int a, int b) {
    if (b == 0) {
        throw std::runtime_error("a除数不能为零");  // 抛出异常
    }
    return static_cast<double>(a) / b;
}

int main() {
    try {
        double result = divide(10, 0);  // 可能抛出异常
        std::cout << "b结果: " << result << std::endl;
    }
    catch (const std::exception& e) {   // 捕获异常
        std::cerr << "c捕获错误: " << e.what() << std::endl;
    }
    
    std::cout << "d程序继续执行..." << std::endl;
    return 0;
}

4.3、python的异常报错机制

  • Python:try-except-else-finally 异常体系,内置丰富异常类型。
python 复制代码
# 不处理异常:程序会直接崩溃并抛出错误
a = 10
b = 0
result = a / b  # 除数为0,触发 ZeroDivisionError
print(result)

# 处理异常:程序不会崩溃,还能给出友好提示
try:
    # 尝试执行的代码(可能出错的代码)
    a = 10
    b = 0
    result = a / b
    print(f"计算结果:{result}")  # 出错时这行不会执行
except ZeroDivisionError:
    # 捕获到 "除数为0" 异常时执行的逻辑
    print("错误:除数不能为0!请检查输入的数值。")
except Exception as e:
    # 捕获所有其他未预料到的异常(万能捕获,可选)
    print(f"发生了未知错误:{e}")
else:
    # 没有异常时才会执行的代码(可选)
    print("计算成功完成!")
finally:
    # 无论是否有异常,都会执行的代码(可选,比如释放资源)
    print("程序执行结束(finally 块)。")

5、面向对象(类)

5.1、C只能模拟面向对象

  • C:无面向对象,需手动模拟(结构体 + 函数指针);

5.2、C++支持面向对象

  • C++:原生支持(类、对象、继承、多态、封装);
  • 【数据类型】类的成员变量、方法参数 / 返回值必须显式声明类型,编译期就会检查类型是否匹配,错误早暴露。
  • 【访问控制】有严格的访问修饰符:public(公开)、private(私有,仅类内访问)、protected(受保护,子类可访问),编译期强制限制,无法绕过。
  • 【继承机制】支持多继承,但会带来菱形继承(钻石问题),需要用 virtual 关键字解决二义性,语法复杂,目的是兼顾性能和正确性。
  • 【构造和析构】构造函数可以重载多个,析构函数必须手动释放内存、关闭文件、释放指针,还有拷贝构造、移动构造重点解决内存拷贝的问题
  • 【方法特性】普通方法默认绑定类的实例,静态方法属于类,虚函数支持运行时多态,支持方法重载。
  • 【类的实例化】C++支持两种实例化,影响内存位置。一种是栈实例(Person p;),自动销毁。一种是堆实例(Person* p = new Person();),需要手动释放(delete p)。

5.3、python支持面向对象

  • Python:原生支持(极简语法,无显式封装,动态属性)。
  • 【数据类型】类的成员无需声明类型,运行时动态绑定类型,同一个变量可以随时赋值不同类型。
  • 【访问控制】没有真正的访问控制,仅靠命名约定:
    self.name:公开(默认)
    self._name:约定私有(提示开发者不要外部访问,但实际能访问)
    self.__name:名称改写(伪私有,外部需用 _类名__name 访问,并非真正禁止)本质是 "君子协定",而非语法强制。
  • 【继承机制】天然支持多继承,通过 MRO(方法解析顺序) 自动解决二义性(如 C(A,B) 会按固定顺序查找父类方法),语法简洁,无需手动处理。
  • 【构造和析构】在python中__init__是初始化,__new__是真正的构造,但很少用。__del__是析构,但极少用,垃圾回收自动处理,开发者不用关注内存。不存在拷贝构造的概念,赋值拷贝依赖浅拷贝或深拷贝函数,比较简单。
  • 【方法特性】实例方法默认带self参数,静态方法需要加装饰器,类方法也要加装饰器用来绑定类。天然支持多态,子类重写父类方法即可,不支持方法重载。
  • 【类的实例化】Python中实例化只有一种方式(p = Person()),垃圾回收自动销毁,无需关心内存位置。

6、线程和进程管理

6.1、什么是进程和线程?

  • 进程(Process):程序的 "独立运行实例", 你双击打开的微信、浏览器、Python 脚本,运行起来后就是一个进程进程是操作系统分配资源(内存、CPU 时间片、文件句柄等)的最小单位
    • 每个进程有自己独立的内存空间,进程间不能直接访问对方的内存(需通过管道、套接字等 "进程间通信(IPC)" 方式);
    • 进程是 "重量级" 的:创建 / 销毁进程需要操作系统分配 / 释放大量资源,开销大;
    • C/C++ 中创建进程(如 fork()/CreateProcess)、Python 中 multiprocessing.Process,本质都是告诉操作系统 "新建一个独立的资源容器,运行指定代码"。
  • ==线程(Thread):进程内的 "执行流",==一个进程(比如微信)内部可以同时做很多事(接收消息、刷朋友圈、播放语音),每一个独立的 "做事路径" 就是一个线程线程是操作系统调度 CPU 执行的最小单位。
    • 线程隶属于进程,同一进程内的所有线程共享进程的内存空间(比如全局变量、堆内存),通信成本极低(直接读写共享变量即可);
    • 线程是 "轻量级" 的:创建 / 销毁线程仅需分配少量栈内存,开销远小于进程;
    • C/C++ 中 pthread/、Python 中 threading.Thread,本质是在已有进程的资源容器内,新建一个 CPU 执行流。

6.2、在c、c++、python中如何使用进程和线程

  • 进程是 "资源容器" (操作系统分配资源的最小单位),线程是 "执行流"(操作系统调度 CPU 的最小单位);
  • C 直接调用操作系统内核接口实现进程 / 线程操作;C++ 仅将操作系统的线程接口封装为标准库(进程仍依赖 C 级系统调用);Python 则基于 C 语言的底层接口对进程 / 线程做二次封装,高度抽象且屏蔽底层细节。

7、跨平台支持

  • C、C++、Python三者均支持跨平台,但底层实现逻辑差异极大:C/C++ 是 "底层可控但需手动适配",Python 是 "高度封装且开箱即用"。

7.1、C语言跨平台支持

  • 【底层支持】几乎所有操作系统(Windows/Linux/macOS/ 嵌入式)都提供 C 语言编译器(GCC/Clang/MSVC),是跨平台的 "基础语言";
  • 【核心特点】语法本身跨平台,但系统调用、硬件接口需手动区分平台(如创建进程:Linux 用 fork(),Windows 用CreateProcess();文件路径:Linux 用 /,Windows 用 \);
  • 【适配方式】通过预处理指令 #ifdef 区分平台(如 #ifdef _WIN32 处理 Windows 逻辑,#ifdef linux 处理 Linux 逻辑);
  • 【总结】适配成本高,需开发者熟悉不同系统的 API 差异,但可控性极强(嵌入式 / 内核级跨平台首选)。

7.2、C++跨平台支持

  • 【底层支持】基于 C 的跨平台基础,C++ 标准库试图屏蔽系统差异,但非所有功能都完全跨平台;
  • 【核心特点】 标准库部分(如容器 std::vector、算法)完全跨平台,无需适配。 系统相关功能(进程 / 线程、文件系统、网络)仍需手动适配(如 封装了底层线程接口,但进程操作仍需区分 fork()/CreateProcess());编译器差异(MSVC/GCC)可能导致非标准语法(如编译器扩展)不兼容;
  • 【适配方式】同 C 一样用 #ifdef 区分平台
  • 【总结】适配成本略低于 C(标准库封装了部分通用逻辑),但仍需关注系统和编译器差异。

7.3、python跨平台支持

  • 【底层支持】Python 解释器(CPython)本身由 C 实现,已适配各主流系统(Windows/Linux/macOS),开发者无需接触底层;
  • 【核心特点】语法和标准库(如 os/sys/threading)完全跨平台,同一行代码可在不同系统运行;第三方库(如 requests/pandas)大多已做跨平台适配,仅少数底层库(如硬件驱动相关)需额外处理;跨平台运行仅需目标系统安装对应平台的 Python 解释器,无需编译。
  • 【适配方式】基本上有个解释器就能实现自动跨平台
  • 【总结】适配成本极低,几乎无需关注系统差异,是上层应用跨平台的首选。

8、常用应用领域(通过什么工具实现xx开发功能)

8.1、C的常用应用领域

  • 底层系统开发:操作系统内核(Linux/Windows 内核)、驱动程序(硬件驱动),工具 / 接口:直接调用操作系统内核 API、GCC/Clang/MSVC 编译器;
  • 嵌入式开发:单片机(STM32)、物联网设备固件,工具 / 接口:Keil、GCC 嵌入式编译器、硬件寄存器操作接口;
  • 高性能基础组件:数据库内核(MySQL 底层)、网络协议栈(TCP/IP 实现),工具 / 接口:POSIX 标准库、系统调用(socket/fork)。

8.2、C++的常用应用领域

  • 高性能应用开发:游戏引擎(Unreal Engine)、工业仿真软件,工具 / 接口:C++ 标准库、Boost 库、DirectX/OpenGL 图形接口;
  • 中间件 / 后端服务:分布式存储(Ceph)、高并发服务器(Nginx 部分模块),工具 / 接口:/ 线程库、ACE/ASIO 网络库;
  • 桌面应用 / 大型软件:CAD 软件(AutoCAD)、办公套件(LibreOffice),工具 / 接口:Qt/MFC 框架、C++ 标准容器(vector/map)。

8.3、python的常用应用领域

  • 数据分析 / 人工智能:数据处理(Pandas/Numpy)、机器学习(TensorFlow/PyTorch),工具 / 接口:Anaconda 环境、各类 AI 框架 API;
  • Web 开发:后端接口(Django/Flask/FastAPI)、爬虫(Scrapy/Requests),工具 / 接口:WSGI/ASGI 协议、requests/BeautifulSoup 库;
  • 自动化 / 运维:脚本运维(Ansible 底层)、自动化测试(Selenium/Pytest),工具 / 接口:os/sys 标准库、paramiko(远程操作)、unittest 测试框架;
  • 快速原型开发:产品 demo、小工具开发,工具 / 接口:Python 标准库、第三方库(如 tkinter 做简单 GUI)。

总结

  • C:聚焦底层 / 嵌入式 / 高性能基础组件,依赖编译器 + 系统原生 API,无高级框架;
  • C++:聚焦高性能应用 / 游戏 / 中间件,依赖标准库 + 专业框架(Qt/Boost);
  • Python:聚焦数据分析 / AI/Web/ 自动化,依赖丰富第三方库 + 高层框架,开发效率优先。
相关推荐
海盗猫鸥2 小时前
「Linux工具」gcc/g++
linux·c语言·c++
Yungoal2 小时前
Visual StudioProfiler对工作流进行热点分析
c++·visual studio
不光头强2 小时前
Java网络爬虫
java·爬虫·python
2401_891482172 小时前
用Python批量处理Excel和CSV文件
jvm·数据库·python
m0_743297422 小时前
使用Flask快速搭建轻量级Web应用
jvm·数据库·python
Lsir10110_2 小时前
【Linux】网络编程基础—套接字
linux·运维·服务器·网络·c++
小年糕是糕手2 小时前
【35天从0开始备战蓝桥杯 -- 补充包】
开发语言·前端·数据结构·数据库·c++·算法·蓝桥杯
技术工小李2 小时前
多人平板答题系统护航第24届汉语桥比赛
python
Byte不洛2 小时前
手写一个C++ TCP服务器实现自定义协议(顺便解决粘包问题)
linux·c++·操作系统·网络编程·tcp