news 2026/7/2 5:01:09

初识C语言的常见概念

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
初识C语言的常见概念

Windows 与 Linux 下 C 编译工具链对比:MSVC MinGW GCC
本文系统梳理Windows平台下的 MSVC和MinGW与Linux平台下的GCC的区别。

工具链全称 / 背景所属生态主要平台
MSVCMicrosoft Visual C++ Compiler微软官方Windows
MinGWMinimalist GNU for WindowsGNU 开源社区Windows
GCCGNU Compiler CollectionGNU/Linux 开源生态Linux

MinGW本质上是在Windows运行的GCC,将Linux/的 GCC 工具链移植到Windows,并提供对Windows API的访问能力

三者都经历预处理 → 编译 → 汇编 → 链接四个阶段,但工具和输出格式存在差异:

步骤MSVC (Windows)MinGW (Windows)GCC (Linux)
编译器前端cl.exegcc.exegcc
汇编器内嵌于cl.exeas(GNU as)as
链接器link.exeld(GNU ld)ld
目标文件格式COFF(.objCOFF(使用.o扩展名)ELF(.o
可执行文件格式PE(.exePE(.exeELF(通常无扩展名)
静态库.lib.a.a
动态库.dll+.lib(导入库).dll+.dll.a.lib.so

要注意MSVC和MinGW都生成.dll,但他们不能混用,它们使用不同的运行时库(CRT)和 ABI(应用二进制接口)混合链接会导致崩溃。

工具链运行时库是否需要额外安装?部署便利性
MSVCMSVCRT(如msvcr140.dll,vcruntime140.dll需安装对应版本的Visual C++ Redistributable较麻烦(需分发运行时)
MinGWmsvcrt.dll(Windows 系统自带)或静态链接通常无需额外安装(尤其静态链接时)更轻量、独立
GCC (Linux)glibc(系统自带)一般已存在依赖系统版本
方面MSVCMinGWGCC (Linux)
IDE 支持深度集成 Visual Studio(调试强大)Code::Blocks、Qt Creator、VS CodeVim/Emacs + GDB,或 VS Code、CLion
调试器cdb/ Visual Studio Debuggergdbgdb
构建系统MSBuild、CMake(支持)Make、CMakeMake、CMake、Meson 等
标准支持C++20/23 支持较好(随 VS 更新)依赖 GCC 版本(如 MinGW-w64 GCC 13)最新标准支持快(开源社区活跃)
跨平台性仅 Windows可跨平台原生跨平台

编译单个文件

# MSVC-在 Developer Command Prompt 中
cl hello.c
# MinGW
gcc hello.c -o hello.exe
# Linux GCC
gcc hello.c -o hello

笔者使用的编译器为MinGw&GCC,环境为VScode or Debian 12.0

4.源文件,头文件介绍

C语言把.c为后缀的文件称为源文件,把.h为后缀的文件称为头文件。

第一个C语言程序
#include <stdio.h>
int main(void)
{
printf("hello world!\n");
return 0;
}
5.main函数

main函数是程序的入口,因此被称为主函数,无论这个C语言程序有多少行代码,均从main函数开始执行。
int表示main在执行结束时需要返回一个整型类型的值,这与结尾的return 0相互呼应。

即使一个项目有多个.c文件,也只可以有一个main函数

6.printf和库函数

上面第一个C语言程序中包含了一个代码:

printf("hello world!\n");

此处使用了printf函数,实现在屏幕上打印的功能。
printf是一个库函数,printf也可以打印其他类型的数据:

int n = 100;
printf("%d\n",n); //打印整型
printf("%c\n",'q'); //打印字符串
printf("%lf\n",3.14); //打印双精度浮点行

这里的%d %c是占位符,会被后面对应的值替换,此处只做初步了解。

在使用库函数的时候,必须包含其对应的头文件,比如printf函数需要包含stdio.h这个头文件

使用库函数的方法是添加:

#include <stdio.h>
为什么需要库函数呢?

为了不在重复实现常用的代码,C语言标准规定了一组函数用于提升开发效率,由不同的编译器厂商根据标准实现,这些函数库叫做标准库,有一些厂商会自行添加函数,为了代码的移植性和跨平台开发,我们应该主动使用标准库中的函数

7.C语言中的关键字

在C语言有一些符号名称被保留下来,诸如:int,if,return,goto等等

  • 关键字具有特殊含义
  • 人为创建标识符的时候不能与关键字重复
  • 关键字也不可以被创建

C语言中最通用普遍的关键字一共有32个:

1.auto break case char const continue default do double else enum
extern
2.float for goto if int long register return short signed sizeof
static
3.struct switch typedef union unsigned void volatile while

C99中加入了_Bool_Complex_Imaginaryinlinerestrict
C11中加入了_Alignas,_Alignof,_Atomic,_Static_assert,_Noreturn,_Thread_local,generic

8.字符和ASCII编码

诸如:&,!,n,p,%,@等,这样的符号叫做字符,在C中,这些字符使用单引号括起来的,像这样:'X'
在计算机中所有的数据都是以二进制存储的,这些字符在内存中如何用二进制存储?美国国家标准学会(ANSI)指定了标准ASCII编码,C中的字符就遵循ASCII编码的方式。


我们只需要能够查阅表格即可,,但为了一些场景使用方便,我们最好记住一些特殊的数字:

  • 字符A-Z的码值在65-90
  • 字符a-z的码值在97-122
  • 大小写字符A-Z,a-z的码值差值是32
  • 数字字符0~9的码值在48-57
  • 换行\n的码值为10
  • 0~31码值对应的字符不可被打印

打印单个字符可以用占位符%c指定其格式:

#include <stdio.h>
int main(void)
{
printf("%c\n",'X');
printf("%c\n",88);
return 0;
}

在屏幕上输出所有的可打印字符:

#include <stdio.h>
int main(void)
{
int i = 0;
for (i = 32; i <= 127;i++)
{
printf("%c ",i);
if (i % 16 == 15)
printf("\n");
}
return 0 ;
}

这样会在终端上输出所有的可打印字符。当然,不能少了编译的过程。

9.字符串和隐藏的\0

我们已经知道了字符这个概念,如果是很多字符连接起来叫做什么?
在C语言中表示字符串使用:
"abcdefg",使用双引号括起来的字符叫做字符串,像一串“烧烤”


打印字符串可以用占位符%s指定其格式,也可以直接打印字符串:

#include <stdio.h>
int main(void)
{
printf("%s\n","abcdefg");
printf("abcdefg");
return0;
}

在字符串中,其实隐藏了一个\0字符,这个\0放置在字符串的末尾,\0是字符串结束的标志。

例如字符串"abcdefg",显示出来7个字符,但在末尾还有一个隐藏的\0,使用printf()函数打印字符串或者使用serlen()函数计算字符串长度的时候,遇到\0就停止,因此\0是字符串的结束标志


在C语言中也可以把一个字符串放在字符数组里来验证\0的作用:

#include <stdio.h>
int main(void)
{
char arr1[] = {'a','b','c'};
char arr2[] = {"abc"};
printf("%s\n",arr1);
printf("%s\n",arr2);
return 0;
}

在进行调试的过程中可以观察到arr1arr2中内容的差异,arr1中只有a,b,c。而arr2中则有a,b,c,\0。由于笔者暂时还不会在Linux中调试,因此脑补一下吧(滑跪--)


如果运行这段代码,可能会产生这样的现象:

abc烫烫烫烫烫烫?n?
abc

这是因为没有\0,仍然向后读取内存中的内容,具体什么内容?那就是未知数了。

arr2数组因为使用了字符串常量初始化,因此一切正常。
若在arr1中单独加入\0,则一切也会正常
由此可见\0的作用

10.转义字符

在上文中使用了\0,\n,这些也是字符,但他们是一组特殊的字符,成为转义字符,用来转变原来字符的意思。


在屏幕中打印出n,很显然:

#include <stdio.h>
int main(void)
{
printf("abcdnefg");
return 0;
}

会输出:

abcdnefg

如果在n之前加入\,则:

#include <stdio.h>
int main(void)
{
printf("abcd\nefg");
return 0;
}

会输出:

abcd
efg

显然两次输出的结果差异很大
\n这个转义字符表示换行


在C语言中的转义字符还有:

  • \a:响铃(Bell),产生 audible 或 visible 警告(如终端 beep)
  • \b:退格(Backspace),光标回退一格
  • \f:换页(Form feed),用于打印机或终端清屏(在某些终端等效于清屏)
  • \n:换行(Newline),将光标移到下一行开头
  • \r:回车(Carriage return),将光标移至当前行开头(不换行)
  • \t:水平制表符(Horizontal tab),通常跳到下一个 8 字符/4 字符对齐位置
  • \v:垂直制表符(Vertical tab),在现代终端中较少使用
  • \\:反斜杠字符本身(用于表示字面量\
  • \':单引号字符(用于字符常量中,如'\'
  • \":双引号字符(用于字符串中包含引号,如"He said \"Hi\""
  • \?:问号字符(用于避免与三字符组 trigraphs 冲突,现已很少用)
  • \0:空字符(Null character),ASCII 值为 0,常用于字符串结尾
  • \ooo:1~3 位八进制数表示的字符(如\141表示 'a')
  • \xhh:1~2 位十六进制数表示的字符(如\x61表示 'a')

用代码可以演示:

#include <stdio.h>
int main(void)
{
printf("%c\n",'\'');
printf("%s\n","\"");
printf("d:\\C_code\\gitee\\test.c\n");
printf("\a");
printf("%c\n",'\130');//130是八进制,输出'X'
printf("%c\n",'\x58');//x30是十六进制,输出'X'
return 0;
}
11.语句及其分类

C语言的代码是由语句构成,可以分为五大类:

  • 空语句
  • 表达式语句
  • 函数调用语句
  • 复合语句
  • 控制语句

11.1空语句

极其简单的语句,一个分号就是空语句:

#include <stdio.h>
int main(void)
{
;//此处为空语句
return 0;
}

出现在此处需要一个语句,但是不需要它做事情。

11.2表达式语句

在表达式的后面加上分号:

#include <stdio.h>
int main(void)
{
int a = 10;
int b = 20;
b = a + 5;//此处为表达式语句
return 0;
}
11.3函数调用语句
//一个文件中包含两个函数
#include <stdio.h>
void butler(void);//ANSI/ISO C函数原型,这里是函数原型
int main(void)//这里是以函数调用的形式出现在main()中
{
printf("I will summon the butler function.\n");
butler();//函数调用语句
printf("Yes. Bring me some tea and writeable DVDs.\n");
//函数调用语句
return 0;
}
void butler(void)//函数定义开始
{
printf("You rang, sir?\n");
}
11.4复合语句

复合语句也就是代码块,成对括号里的代码就构成一个代码块
诸如:


函数中的代码块:

#include <stdio.h>
int main(void)
{
printf("程序开始\n");
{ // 这是一个复合语句(代码块)
int x = 10;
int y = 20;
printf("x + y = %d\n", x + y);
} // x 和 y 的作用域在此结束
printf("程序结束\n");
return 0;
}

if语句中的代码块:

#include <stdio.h>
int main(void)
{
int score = 85;
if (score >= 60)
{
printf("及格了!\n");
printf("继续加油!\n");
} // 这个 {} 构成一个复合语句
return 0;
}

循环中的代码块:

#include <stdio.h>
int main(void)
{
for (int i = 0; i < 3; i++)
{
printf("第 %d 次循环\n", i + 1);
int temp = i * 2;
printf("temp = %d\n", temp);
} // 整个循环体是一个复合语句
return 0;
}

嵌套代码块:

#include <stdio.h>
int main(void)
{
int a = 1;
{
int b = 2;
printf("a = %d, b = %d\n", a, b);
{
int c = 3;
printf("a = %d, b = %d, c = %d\n", a, b, c);
} // c 的作用域结束
} // b 的作用域结束
// 此处只能访问 a
printf("回到外层,a = %d\n", a);
return 0;
}

广泛用于函数体、控制结构(if/for/while 等)中


11.5控制语句

控制语句用于控制程序的执行,以实现程序中的各种结构方式,在C语言中,支持三种结构:顺序结构,选择结构,循环结构。他们由特定的语法定义符号组成。
在C语言中由九种控制语句,可以分为三大类:

  1. 条件判断语句:if,swith
  2. 循环语句:do while,while,for
  3. 转向语句:break,goto,continue,return
    此处只作列举,学习留在后面。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/2 5:00:12

2026年国产TF卡品牌哪家好?深度评测与选购指南

在无人机航拍、运动相机记录、Switch掌机扩容、行车记录仪循环录制以及智能手机拓展存储等场景中&#xff0c;TF卡&#xff08;即microSD卡&#xff09;已成为不可或缺的存储介质。然而&#xff0c;市面上的TF卡品牌繁多&#xff0c;参数虚标、读写掉速、高温环境下数据丢失等问…

作者头像 李华
网站建设 2026/7/2 5:00:11

嵌入式条形码识别系统开发与TM4C123优化实践

1. 项目背景与核心需求在工业自动化、零售仓储和智能设备领域&#xff0c;条形码识别技术一直是数据采集的核心环节。传统方案往往采用现成的扫码枪或工业相机&#xff0c;但在嵌入式设备集成、成本敏感或特殊环境应用中&#xff0c;自主开发条形码读取系统具有独特优势。EM308…

作者头像 李华
网站建设 2026/7/2 4:56:40

AI 视频智能体新手 7 天上手指南:从注册到第一条成片

很多人第一次听到"AI 视频智能体"&#xff0c;第一反应是&#xff1a;又是另一种自动剪辑工具吧&#xff1f; 真不是。 AI 视频智能体和传统剪辑工具最大的区别&#xff0c;是它能把"找爆款、拆结构、写脚本、出视频、做封面、发多平台"这一整圈流程&#…

作者头像 李华
网站建设 2026/7/2 4:54:57

[Divide节点]原理解析与实际应用

理标量、向量和矩阵等多种数据类型&#xff0c;在材质动态控制、特效实现与性能优化中发挥关键作用。例如&#xff0c;在昼夜交替系统中&#xff0c;Divide节点可通过时间参数驱动场景光照的平滑过渡&#xff1b;在角色受伤特效中&#xff0c;它能精确控制屏幕红色渐变的强度。…

作者头像 李华
网站建设 2026/7/2 4:54:54

【Linux网络】理解tc命令

tc&#xff1a;traffic control&#xff0c;即交通控制。 1.基本工作流程 使用tc命令&#xff0c;需要理解三个Linux内核网络中的概念&#xff1a; qdisc&#xff1a;是Queue Discipline的缩写&#xff0c;中文是队列规则&#xff0c;就是数据包怎么入队&#xff0c;每个网口都…

作者头像 李华