2020年9月

C/C++ 入门前提须知不完全指北

本文档用于指导学校不大可能会教,但是又必知的要点(知道有,能简单用就好了,深入的学习还请在深入了解了 c/c++ 之后再做详细的研究学习
也有可能是在后面会教,或是在学习的过程中就学会了……

C 版本与 C++ 版本

K&B C
ANSI C
ISO C
c89
c99
c11
c17

C++98
C++03
C++11
C++14
C++17
C++20
C++23

gcc
mingw
mingw-w64
tdm-gcc

clang-llvm
msvc

末流
borderland++
intel++

大部分的学校所使用的 IDE 无非逃不开 devcpp 5.11 code::blocks VC2010 VC6,这么几种选择。
VC6 属于历史惯性,虽然已经是 上个世纪 98 年的产物,但是完全够教材用,存在的很多局限性,大多数大学生可能也没有太多的感觉。
VC2010 实际上指的是 VC++ 2010 Express 的这种奇奇怪怪的版本,免费,而且轻量,支持的标准也比 VC6 更新,但是也不支持 c++11,但是这个环境已经是目前国家计算机二级等级考试的标准环境,所以,使用 VC6 是真的**。
devcpp 用更老版本的虽然少见,但是确实还是存在的,主流还是 devcpp 5.11 比如我现在就读的这个学校。实际上 devcpp 在相当一定的程度上还可以勉强跟上时代的潮流。
当然,通过更换编译器也可以达到这个效果,不过,和老师的环境不太一样,就没有什么需要考虑的了。devcpp 5.11 支持 c++11,不过需要自己手动开启设置 启用 c++11 或者启动编译器选项 -std=c++11

这里理应需要一张图通过直接勾选启用c++11,但是还没有配置对应环境
![]()
这里应该有一张如何通过编译器选项设置c++11的图片,也没有环境
![]()

code::blocks 可以自动根据系统中的编译器自动配置环境,但是由于官网有一个默认的带有 MinGW 的版本,所以以下的所有内容,也以此为“标准”

实际上 devcpp 和 code::blocks 所使用的编译器都是基于同一个编译器所产生的不同分支,也就是说,同一个妈生的,从使用上,除了 IDE 本身的差别,不会有太多的问题

报错

第一步,当然也是最重要的一步,前面那个只是前言,不看也罢,教不了什么东西

如何看自己的报错

如果你在使用 VS 之流的 IDE,你可以看到它的C++ 报错是有中文的,这个时候可以很方便地看到自己的错误,具体内容是什么意思,但是熟练了,其实看什么都差不多。

一个报错通常会标识一个错误的位置,引发了什么样的错误

部分 ide 提供了双击跳转到错误代码的功能,这个很实用

通常报错总是会由前面的某一个错误,引发一个连锁反应
(关于 C++ 使用到了模板的话,一个报错可能就是几百上千行,此时中间一堆都不用管,直接看到最前面的错误原因就行了)

当程序中存在游离的字符,中文或者是空白字符,通常来说总是后面的问题,因为看到了中文的字符谁不知道它有问题呢,总是一些看不到的符号引发着奇奇怪怪的错误。

又比如函数参数啊,返回值啊等等等等

undefined reference: 未定义的引用,通常是因为include了某个头文件,但是却没有添加对应的源文件或者是库文件,导致函数定义不存在。

不对应的括号,花括号

错误的名称

逗号,分号,中文标点符号

警告

没事,既然只是警告,没有遇到奇葩的问题,就不用管了,
通常是一些什么变量没有使用啊,存在隐式转换什么的,特别奇怪

理解编译的过程

#include <stdio.h>

int main (int argc, char **argv) {

    printf ("Hello World!");
    return 0;
}

这是一个基本的 c 程序,包含了一个宏用于引用别的头文件

main 作为一个入口函数,在程序启动的时候调用

int 是这个函数的返回值,c 标准中没有要求 main 必须返回,或者返回什么

int argc, char**argv 是这个程序启动时输入的参数,你可能操作过类似于,在命令行使用的工具,比如 git 工具,使用 git clone xxx 可以从远端克隆一个项目,每一个参数如何分割是由终端决定的(毕竟万一不支持字符串什么的,也可能是一些问题呢)

printf ("Hello World!"); 是一个调用了标准格式化输出函数,输出字符串的语句,会在你的终端上显示出 Hello World! 这些字符。所谓终端就是你所看到的黑色的窗口,

print 打印
f format 格式化
printf 格式化输出,标准库提供的,所以又叫标准格式化输出函数

scanf sscanf sprintf... 同理

return 0; 返回值,一般 0 为正常结束,非 0 则表示程序出现了异常,在 Windows Command 下,你可以通过打印 %ERRORLEVEL% 的值显示程序返回值(这个内容不是很属于今天要教的内容

$ gcc -o mytest.exe mytest.c -Wall

我们使用如上的命令进行对代码的编译,产生如下的编译结果

$ ./mytest
Hello World!

但实际使用中,使用的更多的还是 make 来进行对项目的构建,make 配置文件通常会由 IDE 进行创建,例如上面提到的,但是 vs 的 make 文件就,比较有特色

预编译、预处理

这个部分将宏进行展开,删除注释

语法检查

检查括号啊,参数类型啊等等等等

语义检查

分析、替换、编译、优化

这部分应该去看一些关于编译原理的书,例如《编译原理》

链接

头文件,库文件,静态链接库动态链接库

标准库为什么没有要我们链接库

因为这个库在系统的内部被提供了
大多数操作系统都会内置一个 c/c++ 的动态链接库给程序链接,实现标准的功能

不同系统的 C++ 标准库在哪

libstdc++.so
什么的

配置链接

-l
-L

编译器选项

-o
-g
-s
-O2
-O3
-O4

构建一个项目

C/C++ 作为一个复杂的工程语言,当然,不是说语法上的复杂,说的是项目之间协作,调库,编译,跨平台编译,使之能够运行是非常复杂的。大家通常使用 makefile 来解决复杂的命令,但是和 .bat .sh 文件来说可能,更加方便令人懂。但是,不同的编译器可能拥有不同的 makefile 语法,然后,很多跨平台跨编译器的项目就需要为这些事情做一些特化,比如附带了一堆的 makefile ,这个通常为实际上的开发产生了相当多的麻烦,因为你需要熟练掌握相当多的 makefile 的语法。然后,cmake 横空出世,通过统一的语法配置了项目,但是 cmake 本身不是直接被编译器所使用的,而是生成了对应编译器的 makefile,然后调用对应编译器对源文件进行编译。但是我觉得 cmake 的语法还是挺操蛋的,非常的不好。有人说 ninja?但是我也觉得只是一般般,然后我现在用的是 xmake,简单的配置就可以为一个项目创建基本的构建工程

参考

C 语言为什么只需要 include<stdio.h> 就能使用里面声明的函数?

C/C++ 框架推荐

这个页面中的内容与 https://zh.cppreference.com/w/cpp/links/libs 十分相似,但是按照我自己的想法添加或移动了内容

项目构建

xmake
cmake
nmake
ninja
MakeFiles

多线程库

网络库

POCO

文本处理库

编码类型转换

格式化库

图像处理

Boost.PIL
Cario

音频处理

OpenAL

多媒体

SDL
EGE
EASYX
XEGE-SDL