tokenpocket钱包下载app安卓|c网络语言是什么意思
tokenpocket钱包下载app安卓|c网络语言是什么意思
C 语言入门手册:几小时内就能学会的 C 语言基础
C 语言入门手册:几小时内就能学会的 C 语言基础
搜索
提交您的搜索查询
论坛
捐款
2021年2月22日
/
#C语言
C 语言入门手册:几小时内就能学会的 C 语言基础
Nicholas Zhan
本手册遵循二八定律。你将在 20% 的时间内学习 80% 的 C 编程语言。
这种方式将会让你对这门语言有一个全面的认识。
本手册并不会尝试覆盖与 C 有关的一切。它只会关注这门语言的核心部分,尽量将更加复杂的主题简单化。
提示:你可以从这里获得这本手册的 PDF 或 ePub 版本。
尽情享受吧!
目录
C 语言简介
变量与类型
常量
运算符
条件语句
循环
数组
字符串
指针
函数
输入与输出
变量作用域
静态变量
全局变量
类型定义
枚举类型
结构体
命令行参数
头文件
预处理器
结语
C 语言简介
C 可能是最广为人知的编程语言。它被全世界的计算机科学课程中用作参考语言,除了 Python 与 Java,它可能是人们在学校学得最多得编程语言。
我记得它是我在 Pascal 之后的第二门编程语言。
学生们用 C 来学习编程,但它的作用远不止这一点。它不是一门学术型语言。它不是最简单的语言,因为 C 是一门非常底层的编程语言。
今天,C 在嵌入式设备中广泛使用,它驱动着绝大多数用 Linux 搭建的因特网服务器。Linux 内核是用 C 写的,这也意味着 C 驱动着所有安卓设备的内核。可以这么说,此时此刻,整个世界的一大部分就是由 C 代码运行的,令人惊叹。
在诞生之初,C 被认为是一门高级语言,因为它可以在不同机器之间移植。如今,我们或多或少都认为在 Mac 或 Windows 或 Linux 运行一个程序(可能使用 Node.js 或 Python)是理所当然的。
在以前,完全不是这样的。C 带来了一门易于实现的语言,它的编译器可以很容易地被移植到不同的机器上。
我说下译器:C 是一门编译型语言,就像 Go、Java、Swift 或 Rust 一样。其它流行的语言,比如 Python、Ruby 或 JavaScript 都是解释型语言。编译型语言与解释型语言的差别是不变的:编译型语言生成的是可直接执行和分发的二进制文件。
C 不支持垃圾收集(garbage collection),这意味着我们必须自己管理内存。管理内存是一项复杂的任务,需要十分小心才能预防缺陷,但 C 也因此成为了嵌入式设备(例如 Arduino)编程的理想语言。
C 并不会隐藏下层机器的复杂性和能力。一旦知道你能做什么,你就能拥有巨大的能力。
现在,我想介绍第一个 C 程序,我们将会管它叫“Hello, World”。
hello.c
#include
int main(void) {
printf("Hello, World!");
}
让我们描述一下这段程序源代码:我们首先导入了 stdio 库(stdio 表示的是标准输入输出库(standard input-output library))。
这个库允许我们访问输入/输出函数。
C 是一门内核非常小的语言,任何内核以外的部分都以库的形式提供。其中一些库由普通编程人员构建并供他人使用。另一些库被内置在编译器中,比如 stdio 等。
stdio 库提供了 prinf() 函数。
这个函数被包裹在 main() 函数中,main() 函数是所有 C 程序的入口。
但是,究竟什么是函数呢?
函数(function)是一个例程,它接收一个或多个参数并返回一个值。
在 main() 的例子中,函数没有参数,返回一个整数。我们使用 void 关键字标识该参数,使用 int 关键字标识返回值。
函数有一个由花括号包裹的函数体,函数需要进行的所有操作的代码都在函数体内。
如你所见,printf() 函数的写法稍有不同。它没有定义返回值,并且我们给它传入了一个用双引号包裹的字符串。我们并没有声明参数的类型。
那是因为这是一个函数调用。在 stdio 库中的某个地方,printf 被定义成
int printf(const char *format, ...);
你现在不需要理解这是何含义,简单来说,这是就是函数定义。当我们调用 printf("Hello, World!"); 时,这就是该函数运行的地方。
我们在上面定义的 main() 函数:
#include
int main(void) {
printf("Hello, World!");
}
将会在程序被执行的时候由操作系统运行。
我们如何执行一个 C 程序呢?
如我所说,C 是一门编译型语言。要运行程序,我们必须先编译它。任何 Linux 或 macOS 计算机都自带了 C 编译器。至于 Windows,你可以使用适用于 Linux 的 Windows 子系统(WSL)。
无论如何,你都可以在打开终端时输入 gcc,这个命令应该会返回一个错误,提示你没有声明任何文件:
很好。它说明 C 编译器是有的,现在我们可以开始使用它了。
现在将上面的程序输入到一个名为 hello.c 的文件中。你可以使用任何编辑器,不过为了简单起见,我将在命令行中使用 nano 编辑器:
输入程序:
现在按 ctrl-X 退出:
按 y 键确认,然后按回车键确认文件名:
就是这样,我们现在应该已经回到终端了:
现在输入
gcc hello.c -o hello
程序应该不会给你任何错误信息:
但是它应该已经生成了一个名为 hello 的可执行程序。现在输入
./hello
运行它:
我在程序名的前面加了 ./,告诉终端要执行的命令就在当前目录下。
太棒了!
现在,如果你调用 ls -al hello,你能看到这个程序只有 12KB 大:
这是 C 的优点之一:它是高度优化的,这也是它非常适用于资源非常有限的嵌入式设备的原因之一。
变量与类型
C 是一门静态类型语言。
这意味着任何变量都有一个相关联的类型,并且该类型在编译时是可知的。
这与你在 Python、JavaScript、PHP 和其它解释型语言中使用变量的方式大有不同。
当你在 C 中创建变量时,你必须在声明中给出该变量的类型。
在这个示例中,我们初始化一个 int 类型的变量 age:
int age;
变量名可以包含任意大写或小写字母,也可以包含数字和下划线,但是不能以数字开头。AGE 和 Age10 都是有效的变量名,但 1age 就不是了。
你还可以在声明中初始化变量,给出初始值即可:
int age = 37;
变量一旦声明,你就可以在程序代码中使用它了。你在任何时候都可以使用 = 改变它的值,例如 age = 100;(提供的新值的类型与原值相同)。
在这种情况下:
#include
int main(void) {
int age = 0;
age = 37.2;
printf("%u", age);
}
编译器会在编译时发出警告,然后将小数转为整数。
C 的内置数据类型有 int、char、short、long、float、double、long double。咱们进一步了解这些数据类型吧。
整数
C 给我们提供了下列定义整数的类型:
char
int
short
long
通常,你很可能会使用 int 保存整数。但是在某些情况下,你或许想在其它三个选项中选取合适的类型。
char 类型通常被用来保存 ASCII 表中的字母,但是它也可以用来保存 -128 到 127 之间的小整数。它占据至少一个字节。
int 占据至少两个字节。short 占据至少两个字节。long 占据至少四个字节。
如你所见,我们并不保证不同环境下的值相同。我们只有一个指示。问题在于每种数据类型中所存储的具体值是由实现和系统架构决定的。
我们保证 short 不会比 int 长。并且我们还保证 long 不会比 int 短。
ANSI C 规范标准确定了每种类型的最小值,多亏了它,我们至少可以知道使用某个类型时可以期待的最小值。
如果你正在 Arduino 上用 C 编程,不同的板子上的限制会有所不同。
在 Arduino Uno 开发板上,int 占两个字节,范围从 -32,768 到 32,767。在 Arduino MKR 1010 上,int 占四个字节,范围从 -2,147,483,648 到 2,147,483,647。差异还真不小。
在所有的 Arduino 开发板上,short 都占两个字节,范围从 -32,768 到 32,767。long 占四个字节,范围从 -2,147,483,648 到 2,147,483,647。
无符号整数
对于以上所有的数据类型,我们都可以在其前面追加一个 unsigned。这样一来,值的范围就不再从负数开始,而是从 0 开始。这在很多情况下是很有用的。
unsigned char 的范围从 0 开始,至少到 255
unsigned int 的范围从 0 开始,至少到 65,535
unsigned short 的范围从 0 开始,至少到 65,535
unsigned long 的范围从 0 开始,至少到 4,294,967,295
溢出的问题
鉴于所有这些限制,可能会出现一个问题:我们如何确保数字不超过限制?如果超过了限制会怎样?
如果你有一个值为 255 的 unsigned int,自增返回的值为 256,这在意料之中。如果你有一个值为 255 的 unsigned char,你得到的结果就是 0。它重置为了初始值。
如果你有一个值为 255 的 unsigned char,给它加上 10 会得到数字 9:
#include
int main(void) {
unsigned char j = 255;
j = j + 10;
printf("%u", j); /* 9 */
}
If you don't have a signed value, the behavior is undefined.
原文这里可能是 typo,从代码来看,这里描述的是有符号整数的溢出行为。
如果你的值是有符号的,程序的行为则是未知的。程序基本上会给你一个很大的值,这个值可能变化,就像这样:
include
int main(void) {
char j = 127;
j = j + 10;
printf("%u", j); /* 4294967177 */
}
换句话说,C 并不会在你超出类型的限制时保护你。对于这种情况,你需要自己当心。
声明错误类型时的警告
如果你声明变量并用错误的值进行初始化,gcc 编译器(你可能正在使用这个编译器)应该会发出警告:
#include
int main(void) {
char j = 1000;
}
hello.c:4:11: warning: implicit conversion
from 'int' to
'char' changes value from 1000 to -24
[-Wconstant-conversion]
char j = 1000;
~ ^~
1 warning generated.
如果你直接赋值,也会有警告:
#include
int main(void) {
char j;
j = 1000;
}
但是对值进行增加操作(例如,使用 +=)就不会有警告:
#include
int main(void) {
char j = 0;
j += 1000;
}
浮点数
浮点类型可以表示的数值范围比整数大得多,还可以表示整数无法表示的分数。
使用浮点数时,我们将数表示成小数乘以 10 的幂。
你可能见过浮点数被写成
1.29e-3
-2.3e+5
和其它的一些看起来很奇怪的形式。
下面的几种类型:
float
double
long double
是用来表示带有小数点的数字(浮点类型)的。这几种类型都可以表示正数和负数。
任何 C 的实现都必须满足的最小要求是 float 可以表示范围在 10^-37 到 10^+37 之间的数,这通常用 32 位比特实现。 double 可以表示一组更大范围的数,long double 可以保存的数还要更多。
与整数一样,浮点数的确切值取决于具体实现。
在现代的 Mac 上,float 用 32 位表示,精度为 24 个有效位,剩余 8 位被用来编码指数部分。
double 用 64 位表示,精度为 53 个有效位,剩余 11 为用于编码指数部分。
long double 类型用 80 位表示,精度为 64 位有效位,剩余 15 位被用来编码指数部分。
你如何能在自己的计算机上确定这些类型的大小呢?你可以写一个程序来干这事儿:
#include
int main(void) {
printf("char size: %lu bytes\n", sizeof(char));
printf("int size: %lu bytes\n", sizeof(int));
printf("short size: %lu bytes\n", sizeof(short));
printf("long size: %lu bytes\n", sizeof(long));
printf("float size: %lu bytes\n", sizeof(float));
printf("double size: %lu bytes\n", sizeof(double));
printf("long double size: %lu bytes\n", sizeof(long double));
}
在我的系统上(一台现代 Mac),输出如下:
char size: 1 bytes
int size: 4 bytes
short size: 2 bytes
long size: 8 bytes
float size: 4 bytes
double size: 8 bytes
long double size: 16 bytes
常量
咱们现在来谈谈常量。
常量的声明与变量类似,不同之处在于常量声明的前面带有 const 关键字,并且你总是需要给常量指定一个值。
就像这样:
const int age = 37;
这在 C 中是完全有效的,尽管通常情况下将常量声明为大写,就像这样:
const int AGE = 37;
虽然这只是一个惯例,但是在你阅读或编写 C 程序时,他能给你提供巨大的帮助,因为它提高了可读性。大写的名字意味着常量,小写的名字意味着变量。
常量的命名规则与变量相同:可以包含任意大小写字母、数字和下划线,但是不能以数字开头。AGE 和 Age10 都是有效的变量名,而 1AGE 就不是了。
另一种定义常量的方式是使用这种语法:
#define AGE 37
在这种情况下,你不需要添加类型,也不需要使用等于符号 =,并且可以省略末尾的分号。
C 编译器将会在编译时从声明的值推断出相应的类型。
运算符
C 给我们提供了各种各样的运算符,我们可以用来操作数据。
特别地,我们可以识别不同分组的运算符:
算术运算符
比较运算符
逻辑运算符
复合赋值运算符
位运算符
指针运算符
结构运算符
混合运算符
在这一节中,我们将用两个假想的变量 a 和 b 举例,详细介绍所有这些运算符。
为了简单起见,我将不会介绍位运算符、结构运算符和指针运算符。
算术运算符
我将把这个小型分组分为二元运算符和一元运算符。
二元操作符需要两个操作数:
操作符
名字
示例
=
赋值
a = b
+
加
a + b
-
减
a - b
*
乘
a * b
/
除
a / b
%
取模
a % b
一元运算符只需要一个操作数:
运算符
名字
示例
+
一元加
+a
-
一元减
-a
++
自增
a++ or ++a
--
自减
a-- or --a
a++ 与 ++a 的区别在于:a++ 在使用 a 之后才自增它的值,而 ++a 会在使用 a 之前自增它的值。
例如:
int a = 2;
int b;
b = a++ /* b 为 2,a 为 3 */
b = ++a /* b 为 4,a 为 4 */
这也适用于递减运算符。
比较运算符
运算符
名字
示例
==
相等
a == b
!=
不相等
a != b
>
大于
a > b
<
小于
a < b
>=
大于等于
a >= b
<=
小于等于
a <= b
逻辑运算符
! 非(例如:!a)
&& 与(例如:a && b)
|| 或(例如:a || b)
这些运算符在使用布尔值时非常有用。
复合赋值运算符
当赋值与算术运算同时进行时,这些运算符非常有用。
运算符
名字
示例
+=
加且赋值
a += b
-=
减且赋值
a -= b
*=
乘且赋值
a *= b
/=
除且赋值
a /= b
%=
求模且赋值
a %= b
三目运算符
三目运算符是 C 中唯一一个使用三个操作数的运算符,并且它是表达条件的简便方法。
它看起来长这样:
<条件> ? <表达式> : <表达式>
示例:
若 a 的值为 true,就执行语句 b,否则执行语句 c。
三目运算符的功能与 if/else 条件语句相同,但是它更短,还可以被内联进表达式。
sizeof
sizeof 运算符返回你传入的操作数的大小。你可以传入变量,或者甚至是类型也可以。
使用示例:
#include
int main(void) {
int age = 37;
printf("%ld\n", sizeof(age));
printf("%ld", sizeof(int));
}
运算符优先级
对于所有的这些运算符(以及我们还没有在本文中介绍的其它运算符,包括位运算符、结构运算符和指针运算符),我们在单个表达式中一起使用它们时必须要留意。
假如我们有这个运算:
int a = 2;
int b = 4;
int c = b + a * a / b - a;
c 的值是多少?我们在执行乘和除之前有进行加法操作吗?
这里是给我们解惑的一组规则。
按照顺序,优先级从低到高:
赋值运算符 =
二元运算符 + 和 -
运算符 * 和 /
一元运算符 + 和 -
运算符还具有关联规则,除了一元运算符和赋值运算符之外,该规则总是从左到右的。
在:
int c = b + a * a / b - a;
中,我们首先执行 a * a / b,由于是从左到右的,我们可以拆分为 a * a 与其结果 /b:2 * 2 = 4,4 / 4 = 1。
然后我们可以进行加法操作和减法操作:4 + 1 - 2。c 的值是 3。
然而,在所有的示例中,我都想确保你意识到你可以使用括号让任何相似的表达式更易读和易理解。
括号的优先级比其它任何运算符都要高。
上述示例表达式可以被重写为:
int c = b + ((a * a) / b) - a;
并且我们不必考虑太多。
条件语句
任何编程语言都给程序员提供了进行选择的能力。
我们想要在一些情况下进行 X,而在其它情况下进行 Y。
我们想检查数据,根据数据的状态做选择。
C 给我们提供了两种方式。
第一种方式是带 else 的 if 语句,第二种是 switch 语句。
if
在 if 语句中,你可以在检查到条件为 true 的时候,执行花括号内的代码块:
int a = 1;
if (a == 1) {
/* 进行一些操作 */
}
如果原始条件的结果是 false,你可以追加一个 else 块以不同的代码块:
int a = 1;
if (a == 2) {
/* 进行一些操作 */
} else {
/* 进行另一些操作 */
}
谨防一种常见的缺陷源——总是在比较中使用比较运算符 ==,而不是赋值运算符 =。如果你不这么做,除非参数为 0,否则 if 条件检查的结果将一直都是 true。例如,如果你这么做:
int a = 0;
if (a = 0) {
/* 永远都不会被调用 */
}
为什么会这样呢?因为条件检查会寻找一个布尔类型的结果(比较的结果),数字 0 总是等于 false。其它的任何东西都是 true,包括负数。
通过将多个 if 语句堆叠在一起,你可以有多个 else 块:
int a = 1;
if (a == 2) {
/* do something */
} else if (a == 1) {
/* 进行一些操作 */
} else {
/* 进行另一些操作 */
}
switch
如果你的检查需要使用非常多的 if/else/if 块,可能是因为你需要检查变量的具体值,这时 switch 语句对你来说就非常有用了。
你可以提供一个变量作为条件,然后为期望的每个值使用一个 case 入口点:
int a = 1;
switch (a) {
case 0:
/* 进行一些操作 */
break;
case 1:
/* 进行另一些操作 */
break;
case 2:
/* 进行另一些操作 */
break;
当前一个 case 执行完后,为了避免下一个 case 被执行,我们需要在每个 case 的末尾使用 break 关键字。这种“级联”效果在某些创造性方法中非常有用的。
你可以在末尾添加一个“捕获所有的” case,名为 default:
int a = 1;
switch (a) {
case 0:
/* 进行一些操作 */
break;
case 1:
/* 进行另一些操作 */
break;
case 2:
/* 进行另一些操作 */
break;
default:
/* 处理所有其它的情况 */
break;
}
循环
C 给我们提供了三种循环:For 循环、while 循环 和 do while 循环。它们都允许你在数组上进行迭代,但又各有不同。咱们仔细来看一看它们。
For 循环
第一种执行循环是 for 循环,它可能也是最常见的循环。
使用 for 关键字时,我们可以先定义循环的 规则,然后提供反复执行的那个代码块。
就像这样:
for (int i = 0; i <= 10; i++) {
/* 反复执行的指令 */
}
(int i = 0; i <= 10; i++) 代码块包含与循环细节有关的三个部分:
初始条件(int i = 0)
测试(i <= 10)
增长(i++)
我们首先定义循环变量,本示例中为 i。i 是循环中的一个常用变量名,j 是嵌套循环(循环内的循环)内使用的变量名。这只是一个惯例。
变量 i 的值被初始化为 0,并且第一次迭代执行完毕。然后 i 像增长部分(这个示例中是 i++,递增 1)所说的那样增长,并且所有的循环会一直重复,直到 i 的值达到数字 10。
在循环的主代码块内,我们可以访问变量 i,从而获知我们当前所处的是哪个迭代。这个程序应该打印 0 1 2 3 4 5 5 6 7 8 9 10:
for (int i = 0; i <= 10; i++) {
/* 反复执行的指令 */
printf("%u ", i);
}
循环可以从较高的数字开始,往较低的数字逼近,就像这样:
for (int i = 10; i > 0; i--) {
/* 反复执行的指令 */
}
你也可以让循环变量的增量为 2 或者其它值:
for (int i = 0; i < 1000; i = i + 30) {
/* 反复执行的指令 */
}
while 循环
while 循环 写起来比 for 循环要简单,因为它需要你在自己的部分做更多的事情。
使用 while 时,你只需要检查条件,而不用在循环开始时预先定义所有的循环数据(就像你在 for 循环中做的那样):
while (i < 10) {
}
这段代码假定 i 已经定义并且用某个值进行了初始化。
除非你在循环内的某些地方增加变量 i 的值,否则这个循环会变成一个 无限循环。无限循环非常糟糕,因为它会阻塞程序,从而使其它任何事情都不会发生。
对于一个“正确的” while 循环,这是你需要知道的:
int i = 0;
while (i < 10) {
/* 做点事情 */
i++;
}
其中有一个例外,我们将会在一分钟后看到它。在这之前,让我介绍下 do while。
Do while 循环
while 循环非常棒,但是有些时候你可能需要做某件特定的事情:你总是想执行某个代码块,然后 可能 一直重复它。
这可以通过 do while 关键字来完成。它在某种程度上和 while 循环非常类似,但是会有些许不同:
int i = 0;
do {
/* 做点事情 */
i++;
} while (i < 10);
尽管条件检查在底部,但是包含注释 /* 做点事情 */ 的代码块总是会至少执行一次。
然后,只要 i 小于 10,我们都将会重复这个代码块。
使用 break 跳出循环
在所有的 C 循环内,不管循环的条件设置得如何,我们都有一种在某个时间立即跳出循环的方法。
这是通过 break 关键字来完成的。
这在很多情况下非常有用,你可能想检查某个变量的值,例如:
for (int i = 0; i <= 10; i++) {
if (i == 4 && someVariable == 10) {
break;
}
}
对 while 循环(也适用于 do while 循环)来说,使用这种方式跳出循环非常有趣,因为我们可以创建一个看似无限的循环,不过我们可以在某个条件发生时结束这个循环。你可以在循环代码块里面定义它:
int i = 0;
while (1) {
/* 做点事情 */
i++;
if (i == 10) break;
}
这种循环在 C 中非常普遍。
数组
数组是存储多个变量的变量。
在 C 中,数组中的每个值都必须有 相同的类型。这意味着你将会有 int 值组成的数组, double 值组成的数组,等等。
你可以像这样定义一个 int 型的数组:
int prices[5];
你必须总是声明数组的大小。C 没有提供开箱即用的动态数组(为此,你必须使用像链表这样的数据结构)。
你可以使用常量定义数组的大小:
const int SIZE = 5;
int prices[SIZE];
你可以在定义数组的时候进行初始化,就像这样:
int prices[5] = { 1, 2, 3, 4, 5 };
但是你也可以在定义数组之后为其赋值,用这种方式:
int prices[5];
prices[0] = 1;
prices[1] = 2;
prices[2] = 3;
prices[3] = 4;
prices[4] = 5;
或者使用循环,这更加实际:
int prices[5];
for (int i = 0; i < 5; i++) {
prices[i] = i + 1;
}
prices[0]; /* 第一个数组项的值 */
prices[1]; /* 第二个数组项的值 */
数组的索引从 0 开始,所以一个有五个元素的数组,比如上面的 prices 数组,将会包含的数组项的范围为 prices[0] 到 prices[4]。
有趣的是,C 数组中的所有元素都是顺序存放的,一个接一个。高级编程语言通常不会出现这种情况。
另一件有趣的事情是:数组的变量名,上述示例中的 prices,是一个指向数组中首个元素的 指针。因此,可以像普通指针一样使用数组。
稍后会介绍更多有关指针的内容。
字符串
在 C 中,字符串是一种特殊的数组:字符串是由 char 值组成的数组:
char name[7];
我在介绍 C 中的数据类型时介绍过 char 类型,但是简而言之,它通常用于存储 ASCII 表中的字母。
可以像初始化一个普通的数组那样初始化一个字符串:
char name[7] = { "F", "l", "a", "v", "i", "o" };
或者使用更加方便的字符串字面量(也被称为字符串常量),一组用双引号引起来的字符:
char name[7] = "Flavio";
你可以通过 printf() 打印字符串,使用 %s:
printf("%s", name);
你有注意到“Flavio”是 6 个字符长,但是我定义了一个长度为 7 的数组吗?这是因为字符串中的最后一个字符必须是 0,它是字符串的终止符号,我们必须给它留个位置。
记住这个非常重要,尤其是当你操作字符串的时候。
说到操作字符串,C 提供了一个非常重要的标准库:string.h。
这个库是必不可少的,因为它抽象了很多与字符串有关的底层细节,给我们提供了一组非常有用的函数。
你可以在程序中加载这个库,需要在文件顶部加上:
#include
一旦你这么做了之后,你就可以访问函数:
strcpy():将一个字符串复制到另一个字符串
strcat():将一个字符串追加到另一个字符串
strcmp():比较两个字符串是否相等
strncmp():比较两个字符串的前 n 个字符
strlen():计算字符串的长度
还有很多很多其它的函数供你调用。
指针
在我看来,指针是 C 中最令人不解/最具挑战的部分。尤其当你是编程新手的时候,如果你是从像 Python 或 JavaScript 这样的高级语言来到 C 的,也会这样。
在这一节中,我想以最简单但又不模糊的方式介绍它们。
指针是某个内存块的地址,这个内存块包含一个变量。
当你像这样声明一个整数时:
int age = 37;
我们可以使用 & 运算符获取内存中该变量的地址值:
printf("%p", &age); /* 0x7ffeef7dcb9c */
我在 printf() 内声明 %p 格式来打印地址值。
我们可以将该地址赋给一个变量:
int address = &age;
当在声明中使用 int *address 时,我们并没有在声明一个整数值,而是在声明一个 指向一个整数的指针。
我们可以使用指针运算符获取该地址指向的变量的值:
int age = 37;
int *address = &age;
printf("%u", *address); /* 37 */
我们又一次使用指针运算符,但是由于这次它不是一个声明,所以它表示“该指针指向的变量的值”。
在这个示例中,我们声明了一个 age 变量,但是我们使用了一个指针来初始化它的值:
int age;
int *address = &age;
*address = 37;
printf("%u", *address);
在使用 C 时,你会发现很多东西都建立在这个简单的概念之上。所以自己运行一下上面的示例,确保你对它有所熟悉。
指针是一个非常好的机会,因为它们迫使我们考虑内存地址以及数据是如何组织的。
数组就是一个例子。当你声明一个数组时:
int prices[3] = { 5, 4, 3 };
prices 变量实际上是一个指向数组首个元素的指针。在这种情况下,你可以使用这个 printf() 函数获取第一个数组元素的值:
printf("%u", *prices); /* 5 */
我们可以通过给 prices 指针加一来获取第二个元素,这是一件非常酷的事情:
printf("%u",`_ `(prices + 1)); /* 4 */
这种做法对于所有的其它值也适用。
我们还可以进行很多非常美妙的字符串操作,因为字符串的底层就是数组。
我们还有很多其它的使用场景,包括传递对象或函数的引用,从而避免消耗更多的资源来进行复制。
函数
我们通过函数将代码组织成子例程,这样就可以:
给它一个名字
在需要它们的时候进行调用
从你的第一个程序(“Hello, World!”)开始,你就在使用 C 函数了:
#include
int main(void) {
printf("Hello, World!");
}
main() 函数是一个非常重要的函数,它是 C 程序的入口点。
这是另一个函数:
void doSomething(int value) {
printf("%u", value);
}
函数有 4 个重要的方面:
它们有一个名字,所以我们可以在之后调用它们
它们声明一个返回值
它们可以有参数
它们有一个函数体,用花括号包裹
函数体是一组指令,任何时候,只要函数被调用,这组指令就会被执行。
如果函数没有返回值,你可以在函数名前面使用关键字 void。否则你就要声明该函数的返回值类型(整数为 int,浮点数为 float,字符串为 const char *,等等)。
函数返回值的数量不能超过一个。
函数可以有参数。它们是可选的。如果函数没有参数,我们就在括号内插入 void,就像这样:
void doSomething(void) {
/* ... */
}
在这种情况下,当我们调用该函数时,括号内没有任何东西:
doSomething();
如果有一个参数,我们就声明该参数的类型和名字,就像这样:
void doSomething(int value) {
/* ... */
}
当我们调用该函数时,我们会在括号内传递对应的参数,就像这样:
doSomething(3);
我们可以有多个参数,为此我们使用逗号对它们进行分隔,在声明和调用时都是这样:
void doSomething(int value1, int value2) {
/* ... */
}
doSomething(3, 4);
参数是通过 拷贝 传递的。这意味着如果你修改 value1,它的值是在局部作用域内修改的。函数外的那个值,即我们在调用时传入的值,并不会改变。
如果你传入的参数为一个 指针,你可以修改该变量的值,因为你现在可以使用它的内存地址直接访问它。
你不能为参数定义默认值。C++ 是可以的(Arduino Language 程序也可以),但是 C 不行。
确保你在调用函数之前定义了该函数,否则编译器将会给出一个警告和一个错误:
➜ ~ gcc hello.c -o hello; ./hello
hello.c:13:3: warning: implicit declaration of
function 'doSomething' is invalid in C99
[-Wimplicit-function-declaration]
doSomething(3, 4);
^
hello.c:17:6: error: conflicting types for
'doSomething'
void doSomething(int value1, char value2) {
^
hello.c:13:3: note: previous implicit declaration
is here
doSomething(3, 4);
^
1 warning and 1 error generated.
你收到的警告与顺序有关,我之前有提到过这个。
错误与另一件事情有关。因为 C 没有在调用函数之前没有“看到”该函数的声明,所以它必须进行假设。并且,它假设该函数返回 int。然而该函数返回的是 void,因此出现了错误。
如果你将该函数的定义修改为:
int doSomething(int value1, int value2) {
printf("%d %d\n", value1, value2);
return 1;
}
你就只会得到警告,错误消失了:
➜ ~ gcc hello.c -o hello; ./hello
hello.c:14:3: warning: implicit declaration of
function 'doSomething' is invalid in C99
[-Wimplicit-function-declaration]
doSomething(3, 4);
^
1 warning generated.
不管是何种情况,确保你在使用函数之前声明了它。要么将函数上移,要么在头文件中加入该函数的原型。
在函数内部,你可以声明变量:
void doSomething(int value) {
int doubleValue = value * 2;
}
变量在调用该函数的那一刻创建,并且在函数退出的时候销毁。它对函数外面来说是不可见的。
在函数内部,你可以调用函数自己。这被称为 递归,它提供了特有的机会。
输入与输出
C 是一门小型语言,并且 C 的“内核”并不包含任何输入/输出(I/O)功能。
当然,这并不是 C 所独有的。语言内核与 I/O 无关是很常见的。
在 C 中,输入/输出由 C 的标准库通过一组定义在 stdio.h 头文件中的函数向我们提供。
你可以在 C 文件顶部使用:
#include
导入这个库。
这个库给我们提供了很多其它的函数:
printf()
scanf()
sscanf()
fgets()
fprintf()
在描述这个函数干啥之前,我想先花一分钟讲一下 I/O 流。
在 C 中,我们有三种类型的 I/O 流:
stdin(标准输入)
stdout(标准输出)
stderr(标准错误)
借助 I/O 函数,我们始终可以和流一起工作。流是一个高级接口,可以代表一个设备或文件。从 C 的角度来看,我们在从文件读取和命令行读取没有任何差异:不论如何,它都是一个 I/O 流。
那是我们需要牢记的一件事情。
某些函数是为与特定的流一起工作而设计的,就像 printf()一样,我们用它来将字符串打印到 stdout。使用它更加通用的版本 fprintf() 时,我们可以指定我们要写到的流。
由于我最开始谈论的是 printf(),咱们现在就介绍它吧。
printf() 是你在学习 C 编程时最先使用的函数之一。
在它最简单的使用形式中,你给它传递一个字符串字面量:
printf("hey!");
并且程序会将该字符串的内容打印到屏幕上。
你可以打印一个变量的值。但是这有点棘手,因为你需要添加一个特殊的字符,一个占位符,它会根据变量的类型变化。例如,我们为有符号十进制整数使用 %d:
int age = 37;
printf("My age is %d", age);
通过使用逗号,我现在可以打印多个变量:
int age_yesterday = 37;
int age_today = 36;
printf("Yesterday my age was %d and today is %d", age_yesterday, age_today);
还有其它像 %d 一样的格式指示符:
%c 用于字符
%s 用于字符串
%f 用于浮点数
%p 用于指针
还有很多。
我们可以在 printf() 中使用转义字符,比如 \n 可以用来让输出创建一个新行。
scanf()
printf() 被用作输出函数。我现在想介绍一个输入函数,这样我们就能完成所有的 I/O 操作:scanf()。
这个函数被用来从用户运行的程序,从命令行获取一个值。
我们必须先定义一个变量,它将被用来存放我们从输入中获取的值:
int age;
然后我们调用 scanf(),传入两个参数:变量的格式(类型),和变量的地址:
scanf("%d", &age);
如果我们想在输入时获取一个字符串,还记得字符串名是一个指向第一个字符的指针,所以你不需要在它前面加上 &:
char name[20];
scanf("%s", name);
这里是一个小程序,它同时使用了 printf() 和 scanf():
#include
int main(void) {
char name[20];
printf("Enter your name: ");
scanf("%s", name);
printf("you entered %s", name);
}
变量作用域
当你在 C 程序中定义一个变量时,根据你声明它的位置,它会有一个不同的 作用域(scope)。
这意味着它将会在某些地方可用,而在其它地方不可用。
该位置决定了两种类型的变量:
全局变量(global variables)
局部变量(local variables)
这就是区别:在函数内部声明的变量就是局部变量,比如这个:
int main(void) {
int age = 37;
}
局部变量只有在函数内才能访问,它们会在函数结束后不复存在。它们会被从内存中清除掉(有一些例外)。
定义在函数外部的变量就是全局变量,比如这个示例:
int age = 37;
int main(void) {
/* ... */
}
全局变量可以从程序中的任何一个函数访问,它们在整个程序的执行过程中都是可用的,直到程序结束。
我提到过局部变量在函数结束之后就不再可用。
原因是局部变量默认是在 栈(stack) 上声明的,除非你使用指针在堆中显式地分配它们。但是这样一来,你就不得不自己管理内存了。
静态变量
在函数内部,你可以使用 static 关键字初始化一个 静态变量(static variable)。
我说了“在函数内部”,因为全局变量默认就是静态的,所以没有必要再添加这个关键字。
什么是静态变量?静态变量在没有声明初始值的时候会被初始化为 0,并且它会在函数调用中保持该值。
考虑这个函数:
int incrementAge() {
int age = 0;
age++;
return age;
}
如果我们调用一次 incrementAge(),我们将会得到返回值 1。如果我们再调用一次,我们总是会得到 1,因为 age 是一个局部变量并且在每次调用该函数的时候都会被重新初始化为 0。
如果我们将该函数改为:
int incrementAge() {
static int age = 0;
age++;
return age;
}
现在我们每调用一次这个函数,我们就会得到一个增加了的值:
printf("%d\n", incrementAge());
printf("%d\n", incrementAge());
printf("%d\n", incrementAge());
将会给我们:
1
2
3
我们也可以在 static int age = 0; 中省略初始化 age 为 0 的代码,只写 static int age;,因为静态变量在创建时会自动设置为 0。
我们也可以有静态数组。这时,每一个数组元素都被初始化为 0:
int incrementAge() {
static int ages[3];
ages[0]++;
return ages[0];
}
全局变量
在这一节中,我想多谈论一点 全局变量与局部变量 之间的差异。
局部变量 被定义在函数内部,只在该函数内可用。
就像这样:
#include
int main(void) {
char j = 0;
j += 10;
printf("%u", j); //10
}
j 在 main 函数之外的任何地方都不可用。
全局变量 定义在所有函数的外部,就像这样:
#include
char i = 0;
int main(void) {
i += 10;
printf("%u", i); //10
}
全局变量可以被程序内的任何函数访问。该访问并不只局限于读取全局变量的值:任何函数都可以更新全局变量的值。
因此,全局变量是一种在函数间共享相同数据的一种方式。
局部变量的主要不同在于,分配给局部变量的内存会在函数结束之后立即释放。
全局变量只在程序结束时才会释放。
类型定义
C 中的 typedef 关键字允许你定义新的类型。
我们可以从 C 内置的类型开始创建自己的类型,使用这个语法:
typedef existingtype NEWTYPE
按照惯例,我们创建的新类型通常是大写的。
这样可以更加容易区分它,并且可以立即识别出它是一种类型。
例如,我们可以定义一个新的 NUMBER 类型,它还是 int:
typedef int NUMBER
一旦你这么做了之后,你就可以定义新的 NUMBER 变量了:
NUMBER one = 1;
现在你可能会问:为什么?为什么不直接使用内置的 int 类型呢?
嗯,当两个东西搭配在一起的时候,typedef 会变得真的很有用:枚举类型和结构体。
枚举类型
使用 typedef 和 enum 关键字,我们可以定义具有指定值的类型。
这是 typedef 关键字最重要的使用场景之一。
这是枚举类型的语法:
typedef enum {
//值……
}
按照惯例,我们创建的枚举类通常是大写的。
这里是一个简单的示例:
typedef enum {
true,
false
} BOOLEAN;
C 自带 bool 类型,所以这个示例并不实用,但是它会让你领悟到其中的精髓。
另一个示例是定义一周中的那几个日子:
typedef enum {
monday,
tuesday,
wednesday,
thursday,
friday,
saturday,
sunday
} WEEKDAY;
这里是使用这个枚举类的一个简单程序:
#include
typedef enum {
monday,
tuesday,
wednesday,
thursday,
friday,
saturday,
sunday
} WEEKDAY;
int main(void) {
WEEKDAY day = monday;
if (day == monday) {
printf("It's monday!");
} else {
printf("It's not monday");
}
}
枚举定义中的每个枚举项在内部都与一个整数配对。所以在这个示例中 monday 是 0,tuesday 是 1,以此类推。
这意味着对应的条件可以是 if (day == 0) 而不是 if (day == monday),但是对于我们人类来说,使用名字比数字更合理,所以它是一个非常便利的语法。
结构体
利用 struct 关键字,我们可以使用基本的 C 类型创建复杂的数据结构。
结构体是一组由不同类型的值组成的集合。C 中的数组被限制为一种类型,所以结构体在很多用例中会显得非常有趣。
这里是结构体的语法:
struct
//变量……
};
示例:
struct person {
int age;
char *name;
};
通过将变量添加到右花括号之后,分号之前,你可以声明类型为该结构体的变量,就像这样:
struct person {
int age;
char *name;
} flavio;
或者多个变量也行,就像这样:
struct person {
int age;
char *name;
} flavio, people[20];
这次我声明一个名为 flavio 的 person 变量,以及一个具有 20 个 person 的名为 people 的数组。
我们也可以稍后再声明变量,使用这个语法:
struct person {
int age;
char *name;
};
struct person flavio;
我们可以在声明的时候初始化一个结构体:
struct person {
int age;
char *name;
};
struct person flavio = { 37, "Flavio" };
一旦定义了结构体,我们就可以使用一个点(.)来访问它里面的值了:
struct person {
int age;
char *name;
};
struct person flavio = { 37, "Flavio" };
printf("%s, age %u", flavio.name, flavio.age);
我们也可以使用点语法改变结构体中的值:
struct person {
int age;
char *name;
};
struct person flavio = { 37, "Flavio" };
flavio.age = 38;
结构体非常有用,因为它们既可以作为函数的参数,也可以作为函数的返回值,以及它们内部的嵌入变量。每个变量都有一个标签。
注意到结构体是 复制传递 的,这一点很重要,除非,当然你可以传递一个指向结构体的指针,这种情况下它就是引用传递。
使用 typedef,我们可以简化处理结构体时的代码。
咱们看一个示例:
typedef struct {
int age;
char *name;
} PERSON;
按照惯例,我们使用 typedef 创建的结构体通常是大写的。
现在,我们可以像这样声明一个新的 PERSON 变量:
PERSON flavio;
并且我们可以用这种方式在声明的时候初始化它们:
PERSON flavio = { 37, "Flavio" };
命令行参数
在 C 程序中,你可能需要在命令启动时从命令行接收参数。
对于简单的需求而言,你只需要将 main() 函数的签名从
int main(void)
修改为
int main (int argc, char *argv[])
argc 是一个整数,包含从命令行提供的参数的数量。
argv 是一个字符串数组。
当程序开始运行时,我们用这两个参数给主函数提供参数。
注意 argv 数组中总是至少有一个元素:程序的名字。
咱们以我们用来运行程序的 C 编译器作为示例吧,就像这样:
gcc hello.c -o hello
如果这就是我们的程序,我们的 argc 将会是 4,argv 将是一个包含以下内容的数组:
gcc
hello.c
-o
hello
咱们写一个打印它收到的参数的程序吧:
#include
int main (int argc, char *argv[]) {
for (int i = 0; i < argc; i++) {
printf("%s\n", argv[i]);
}
}
如果我们的程序名为 hello,并且我们像这样运行它:./hello,我们就会得到以下输出:
./hello
如果我们传递一些随机参数,就像这样:./hello a b c,我们竟会在终端中得到这个输出:
./hello
a
b
c
对于简单的需求而言,这个系统工作得很好。对于更加复杂的需求,有一些常用的包,比如 getopt。
头文件
简单的程序可以直接放在单个文件中。但是当你的程序变大,将它放在单个文件中就不可能了。
你可以将程序一些部分移动到一个单独的文件中,然后创建一个 头文件。
头文件看起来就像普通的 C 文件一样,但是它是以 .h 而不是 .c 结尾的。它里面的内容是 声明,而不是函数的实现和程序的其它部分。
你已经在第一次使用 printf() 函数或其它 I/O 函数的时候使用过头文件了,如果你要使用它,需要输入以下内容:
#include
#include 是一个预处理器指令。
该预处理器会在标准库中寻找 stdio.h 文件,因为你使用了花括号包裹它。若要包含你自己的头文件,你需要使用引号("),就像这样:
#include "myfile.h"
上述代码会让预处理器在当前文件夹内寻找 myfile.h。
你也可以使用文件夹结构的库:
#include "myfolder/myfile.h"
咱们看一个示例。这个程序计算自给定年份以来的年数:
#include
int calculateAge(int year) {
const int CURRENT_YEAR = 2020;
return CURRENT_YEAR - year;
}
int main(void) {
printf("%u", calculateAge(1983));
}
假设我想将 caculateAge 函数移到一个单独的文件中。
我创建一个名为 calculate_age.c 的文件:
int calculateAge(int year) {
const int CURRENT_YEAR = 2020;
return CURRENT_YEAR - year;
}
我还创建了一个名为 calculate_age.h 的文件,我在其中放入了 函数原型,除了函数体,它与 .c 文件中的函数完全相同:
int calculateAge(int year);
现在在主 .c 文件中,我们可以移除 calculateAge() 函数的定义,并且我们可以导入 calculate_age.h,它会让 calculateAge() 函数可用:
#include
#include "calculate_age.h"
int main(void) {
printf("%u", calculateAge(1983));
}
别忘了编译多个文件组成的程序,你需要在命令行中列出它们,就像这样:
gcc -o main main.c calculate_age.c
如果配置更加复杂,一个告诉编译器如何编译该程序的 Makefile 是必需的。
预处理器
预处理器是一个工具,当我们用 C 编程时,它对我们有很大的帮助。它是 C 标准的一部分,就像语言本身、编译器和标准库一样。
它解析我们的程序,确保编译器在处理之前获得所有需要的东西。
在实践中,它是做什么的呢?
例如,它查找你使用 #include 指令包含的所有头文件。
它还查看你使用 #define 定义的每个常量并将其替换为实际的值。
这只是一个开始。我提到了这两个操作,是因为它们是最常见的两个。预处理器能做的事情还有很多。
你有注意到 #include 和 #define 在开头有一个 # 吗?那在预处理器指令中是很常见的。如果某一行以 # 开始,它就会被预处理器关照。
条件
我们能做的一件事情是使用条件让表达式决定程序的编译方式。
例如,我们可以检查 DEBUG 常量是否为 0:
#include
const int DEBUG = 0;
int main(void) {
#if DEBUG == 0
printf("I am NOT debugging\n");
#else
printf("I am debugging\n");
#endif
}
符号常量
我们可以定义一个 符号常量(symbolic constant):
#define VALUE 1
#define PI 3.14
#define NAME "Flavio"
当我们在自己的程序中使用 NAME 或 PI 或 VALUE 时,预处理器会在执行程序之前将名字替换成对应的值。
符号常量非常有用,因为我们可以给值名字,而不用在编译时创建变量。
宏
我们还可以使用 #define 定义 宏(macro)。宏与符号常量之间的差别在于:宏可以接受一个参数,并且通常包含代码,而符号常量只是一个值:
#define POWER(x) ((x) * (x))
注意参数两侧的括号:当宏在预编译过程中被替换时,这是一个避免问题的好方法。
然后我们可以在代码中使用它,像这样:
printf("%u\n", POWER(4)); //16
它与函数之间的一个大差别就是:宏不会声明参数或返回值的类型,这在一些场景中可能很方便。
然而,宏的定义被限制成只有一行。
If defined
我们可以使用 #ifdef 来检查某个符号常量或宏是否被定义过:
#include
#define VALUE 1
int main(void) {
#ifdef VALUE
printf("Value is defined\n");
#else
printf("Value is not defined\n");
#endif
}
我们也可以使用 #ifndev 检查对立面(宏未定义)。
我们还可以使用 #if defined 和 #if !defined 来达到同样的目的。
像这样将一些代码块包裹到单个块中是很常见的:
#if 0
#endif
这样可以临时防止程序运行,也可以使用一个 DEBUG 符号常量:
#define DEBUG 0
#if DEBUG
// 当 DEBUG 不为 0 时,代码才会被发给编译器
#endif
你可以使用的预定义的符号常量
预处理器还定义了很多你可以直接使用的符号常量,它们的名字的前后有两个下划线作为标识,包括:
__LINE__ 代表源代码文件中的当前行
__FILE__ 代表文件的名字
__DATE__ 表示编译日期,格式为 Mmm gg aaaa
__TIME__ 表示编译实践,格式为 hh:mm:ss
结语
非常感谢阅读本手册!
我希望它将鼓励你去了解更多有关 C 的知识。
若想查看更多教程,你可以访问我的博客。
通过 hey@flaviocopes.com 给我发送反馈、勘误或者意见。
记住:你可以从这里获得这本手册的 PDF 或 ePub 版本。
你可以在 Twitter @flaviocopes 联系我。
原文:The C Beginner's Handbook: Learn C Programming Language basics in just a few hours,作者:Flavio Copes
Nicholas Zhan
阅读 更多文章。
在 freeCodeCamp 免费学习编程。 freeCodeCamp 的开源课程已帮助 40,000 多人获得开发者工作。开始学习
freeCodeCamp 是捐助者支持的 501(c)(3) 条款下具有免税资格的慈善组织(税号:82-0779546)。
我们的使命:帮助人们免费学习编程。我们通过创建成千上万的视频、文章和交互式编程课程——所有内容向公众免费开放——来实现这一目标。
所有给 freeCodeCamp 的捐款都将用于我们的教育项目,购买服务器和其他服务,以及聘用员工。
你可以点击此处免税捐款。
精选文章
about:blank 是什么意思
打开 .dat 文件
Node 最新版本
反恶意软件服务
Windows10 产品密钥
Git 切换分支
AppData 文件夹
Windows 10 屏幕亮度
JSON 注释
MongoDB Atlas 教程
Python 字符串转数字
Git 命令
更新 NPM 依赖
谷歌恐龙游戏
CSS 使用 SVG 图片
Python 获取时间
Git Clone 指定分支
JS 字符串反转
React 个人作品网站
媒体查询范围
forEach 遍历数组
撤销 Git Add
OSI 七层网络
Event Loop 执行顺序
CMD 删除文件
Git 删除分支
HTML 表格代码
Nano 怎么保存退出
HTML5 模板
学习编程
移动应用
我们的慈善机构
简介
校友网络
开源
商店
支持
赞助商
学术诚信
行为规范
隐私条例
服务条款
版权条例
C语言 - 维基百科,自由的百科全书
C语言 - 维基百科,自由的百科全书
跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页分类索引特色内容新闻动态最近更改随机条目资助维基百科
帮助
帮助维基社群方针与指引互助客栈知识问答字词转换IRC即时聊天联络我们关于维基百科
搜索
搜索
创建账号
登录
个人工具
创建账号 登录
未登录编辑者的页面 了解详情
贡献讨论
目录
移至侧栏
隐藏
序言
1概述
2歷史
3語法
4Hello World 程序
5内存管理
6库
7工具軟體
8經典錯誤
9参见
10註腳
开关註腳子章节
10.1注解
10.2參考資料
11參考資料
12外部連結
开关目录
C语言
120种语言
AfrikaansAlemannischአማርኛAragonésالعربيةالدارجةঅসমীয়াAsturianuAzərbaycancaتۆرکجهŽemaitėškaБеларускаяБеларуская (тарашкевіца)БългарскиभोजपुरीবাংলাBrezhonegBosanskiBasa UgiCatalà閩東語 / Mìng-dĕ̤ng-ngṳ̄CorsuČeštinaЧӑвашлаCymraegDanskDeutschΕλληνικάEnglishEsperantoEspañolEestiEuskaraفارسیSuomiFrançaisGaeilgeGalegoગુજરાતી客家語/Hak-kâ-ngîעבריתहिन्दीHrvatskiMagyarՀայերենInterlinguaBahasa IndonesiaIdoÍslenskaItaliano日本語JawaქართულიTaqbaylitҚазақшаភាសាខ្មែរಕನ್ನಡ한국어KurdîКыргызчаLatinaLombardລາວLietuviųLatviešuमैथिलीMalagasyМакедонскиമലയാളംМонголꯃꯤꯇꯩ ꯂꯣꯟमराठीBahasa Melayuမြန်မာဘာသာनेपालीNederlandsNorsk nynorskNorsk bokmålOccitanଓଡ଼ିଆਪੰਜਾਬੀPolskiPiemontèisپنجابیPortuguêsRuna SimiRomânăРусскийСаха тылаᱥᱟᱱᱛᱟᱲᱤScotsSrpskohrvatski / српскохрватскиසිංහලSimple EnglishSlovenčinaSlovenščinaShqipСрпски / srpskiSvenskaKiswahiliதமிழ்తెలుగుТоҷикӣไทยTagalogTürkçeТатарча / tatarçaУкраїнськаاردوOʻzbekcha / ўзбекчаVènetoTiếng ViệtWinaray吴语IsiXhosaייִדישⵜⴰⵎⴰⵣⵉⵖⵜ ⵜⴰⵏⴰⵡⴰⵢⵜ文言Bân-lâm-gú粵語
编辑链接
条目讨论
不转换
不转换简体繁體大陆简体香港繁體澳門繁體大马简体新加坡简体臺灣正體
阅读编辑查看历史
工具
工具
移至侧栏
隐藏
操作
阅读编辑查看历史
常规
链入页面相关更改上传文件特殊页面固定链接页面信息引用本页获取短URL下载二维码维基数据项目
打印/导出
下载为PDF打印页面
在其他项目中
维基共享资源维基教科书
维基百科,自由的百科全书
「C程序设计语言」重定向至此。關於书籍,請見「C程序设计语言 (书)」。
本條目存在以下問題,請協助改善本條目或在討論頁針對議題發表看法。
本條目或許劃分有過多章節以致內容分散。請協助改善條目,統整相近或很小的章節並除去不必要的副標題。
此條目應避免有陳列雜項、瑣碎資料的部分。 (2020年6月18日)請協助將有關資料重新編排成連貫性的文章,安置於適當章節或條目內。
C語言《C程序设计语言》,第一部介绍C语言的书籍编程范型程序式指令式编程(过程式)、结构化编程設計者丹尼斯·里奇(Dennis Ritchie)實作者丹尼斯·里奇(Dennis Ritchie)和肯·汤普逊(Ken Thompson)发行时间1972年,52年前(1972)当前版本C18 (C语言标准) (2018年6月;穩定版本)C2x (2020年12月11日;預覽版本)[1][2]
型態系統静态, 弱类型, 明示(英语:Manifest typing), 名称(英语:Nominal type system)操作系统跨平台網站www.iso.org/standard/74528.html 主要實作產品Clang、GCC、MSVC、Turbo C、Watcom C啟發語言B(BCPL、CPL)、ALGOL 68[3]、組合語言、PL/I、FORTRAN影響語言大量,如:awk、BitC(英语:BitC)、csh、C++、C#、D、Java、JavaScript、Objective-C、Perl、PHP、Rust等
維基教科書中有關C Programming的文本
C语言(英語:C Language)是一种通用的、过程式编程程式語言,支持结构化编程、词法作用域和递归,使用静态类型系统,并且广泛用于系统软件与应用软件的开发。
C语言于1969年至1973年間,為了移植與開發UNIX作業系統,由丹尼斯·里奇與肯·汤普逊,以B语言为基础,在贝尔实验室設計、开发出來。二十世纪八十年代,C语言应用日渐广泛。為了避免各開發廠商用的C語言的語法產生差異,美國國家標準局為C語言訂定了一套完整的國際標準語法,稱為ANSI C,作為C語言的標準。与此同时,国际标准化组织也接受该标准为国际标准。因此,ANSI C也同时被称为ISO C。二十世纪八十年代至今的有关程式開發工具,一般都支持符合ANSI C的語法。
C语言具有高效、灵活、功能丰富、表达力强和較高的可移植性等特点,在程式設計中备受青睐,成为最近25年使用最为广泛的编程语言[4]。目前,C语言編譯器普遍存在於各種不同的操作系统中,例如Microsoft Windows、macOS、Linux、Unix等。C語言的設計影響了众多後來的程式語言,例如C++、Objective-C、Java、C#等。现行的许多软件都是由C语言或者其影响和衍生的编程语言开发出来的。
概述[编辑]
与ALGOL一族的大多数过程式编程语言类似,C語言是一個有結構化程式設計、具有变量作用域(variable scope)以及遞迴功能的程序式語言。其采用的静态类型系统可以防止无意的程序设计操作。C语言中所有的可执行代码都被包含在子程序(函数)裡。其傳遞參數均是以值傳遞(pass by value)[5],另外也可以傳遞指针(a pointer passed by value)。C语言是自由形式语言,即其源代码的缩进并不影响程序的功能,而是使用分号作为语句的结尾,花括号来表示代码块。
由于C语言的语言规模较小,若干高层的机制需要使用定义的函数来提供。比如,C语言并没有直接处理复合对象(例如字符串、集合、列表、数组等)的操作,也没有对于存储器分配工具和内存回收工具的直接定义,同时也本身不具有输入和输出以及文件访问的方法。然而,用户定义的函数和C语言标准库中的函数为这些高层的机制提供了可能性。[6]
C语言也具有以下的特性:[6]
基本数据类型包括字符、整型和浮点数等。另外也有派生的各种数据类型,如指针、数组、结构和联合。
部份的变量類型可以轉換,例如整數型和字符型变量。
透過指標(pointer),C語言可以容易的對記憶體進行低階控制。
不同的變數類型可以用結構体(struct)組合在一起。
具有基本的控制流:语句组、条件判断、多路选择、循环等。
函数可以返回各种数据类型的值,并且都可以递归调用。每次调用函数会重新创建变量。
C语言只有32個保留字(reserved keywords),使变量、函數命名有更多彈性。
编译预处理(preprocessor)讓C語言的編譯更具有彈性。
歷史[编辑]
主条目:C语言的历史
20世纪70年代,肯·汤姆森为了使其设计的Unix系统更加高效,使用B语言的变种(即C语言)在DEC PDP-7计算机上重写了Unix。C语言中许多重要概念来源于BCPL语言,其对C语言的影响也间接地来源于B语言。在1978年,丹尼斯·里奇和布萊恩·柯林漢合作出版了《C程序设计语言》第一版,事实上即为K&R C标准[7]。1983年,为了制定一个独立于具体机器且无歧义的C语言标准,美国国家标准协会成立了一个委员会,并在1988年完成了该标准的制定,即ANSI C。此标准同时被国际标准化组织所采纳,也被称作ISO C。
其后,C语言至今经历了几次标准更新,诞生了C99、C11和目前最新的标准C18。C语言标准的下一次更新C2x目前正在起草中。
語法[编辑]
主条目:C语言语法
此章节需要扩充。
C語言的语法相对简洁而直接。C语言的形式文法由国际标准化组织所制定。[8]簡單來說,C語言包括如下文法:
作为一种指令式编程语言,C语言使用语句执行操作。最常见的语句是表达式语句,由一个表达式后加一个分号组成,可以令系统调用函数和为变量赋值;
註釋: C语言支持单行注释(以//开头)和多行注释(以/*开始,以*/结束);
数据类型: 基本的数据类型包括整数(int)、浮点数(float和double)、字符(char)、枚舉enum等;
数组: 数组是一组相同类型的数据元素的集合。使用以下方法初始化一個五個元素的整數數組:int numbers[5] = {1, 2, 3, 4, 5};
封裝結構:结构(struct)、联合(union);
結構化編程和控制结构: C语言包括条件语句(if、else)、循环语句(for、while、do-while)等;
跳轉語句:C語言允許使用跳轉關鍵字goto、break和continue來實現程序塊之間的跳轉,這和匯編語言的jmp關鍵字有一定相似處;
函数: C语言中的函数是程序的基本模块,可以自定义函数并在程序中调用;
靈活且靠近底層的內存控制機制:C程序員可以自由選擇分配何種內存,以及分配多大的內存,如如下代碼所示:int *array = (int *)malloc(5 * sizeof(int)); // 分配一個包含五個整數的數組
free(array); // 釋放使用malloc分配的內存
Hello World 程序[编辑]
主条目:Hello World
Brian Kernighan于1978年亲笔书写的“Hello World”程序
"对于所有语言的初学者来说,编写的第一个程序几乎都是相同的,即‘请打印出下列内容 hello, world’"– 《C程序设计语言》[6]
现在广泛被编程初学者使用的"hello, world"程序实例最初就是出现在《C程序设计语言》第一版中。下面是一個在標準輸出設備(stdout)上打印出 "Hello, world!" 字串的簡單程式。類似的程式,通常作為初學程式語言時的第一個程式:
#include
int main(void) {
printf("Hello, world!\n");
return 0;
}
其中只有int,void,return为C语言的关键字,预处理器会将#include
main函数是C语言程序的入口点。
"Hello, world!\n"中的\n是一个转义字符,形式为\加上一个字符。所起的作用在ASCII码中规定。
printf是声明于stdio.h的函数,关于printf的更多细节,参见printf;
关于格式化字符串的更多信息,参见格式化字符串。
内存管理[编辑]
C语言的特色之一是:程序员必须亲自处理内存的分配细节。语言不负责内存边界检查,这是因为在运行时进行内存边界检查会造成性能问题,与UNIX哲学不符。此特性容易导致缓冲区溢出问题。然而,部分编译器(如英特尔编译器)会出于安全性的考量,提供方法以进行运行时内存边界检查[9]。
大多数C语言实现使用栈(Stack)来保存函数返回地址/栈帧基址、完成函数的参数传递和函数局部变量的存储。然而,在部分极特殊的平台上,使用栈并不能获得最大效率。此时的实现由编译器决定[10]。
如果程序需要在运行的过程中动态分配内存,可以利用堆(Heap)来实现。
基本上C程序的元素存储在内存的时候有3种分配策略:
静态分配
如果一个变量声明为全局变量或者是函数的静态变量,这个变量的存储将使用静态分配方式。静态分配的内存一般会被编译器放在数据段或代码段来存储,具体取决于实现。这样做的前提是,在编译时就必须确定变量的大小。
以IA32的x86平台及gcc编译器为例,全局及静态变量放在数据段的低端;全局及静态常量放在代码段的高端。
自动分配
函数的自动局部变量应该随着函数的返回会自动释放(失效),这个要求在一般的体系中都是利用栈(Stack)来满足的。相比于静态分配,这时候,就不必绝对要求这个变量在编译时就必须确定变量的大小,运行时才决定也不迟,但是C89仍然要求在编译时就要确定,而C99放松了这个限制。但无论是C89还是C99,都不允许一个已经分配的自动变量运行时改变大小。
所以说C函数永远不应该返回一个局部变量的地址。
要指出的是,自动分配也属于动态分配,甚至可以用alloca函数来像分配堆(Heap)一样进行分配,而且释放是自动的。
动态分配
还有一种更加特殊的情况,变量的大小在运行时有可能改变,或者虽然单个变量大小不变,变量的数目却有很大弹性,不能静态分配或者自动分配,这时候可以使用堆(Heap)来满足要求。ANSI C定义的堆操作函数是malloc、calloc、realloc和free。
使用堆(Heap)内存将带来额外的开销和风险。
库[编辑]
主条目:C 標準函式庫
C語言的标准文档要求了一个平台移植C语言的时候至少要实现的一些功能和封装的集合,称为“标准库”,标准庫的声明头部通過预处理器命令#include進行引用。
在C89標準中:
文件
简介说明
断言相关
字符类型判断
标准报错机制
浮点运算
各种体系结构限制
本地化接口
数学函数
跨函数跳转
信号(类似UNIX的信号定义,但是差很远)
可变参处理
一些标准宏定义
标准I/O库
标准工具库函数
ASCII字符串及任意内存处理函数
时间相关
在94年的修正版中
在C99中增加了六個函式庫
以上是C语言的标准。各个系统各自又对C库函数进行的各种扩充,就浩如烟海了。如POSIX C、GNU C等。
工具軟體[编辑]
工具軟體可以幫助程式設計者避免一些程式中潛藏或容易出現的問題,例如常會造成程式未預期動作或是執行期錯誤的程式碼。
許多語言都有自動源代碼檢查及審計工具,C語言也有類似工具,像是Lint。可以在程式剛寫好時用Lint找出可能有問題的程式,通過Lint後再用C編譯器進行編譯,許多編譯器也可以設定是否要針對一些可能有問題的程式碼提出警告。MISRA C是一套針對嵌入式系統的法則,可主要也是避免一些可能有問題的程式碼。
也有一些編譯器、程式庫或作業系統可以處理一些非標準C語言的功能,例如邊界值檢查、缓存溢出偵測、序列化及自動垃圾回收功能。
使用像Valgrind或IBM Rational Purify(英语:Purify)等軟體工具,或者連結有特別malloc函式的程式庫,有助於找出一些運行期記憶體使用的問題。
經典錯誤[编辑]
“void main()”的用法并不是任何标准制定的[11][12]。 C語言标准語法是“int main()”,任何实现都必须支持int main(void) { /* ... */ }和int main(int argc, char* argv[]) { /* ... */ }[13]。 在 C++ 標準中,main的標準型態應是int,否则类型是由实现定义的。任何实现都必须支持int main() { /* ... */ }和int main(int argc, char* argv[]) { /* ... */ }[14]。
参见[编辑]
块 (C语言扩展)
註腳[编辑]
注解[编辑]
參考資料[编辑]
^ History of C. 2020年12月13日 [2020年10月24日] (英語). 引文格式1维护:未识别语文类型 (link)
^ Programming languages — C (PDF). 2020年12月11日 [2020年12月17日] (英語). 引文格式1维护:未识别语文类型 (link)
^ Ritchie, Dennis M. The Development of the C Language. January 1993 [2008-01-01]. (原始内容存档于2015-02-03). The scheme of type composition adopted by C owes considerable debt to Algol 68, although it did not, perhaps, emerge in a form that Algol's adherents would approve of.
^ TIOBE Programming Community Index [TIOBE编程社区指数]. 2012 [2012-11-03]. (原始内容存档于2018-12-25) (英语).
^ Brian W. Kernighan and Dennis M. Ritchie. The C programming Language. Prentice-Hall. 1988. ISBN 0-13-110362-8 (英语). In C, all function arguments are passed ``by value.
^ 6.0 6.1 6.2 Dennis M. Ritchie,Brian W. Kernighan. C程序设计语言. 北京: 机械工业出版社. 2004年1月 [2020-06-10]. ISBN 9787111128069 (中文).
^ Stephen Prata. C Primer Plus(第5版). 北京: 人民邮电出版社. 2005年2月: 3-4 [2020-07-15]. ISBN 9787115130228 (中文).
^ ISO/IEC JTC1/SC22/WG14 - C. [2022-04-02]. (原始内容存档于2018-02-12) (英语).
^ check-pointers, Qcheck-pointers. Intel. [2021-06-01]. (原始内容存档于2021-02-15) (英语).
^ ISO/IEC 9899:2018 (PDF). [2020-06-10]. (原始内容存档 (PDF)于2020-07-22).
^ Can I write "void main()"? (页面存档备份,存于互联网档案馆)The definition void main() { /* ... */ } is not and never has been C++, nor has it even been C.
^ 用 C99 进行开放源代码的开发. [2011-01-21]. (原始内容存档于2011-08-12).
^ 「The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters: int main(void) { /* ... */ } or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared): int main(int argc, char *argv[]) { /* ... */ } or equivalent; or in some other implementation-defined manner.」,引自ISO/IEC 9899:1999, Section 5.1.2.2.1 Program startup
^ 「An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both of the following definitions of main: int main() { /* ... */ } and int main(int argc, char* argv[]) { /* ... */ }.」,引自 ISO/IEC 14882, 第一版(1998)、第二版(2003)與第三版(2011), section 3.6.1 Main function
參考資料[编辑]
Brian Kernighan, Dennis Ritchie: The C Programming Language. 亦被称作K&R,第一部介绍C语言的书籍。
第一版, Prentice Hall 1978; ISBN 978-0-13-110163-0. ANSI/ISO标准化之前的C。
第二版, Prentice Hall 1988; ISBN 978-0-13-110362-7. ANSI/ISO C。
中译本第二版,机械工业出版社 2004; ISBN 978-7-11-112806-9。
ISO/IEC 9899. The official C:1999 standard, along with technical corrigenda and a rationale. As of 2005 the latest version is ISO/IEC 9899:TC2.
Samuel P. Harbison, Guy L. Steele: C: A Reference Manual. This book is excellent as a definitive reference manual, and for those working on C compilers. The book contains a BNF grammar for C.
4th, Prentice Hall 1994; ISBN 978-0-13-326224-7.
5th, Prentice Hall 2002; ISBN 978-0-13-089592-9.
Derek M. Jones: The New C Standard: A Cultural and Economic Commentary, Addison-Wesley, ISBN 978-0-201-70917-9, online material
Robert Sedgewick: Algorithms in C, Addison-Wesley, ISBN 978-0-201-31452-6 (Part 1–4) and ISBN 978-0-201-31663-6 (Part 5)
William H. Press, Saul A. Teukolsky, William T. Vetterling, Brian P. Flannery: Numerical Recipes in C (The Art of Scientific Computing), ISBN 978-0-521-43108-8
外部連結[编辑]
维基共享资源中相关的多媒体资源:C语言
Coding Programmer Page / C Library Reference and Examples(页面存档备份,存于互联网档案馆) (english)
GCC 首页(页面存档备份,存于互联网档案馆)
GLIBC2 首页(页面存档备份,存于互联网档案馆)
Visual Studio Express 首頁(页面存档备份,存于互联网档案馆)
ISO/IEC 9899(页面存档备份,存于互联网档案馆)。C99标准的官方网站。目前(2020年)可直接下载的标准文本是 ISO/IEC 9899:202x(页面存档备份,存于互联网档案馆)。
查论编C语言
《C程序设计语言》(K&R C)
历史
ANSI C
C99
C11
C18
C23(英语:C23_(C_standard_revision))
嵌入式C语言
MISRA C
特性
Functions
头文件
字符串
语法
预处理器
数据类型
指针
函式庫
glibc
C標準函式庫
C POSIX library
Dietlibc
uClibc
Newlib
EGLIBC
Bionic
klibc
musl
編譯器
Clang
GCC
MSVC
Intel C++
Borland Turbo C
LCC
Pelles C
PCC
TCC
C++/CLI
C++/CX
Watcom C/C++ 编译器
C與其他的程式語言
C与C++
兼容性
運算子
Pascal与C的比较(英语:Comparison of Pascal and C)
C to Java byte-code compiler
派生的程式語言
C++
C#
Objective-C
D語言
Alef(英语:Alef (programming language))
Limbo
Go
Vala
C/C++的整合開發環境
分类
查论编程序设计语言范型过程式
FORTRAN
COBOL
JOVIAL
ALGOL 60
JOSS(英语:JOSS)
BASIC
QB64(英语:QB64)
PL/I
MUMPS(英语:MUMPS)
ALGOL 68
Forth
Pascal
Turbo Pascal
C
Modula-2
Ada 83
occam
Oberon
Go
Zig
面向对象
Simula 67
Smalltalk
Objective-C
Eiffel
Object Pascal
Delphi
Self
Visual Basic
Gambas
Ada 95
Java
C#
Vala
Fantom(英语:Fantom (programming language))
Crystal(英语:Crystal (programming language))
多范型
C++
Modula-3
Dylan
Python
Lua
JavaScript
Ruby
D
Factor
Scala
F#
F*
Haxe
Dafny(英语:Dafny)
Nim
Rust
Dart
Julia
Swift
Bosque(英语:Bosque (programming language))
函数式
LISP
Scheme
Common Lisp
Clojure
Logo
APL/J
ML
Standard ML
OCaml
Erlang
Elixir
Haskell
Curry
SAC
Agda
Idris
Pure(英语:Pure (programming language))
jq(英语:jq (programming language))
Cuneiform
逻辑式
Prolog
Datalog
Mercury
AnsProlog
脚本语言动态语言
SNOBOL
Icon
REXX
Perl
Raku
Tcl/Tk
CLOS
newLISP
Python
Lua
Ruby
PHP
Hack
CFML(英语:ColdFusion Markup Language)
REBOL
Red(英语:Red (programming language))
Julia
Shell语言
Unix shell
sh/ash
csh/tcsh
ksh
bash
zsh
rc(英语:rc)
fish
sed
AWK
PowerShell
ECMA-262
ECMAScript
JavaScript
TypeScript
CoffeeScript/LiveScript(英语:LiveScript (programming language))
Elm
PureScript
Reason
特定平台.NET
C#
C++/CLI
F#
PowerShell
VB.NET
Small Basic
JVM
Java
AspectJ(英语:AspectJ)
Scala
Clojure
Groovy
Kotlin
特定领域科学计算
Speakeasy(英语:Speakeasy (computational environment))
IDL
GDL
Maxima
Maple
MATLAB
Octave
Scilab
Wolfram
R
Yorick(英语:Yorick (programming language))
SageMath
Julia
GPU计算
Cg/HLSL
GLSL
Brook(英语:BrookGPU)
OpenCL
SYCL
CUDA/PTX(英语:Parallel Thread Execution)
Futhark
SPIR-V(英语:Standard Portable Intermediate Representation)
数据查询
SQL
PL/SQL
T-SQL
SQL/PSM(英语:SQL/PSM)
xBase(英语:xBase)
XPath
XQuery(英语:XQuery)
GraphQL
可视化
Simulink
LabVIEW
Orange(英语:Orange (software))
KNIME(英语:KNIME)
Scratch
Snap!
Power Fx
传媒设计
SuperCollider
Pure Data
Processing
ChucK
其它
汇编语言
APT(英语:APT (programming language))
GPSS(英语:GPSS)
dc
make
PostScript
XSLT
LLVM IR
WebAssembly
目录
列表
历史
比较(英语:Comparison of programming languages)
时间线(英语:Timeline of programming languages)
查论编肯·汤普逊操作系统
Unix
貝爾實驗室九號計畫
编程语言
B語言
Bon(英语:Bon (programming language))
C语言
Go
软件
Belle(英语:Belle (chess machine))
QED(英语:QED (text editor))
ed
Sam(英语:Sam (text editor))
星际旅行 (1969年游戏)
Thompson shell
字符编码
UTF-8
规范控制
BNF: cb119665180 (data)
FAST: 843279
GND: 4113195-2
J9U: 987007293665105171
LCCN: sh85018532
NKC: ph116955
SUDOC: 027672441
取自“https://zh.wikipedia.org/w/index.php?title=C语言&oldid=81835190”
分类:C語言C語言家族美国发明跨平台軟體过程式编程语言静态类型编程语言系統程式語言ISO标准化编程语言1972年建立的程式語言隐藏分类:引文格式1维护:未识别语文类型CS1英语来源 (en)包含過多章節的條目自2020年6月需要清理的內容瑣碎條目含有多个问题的条目使用未知编程语言信息框参数的页面扩充中的条目所有扩充中的条目拒绝当选首页新条目推荐栏目的条目使用小型訊息框的頁面包含BNF标识符的维基百科条目包含FAST标识符的维基百科条目包含GND标识符的维基百科条目包含J9U标识符的维基百科条目包含LCCN标识符的维基百科条目包含NKC标识符的维基百科条目包含SUDOC标识符的维基百科条目使用ISBN魔术链接的页面
本页面最后修订于2024年3月9日 (星期六) 16:45。
本站的全部文字在知识共享 署名-相同方式共享 4.0协议之条款下提供,附加条款亦可能应用。(请参阅使用条款)
Wikipedia®和维基百科标志是维基媒体基金会的注册商标;维基™是维基媒体基金会的商标。
维基媒体基金会是按美国国內稅收法501(c)(3)登记的非营利慈善机构。
隐私政策
关于维基百科
免责声明
行为准则
开发者
统计
Cookie声明
手机版视图
开关有限宽度模式
【通俗易懂】C语言教程----初识C语言 - 知乎
【通俗易懂】C语言教程----初识C语言 - 知乎切换模式写文章登录/注册【通俗易懂】C语言教程----初识C语言C语言yyds1.什么是C语言?C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易 的方式编译、处理低级存储器、产 生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。 尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的 C语言程序可在许多电脑平台上进 行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制 定了一套完整的美国国家标准语 法,称为ANSI C,作为C语言最初的标准。目前2011年12月8日,国际标准化组织(ISO)和 国际电工委员会(IEC)发布的C11 标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。 其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。2. 第一个C语言程序#include
int main()//main()是主函数
{
printf("hello world\n");//printf()是输出函数,'\n'是换行的意思
return 0;//使程序退出,0的意思是程序正常退出
}
//解释:
//main函数是程序的入口
//一个工程中main函数有且仅有一个程序执行结果:3. 数据类型char //字符数据类型short //短整型int //整形long //长整型long long //更长的整形float //单精度浮点数double //双精度浮点数//C语言有没有字符串类型?答案:C语言本身并没有字符串类型,我们在C语言程序中使用的字符串实际上是字符数组,即多个字符构成的就是字符串!下面是字符串的两种定义方式:#include
int main()
{
char string1[] = "abc";
char string2[] = { 'a','b','c' };
return 0;
}这两种方式的区别并不在此处进行详细的讲解,在后面会进行详细的讲解,此处只是希望大家能够了解即可!为什么出现这么的类型?答案:一方面是能够存储更加多样的数据,便于进行数据处理;另一方面的原因就是为了能够更好节约我们的内存空间!至于为什么会这么说呢,后面关于不同数据类型所占的内存空间大小的时候大家能够了解到,并且对其能够有一个更加深入的了解。每种类型的大小是多少?#include
int main()
{
printf("%d\n", sizeof(char));
printf("%d\n", sizeof(short));
printf("%d\n", sizeof(int));
printf("%d\n", sizeof(long));
printf("%d\n", sizeof(long long));
printf("%d\n", sizeof(float));
printf("%d\n", sizeof(double));
printf("%d\n", sizeof(long double));
return 0;
}下面即为代码的运行结果:类型的使用:char ch = 'w';
int weight = 120;
int salary = 20000;3. 变量、常量生活中的有些值是不变的(比如:圆周率,性别,身份证号码,血型等等)有些值是可变的(比如:年龄,体重,薪资)。不变的值,C语言中用常量的概念来表示,变的值C语言中用变量来表示。3.1 定义变量的方法int age = 150;
float weight = 45.5f;
char ch = 'w';3.2 变量的分类局部变量全局变量#include
int global = 2019;//全局变量
int main()
{
int local = 2018;//局部变量
//下面定义的global会不会有问题?
int global = 2020;//局部变量
printf("global = %d\n", global);
return 0;
}输出结果展示:总结:上面的局部变量global变量的定义其实没有什么问题的!当局部变量和全局变量同名的时候,局部变量优先使用,这就是我们常说的局部优先原则!3.3 变量的使用#include
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = num1 + num2;
printf("sum = %d\n", sum);
return 0;
}此处简单带大家了解一下printf()函数和scanf()函数!printf()函数:输出函数。在双引号内的将进行输出,而%就是控制变量的输出格式,即起到了格式控制的作用,比如%d就是将变量以整型的形式进行打印输出到屏幕上来,%c则是以字符型的形式进行打印输出!在逗号后面的就是我们想要输出的变量,在这个地方需要大家进行注意,%格式控制一定要与后面的变量进行意义对应!scanf()函数:输入函数。跟上面的一样,%也是进行格式控制,不过此处与前面的区别就是此处是进行输入的格式控制,比如%d,就是将我们的输入的内容以整型的形式存储到我们的变量中,此处与前面也一样,都要与逗号后面的变量进行严格的对应,但此处仍然有一个需要大家进行注意的点,比如我们在输入时,我们在%d %d两个%d中间有一个空格进行分隔,那么我们在通过键盘进行输入的时候也要在两个变量中间进行分隔,即我们的输入要与双引号之间的内容进行严格第对应!由于本节旨在带大家进行初识C语言,所以不进行过多的讲解!3.4 变量的作用域和生命周期(1)作用域作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用 的,而限定这个名字的可用性的代码范围就是这个名字的作用域。1. 局部变量的作用域是变量所在的局部范围。2. 全局变量的作用域是整个工程。(2)生命周期变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。2. 全局变量的生命周期是:整个程序的生命周期。3.5 常量C语言中的常量和变量的定义的形式有所差异。C语言中的常量分为以下以下几种:字面常量const 修饰的常变量#define 定义的标识符常量枚举常量const修饰的常变量:#include
//举例
enum Sex
{
MALE,
FEMALE,
SECRET
};
//括号中的MALE,FEMALE,SECRET是枚举常量
int main()
{
//字面常量演示
3.14;//字面常量
1000;//字面常量
//const 修饰的常变量
const float pai = 3.14f; //这里的pai是const修饰的常变量
pai = 5.14;//是不能直接修改的!会报警告!!!
//#define的标识符常量 演示
#define MAX 100
printf("max = %d\n", MAX);
//枚举常量演示
printf("%d\n", MALE);
printf("%d\n", FEMALE);
printf("%d\n", SECRET);
//注:枚举常量的默认是从0开始,依次向下递增1的
return 0;
}注:上面例子上的 pai 被称为 const 修饰的常变量, const 修饰的常变量在C语言中只是在语法层面限制了 变量 pai 不能直接被改变,但是 pai 本质上还是一个变量的,所以叫常变量。4. 字符串+转义字符+注释4.1 字符串"hello bit.\n"这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符 串。注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串 内容。#include
//下面代码,打印结果是什么?为什么?(突出'\0'的重要性)
int main()
{
char arr1[] = "bit";
char arr2[] = { 'b', 'i', 't' };
char arr3[] = { 'b', 'i', 't','\0'};
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
return 0;
} 在着我们可以看到,我们在输出arr2时出现了乱码形式,为什么会出现这种情况呢?因为在arr2中并不包含字符串的结束标志即'\0',所以会出现上面的乱码!注意:1、在我们用printf()函数以字符串形式进行输出时,只有遇到'\0'才会停止输出!2、我们在使用上面arr1这种形式进行定义字符串时,在""里面的字符串中就已经自动包含了字符串的结束标志即'\0'!3、当我们在使用{}字符串的定义的 方式时我们一定要记得加上字符串的结束标志,虽然我们有时候用不到,但这却是我们必须要做的,这也是一个合格的程序员必备的素养,当然,有的时候确实并不需要加上,在新手期间,建议还是加上。4.2 转义字符假如我们要在屏幕上打印一个目录: c:\code\test.c我们该如何写代码?#include
int main()
{
printf("c:\code\test.c\n");
return 0;
}但其实打印结果是这样的: 这里就不得不提一下转义字符了。转义字符顾名思义就是转变意思。下面看一些转义字符。 下面是一个简单的练习:#include
int main()
{
//问题1:在屏幕上打印一个单引号',怎么做?
//问题2:在屏幕上打印一个字符串,字符串的内容是一个双引号“,怎么做?
printf("%c\n", '\'');
printf("%s\n", "\"");
return 0;
}下面是一道笔试题,带大家来了解一下吧!//程序输出什么?
#include
int main()
{
printf("%d\n", strlen("abcdef"));
// \62被解析成一个转义字符
printf("%d\n", strlen("c:\test\628\test.c"));
return 0;
}下面是我们在VS上的运行结果: 为什么会得到上面的结果呢?我们首先来了解一下strlen(),这个函数的作用是求字符串的长度,当遇到字符串的结束标志时将停止,但是大家需要注意一点,就是字符串的结束标志'\0'本身并不作为字符串长度的一部分。我们先看上面这一段代码,strlen()括号中的字符串内容为abcdef还有字符串的结束标志'\0',但是由于字符串的结束标志并不作为字符串长度的一部分,所以字符串的长度为6。接下来我们来看下一段代码,上面我们已经了解了转义字符,此处需要给大家明确一个概念,转义字符被我们看作成是一个字符,即使它的形式是\后面跟了1个或者多个字符,但strlen()函数只把它看成是一个字符。所以为什么我们的编译器给出上面的结果也就不难理解了,在上面的结果也就不难理解了,\t是一个转义字符,\62也是一个转义字符,为什么8不跟着一块呢?因为\后面跟的是八进制,即只包含0到7的数字,不能包含8,所以8不被包含在内!后面还有已给\t也是一个转义字符!最终得出14的结果!5. 注释代码中有不需要的代码可以直接删除,也可以注释掉 代码中有些代码比较难懂,可以加一下注释文字比如:#include
int Add(int x, int y)
{
return x + y;
}
/*C语言风格注释
int Sub(int x, int y)
{
return x-y;
}
*/
int main()
{
//C++注释风格
//int a = 10;
//调用Add函数,完成加法
printf("%d\n", Add(1, 2));
return 0;
}注释有两种风格:C语言风格的注释 /*xxxxxx*/ 缺陷:不能嵌套注释C++风格的注释 //xxxxxxxx 可以注释一行也可以注释多行6. 选择语句如果你好好学习,校招时拿一个好offer,走上人生巅峰,你女朋友继续陪在你的身边!如果你不学习,毕业等于失业,你女朋友跟你分手了!这就是选择!#include
int main()
{
int coding = 0;
printf("你会去敲代码吗?(选择1 or 0):>");
scanf("%d", &coding);
if (coding == 1)
{
printf("坚持,你会有好offer,女朋友陪在身边\n");
}
else
{
printf("毕业即失业,女朋友跟你分手\n");
}
return 0;
} 下面是运行截图:7. 循环语句C语言中如何实现循环呢?while语句-讲解for语句(后期讲)do ... while语句(后期讲) #include
int main()
{
int line = 0;
while (line <= 20000)
{
line++;
printf("我要继续努力敲代码\n");
}
if (line > 20000)
printf("好offer\n");
return 0;
}8. 函数#include
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = num1 + num2;
printf("sum = %d\n", sum);
return 0;
}
上述代码,写成函数如下:
#include
int Add(int x, int y)
{
int z = x + y;
return z;
}
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = Add(num1, num2);
printf("sum = %d\n", sum);
return 0;
}函数的特点就是简化代码,代码复用。9. 数组要存储1-10的数字,怎么存储?C语言中给了数组的定义:一组相同类型元素的集合.9.1 数组定义int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素9.2 数组的下标C语言规定:数组的每个元素都有一个下标,下标是从0开始的。数组可以通过下标来访问的。比如:int arr[10] = {0};
//如果数组10个元素,下标的范围是0-9 9.3 数组的使用#include
int main()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}运行结果如下图所示:10. 操作符算术操作符+ 加- 减* 乘/ 除% 取余运算符有很多,此处不再一一列举!后面的内容中会讲!#include
int main()
{
int a = 10;
int b = 5;
int c = 3;
printf("%d\n", a + b);
printf("%d\n", a - b);
printf("%d\n", a * b);
printf("%d\n", a / b);
printf("%d\n", a % c);
return 0;
}下面是运行结果:11. 常见关键字 auto break case char const continue default do doubleelse enumexternfloat for goto if int long register return short signedsizeof staticstruct switch typedefunion unsigned void volatile while先不进行全面的介绍,后面会逐步进行介绍的!此处先简要给大家介绍几个!11.1 关键字 typedeftypedef 顾名思义是类型定义,这里应该理解为类型重命名。比如:typedef unsigned int uint_32;
int main()
{
//观察num1和num2,这两个变量的类型是一样的
unsigned int num1 = 0;
uint_32 num2 = 0;
return 0;
}11.2 关键字static在C语言中:static是用来修饰变量和函数的修饰局部变量-称为静态局部变量修饰全局变量-称为静态全局变量修饰函数-称为静态函数11.2.1 修饰局部变量//代码1
#include
void test()
{
int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
test();
}
return 0;
}
//代码2
#include
void test()
{
//static修饰局部变量
static int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
test();
}
return 0;
}代码1运行结果: 代码2运行结果:结论:static修饰局部变量改变了变量的生命周期 让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。11.2.2 修饰全局变量注:add.c和test.c代表两个不同的源文件//代码1
//add.c
int g_val = 2018;
//test.c
int main()
{
printf("%d\n", g_val);
return 0;
}
//代码2
//add.c
static int g_val = 2018;
//test.c
int main()
{
printf("%d\n", g_val);
return 0;
}代码1正常,代码2在编译的时候会出现连接性错误。结论: 一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。11.2.3 修饰函数//代码1
//add.c
int Add(int x, int y)
{
return c + y;
}
//test.c
int main()
{
printf("%d\n", Add(2, 3));
return 0;
}
//代码2
//add.c
static int Add(int x, int y)
{
return c + y;
}
//test.c
int main()
{
printf("%d\n", Add(2, 3));
return 0;
}代码1正常,代码2在编译的时候会出现连接性错误.结论:一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。12. #define 定义常量和宏//define定义标识符常量
#define MAX 1000
//define定义宏
#define ADD(x, y) ((x)+(y))
#include
int main()
{
int sum = ADD(2, 3);
printf("sum = %d\n", sum);
sum = 10 * ADD(2, 3);
printf("sum = %d\n", sum);
return 0;
}运行结果:13. 指针13.1 内存内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。 取出变量地址如下:#include
int main()
{
int num = 10;
#//取出num的地址
//注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址)
printf("%p\n", &num);//打印地址,%p是以地址的形式打印
return 0;
}那地址如何存储,需要定义指针变量。int num = 10;
int *p;//p为一个整形指针变量
p = #指针的使用实例:#include
int main()
{
int num = 10;
int* p = #
*p = 20;
return 0;
} 以整形指针举例,可以推广到其他类型,如:#include
int main()
{
char ch = 'w';
char* pc = &ch;
*pc = 'q';
printf("%c\n", ch);
return 0;
}13.2 指针变量的大小#include
//指针变量的大小取决于地址的大小
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{
printf("%d\n", sizeof(char*));
printf("%d\n", sizeof(short*));
printf("%d\n", sizeof(int*));
printf("%d\n", sizeof(double*));
return 0;
}上述即为32位平台! 上述为64位平台! 结论:指针大小在32位平台是4个字节,64位平台是8个字节。14. 结构体结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。 比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。 这里只能使用结构体来描述了。例如:struct Stu
{
char name[20];//名字
int age; //年龄
char sex[5]; //性别
char id[15]; //学号
};结构体的初始化://打印结构体信息
struct Stu s = { "张三", 20, "男", "20180101" };
//.为结构成员访问操作符
printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);
//->操作符
struct Stu* ps = &s;
printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps -
> id);编辑于 2022-08-22 22:00C语言设计习题C(编程语言)C语言(书籍)赞同 11添加评论分享喜欢收藏申请
C 简介 | 菜鸟教程
C 简介 | 菜鸟教程
菜鸟教程 -- 学的不仅是技术,更是梦想!
首页
HTML
CSS
JavaScript
Vue
Bootstrap
NodeJS
Python3
Python2
Java
C
C++
C#
Go
SQL
Linux
jQuery
本地书签
首页
HTML
CSS
JS
本地书签
Search
Python3 教程
Python2 教程
Vue3 教程
vue2 教程
Bootstrap3 教程
Bootstrap4 教程
Bootstrap5 教程
Bootstrap2 教程
C 教程
C 语言教程
C 简介
C 环境设置
C 程序结构
C 基本语法
C 数据类型
C 变量
C 常量
C 存储类
C 运算符
C 判断
C 循环
C 函数
C 作用域规则
C 数组
C enum(枚举)
C 指针
C 函数指针与回调函数
C 字符串
C 结构体
C 共用体
C 位域
C typedef
C 输入 & 输出
C 文件读写
C 预处理器
C 头文件
C 强制类型转换
C 错误处理
C 递归
C 可变参数
C 内存管理
C 命令行参数
C 排序算法
C 语言实例
C 经典100例
C 标准库
C 标准库 - 参考手册
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 语言测验
C 语言教程
C 环境设置
C 简介
C 语言是一种通用的高级语言,最初是由丹尼斯·里奇在贝尔实验室为开发 UNIX 操作系统而设计的。C 语言最开始是于 1972 年在 DEC PDP-11 计算机上被首次实现。
在 1978 年,布莱恩·柯林汉(Brian Kernighan)和丹尼斯·里奇(Dennis Ritchie)制作了 C 的第一个公开可用的描述,现在被称为 K&R 标准。
UNIX 操作系统,C编译器,和几乎所有的 UNIX 应用程序都是用 C 语言编写的。由于各种原因,C 语言现在已经成为一种广泛使用的专业语言。
易于学习。
结构化语言。
它产生高效率的程序。
它可以处理底层的活动。
它可以在多种计算机平台上编译。
关于 C
C 语言是为了编写 UNIX 操作系统而被发明的。
C 语言是以 B 语言为基础的,B 语言大概是在 1970 年被引进的。
C 语言标准是于 1988 年由美国国家标准协会(ANSI,全称 American National Standard Institute)制定的。
截至 1973 年,UNIX 操作系统完全使用 C 语言编写。
目前,C 语言是最广泛使用的系统程序设计语言。
大多数先进的软件都是使用 C 语言实现的。
当今最流行的 Linux 操作系统和 RDBMS(Relational Database Management System:关系数据库管理系统) MySQL 都是使用 C 语言编写的。
为什么要使用 C?
C 语言最初是用于系统开发工作,特别是组成操作系统的程序。由于 C 语言所产生的代码运行速度与汇编语言编写的代码运行速度几乎一样,所以采用 C 语言作为系统开发语言。下面列举几个使用 C 的实例:
操作系统
语言编译器
汇编器
文本编辑器
打印机
网络驱动器
现代程序
数据库
语言解释器
实体工具
C 程序
一个 C 语言程序,可以是 3 行,也可以是数百万行,它可以写在一个或多个扩展名为 ".c" 的文本文件中,例如,hello.c。您可以使用 "vi"、"vim" 或任何其他文本编辑器来编写您的 C 语言程序。
本教程假定您已经知道如何编辑一个文本文件,以及如何在程序文件中编写源代码。
C11
C11(也被称为C1X)指ISO标准ISO/IEC 9899:2011。在它之前的C语言标准为C99。
新特性
对齐处理(Alignment)的标准化(包括_Alignas标志符,alignof运算符,aligned_alloc函数以及
_Noreturn 函数标记,类似于 gcc 的 __attribute__((noreturn))。
_Generic 关键字。
多线程(Multithreading)支持,包括:
_Thread_local存储类型标识符,
_Atomic类型修饰符和
增强的Unicode的支持。基于C Unicode技术报告ISO/IEC TR 19769:2004,增强了对Unicode的支持。包括为UTF-16/UTF-32编码增加了char16_t和char32_t数据类型,提供了包含unicode字符串转换函数的头文件
删除了 gets() 函数,使用一个新的更安全的函数gets_s()替代。
增加了边界检查函数接口,定义了新的安全的函数,例如 fopen_s(),strcat_s() 等等。
增加了更多浮点处理宏(宏)。
匿名结构体/联合体支持。这个在gcc早已存在,C11将其引入标准。
静态断言(Static assertions),_Static_assert(),在解释 #if 和 #error 之后被处理。
新的 fopen() 模式,("…x")。类似 POSIX 中的 O_CREAT|O_EXCL,在文件锁中比较常用。
新增 quick_exit() 函数作为第三种终止程序的方式。当 exit()失败时可以做最少的清理工作。
C 语言教程
C 环境设置
点我分享笔记
取消
分享笔记
昵称昵称 (必填)
邮箱邮箱 (必填)
引用地址引用地址
分类导航
HTML / CSSHTML 教程HTML5 教程CSS 教程CSS3 教程Bootstrap3 教程Bootstrap4 教程Bootstrap5 教程Font Awesome 教程Foundation 教程 JavaScriptJavaScript 教程HTML DOM 教程jQuery 教程AngularJS 教程AngularJS2 教程Vue.js 教程Vue3 教程React 教程TypeScript 教程jQuery UI 教程jQuery EasyUI 教程Node.js 教程AJAX 教程JSON 教程Echarts 教程Chart.js 教程Highcharts 教程Google 地图 教程 服务端Python 教程Python2.x 教程Linux 教程Docker 教程Ruby 教程Java 教程C 教程C++ 教程Perl 教程Servlet 教程JSP 教程Lua 教程Rust 教程Scala 教程Go 教程PHP 教程数据结构与算法Django 教程FastAPI 教程Zookeeper 教程设计模式正则表达式Maven 教程Verilog 教程ASP 教程AppML 教程VBScript 教程 数据库SQL 教程MySQL 教程PostgreSQL 教程SQLite 教程MongoDB 教程Redis 教程Memcached 教程 数据分析Python 教程NumPy 教程Pandas 教程Matplotlib 教程Scipy 教程R 教程Julia 教程 移动端Android 教程Swift 教程jQuery Mobile 教程ionic 教程Kotlin 教程 XML 教程XML 教程DTD 教程XML DOM 教程XSLT 教程XPath 教程XQuery 教程XLink 教程XPointer 教程XML Schema 教程XSL-FO 教程SVG 教程 ASP.NETASP.NET 教程C# 教程Web Pages 教程Razor 教程MVC 教程Web Forms 教程 Web ServiceWeb Service 教程WSDL 教程SOAP 教程RSS 教程RDF 教程 开发工具Eclipse 教程Git 教程Svn 教程Markdown 教程 网站建设HTTP 教程网站建设指南浏览器信息网站主机教程TCP/IP 教程W3C 教程网站品质
Advertisement
反馈/建议
在线实例
·HTML 实例
·CSS 实例
·JavaScript 实例
·Ajax 实例
·jQuery 实例
·XML 实例
·Java 实例
字符集&工具
· HTML 字符集设置
· HTML ASCII 字符集
· JS 混淆/加密
· PNG/JPEG 图片压缩
· HTML 拾色器
· JSON 格式化工具
· 随机数生成器
最新更新
·
Rust 宏
·
Seaborn 教程
·
Pandas 相关性分析
·
31.2k star, 免...
·
Dev Home —...
·
免费开源的 AI ...
·
11.2k star, 免...
站点信息
·
意见反馈
·
免责声明
·
关于我们
·
文章归档
关注微信
Copyright © 2013-2024 菜鸟教程
runoob.com All Rights Reserved. 备案号:闽ICP备15012807号-1
微信关注
什么是C语言?C语言的简介 - 知乎
什么是C语言?C语言的简介 - 知乎切换模式写文章登录/注册什么是C语言?C语言的简介小辰C语言是一种计算机程序设计语言,它既具有高级语言的特点,又具有汇编语言的特点它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序因此,它的应用范围广泛,不仅仅是在软件开发上,而且各类科研都需要用到C语言,具体应用比如单片机以及嵌入式系统开发语言特点:1. C是中级语言它把高级语言的基本结构和语句与低级语言的实用性结合起来。C 语言可以像汇编语言一样对位、字节和地址进行操作, 而这三者是计算机最基本的工作单元。2.C是结构式语言结构式语言的显著特点是代码及数据的分隔化,即程序的各个部分除了必要的信息交流外彼此独立。这种结构化方式可使程序层次清晰,便于使用、维护以及调试。C 语言是以函数形式提供给用户的,这些函数可方便的调用,并具有多种循环、条件语句控制程序流向,从而使程序完全结构化。3.C语言功能齐全具有各种各样的数据类型,并引入了指针概念,可使程序效率更高。而且计算功能、逻辑判断功能也比较强大,可以实现决策目的的游戏。 c语言4. C语言适用范围大适合于多种操作系统,如Windows、DOS、UNIX等等;也适用于多种机型。C语言对编写需要硬件进行操作的场合,明显优于其它解释型高级语言,有一些大型应用软件也是用C语言编写的C语言具有较好的可移植性,并具备很强的数据处理能力,因此适于编写系统软件,三维,二维图形和动画。它是数值计算的高级语言。优点1.简洁紧凑、灵活方便C语言一共只有32个关键字,9种控制语句,程序书写形式自由,区分大小写。把高级语言的基本结构和语句与低级语言的实用性结合起来。 C 语言可以像汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元。2.运算符丰富C语言的运算符包含的范围很广泛,共有34种运算符。C语言把括号、赋值、强制类型转换等都作为运算符处理。从而使C语言的运算类型极其丰富,表达式类型多样化。灵活使用各种运算符可以实现在其它高级语言中难以实现的运算。3.数据类型丰富C语言的数据类型有:整型、实型、字符型、数组类型、指针类型、结构体类型、共用体类型等。能用来实现各种复杂的数据结构的运算。并引入了指针概念,使程序效率更高。另外C语言具有强大的图形功能,支持多种显示器和驱动器。且计算功能、逻辑判断功能强大。 同时对于不同的编译器也有各种4.C是结构式语言结构式语言的显著特点是代码及数据的分隔化,即程序的各个部分除了必要的信息交流外彼此独立。这种结构化方式可使程序层次清晰,便于使用、维护以及调试。C语言是以函数形式提供给用户的,这些函数可方便的调用,并具有多种循环、条件语句控制程序流向,从而使程序完全结构化。5.语法限制不太严格,程序设计自由度大虽然C语言也是强类型语言,但它的语法比较灵活,允许程序编写者有较大的自由度。允许直接访问物理地址,对硬件进行操作由于C语言允许直接访问物理地址,可以直接对硬件进行操作,因此它既具有高级语言的功能,又具有低级语言的许多功能,能够像汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元,可用来写系统软件。生成目标代码质量高,程序执行效率高,一般只比汇编程序生成的目标代码效率低10へ20%。6.适用范围大,可移植性好C语言有一个突出的优点就是适合于多种操作系统,如DOS、UNIX、windows 98、windows NT;也适用于多种机型。C语言具有强大的绘图能力,可移植性好,并具备很强的数据处理能力,因此适于编写系统软件,三维,二维图形和动画,它也是数值计算的高级语言。缺点1. C语言的缺点主要表现在数据的封装性上,这一点使得C在数据的安全性上有很大缺陷,这也是C和C++的一大区别。2. C语言的语法限制不太严格,对变量的类型约束不严格,影响程序的安全性,对数组下标越界不作检查等。从应用的角度,C语言比其他高级语言较难掌握。3.指针是C语言的一大特色,可以说是C语言优于其它高级语言的一个重要原因。就是因为它有指针,可以直接进行靠近硬件的操作,但是C的指针操作也给它带来了很多不安全的因素。C++在这方面做了很好的改进,在保留了指针操作的同时又增强了安全性。Java取消了指针操作,提高了安全性,适合初学者使用。这些是C/C++能做的 服务器开发工程师、人工智能、云计算工程师、信息安全(黑客反黑客)、大数据 、数据平台、嵌入式工程师、流媒体服务器、数据控解、图像处理、音频视频开发工程师、游戏服务器、分布式系统、游戏辅助等发布于 2020-05-26 20:01C(编程语言)零基础学C语言(书籍)计算机语言赞同 7添加评论分享喜欢收藏申请
C 语言教程 | 菜鸟教程
C 语言教程 | 菜鸟教程
菜鸟教程 -- 学的不仅是技术,更是梦想!
首页
HTML
CSS
JavaScript
Vue
Bootstrap
NodeJS
Python3
Python2
Java
C
C++
C#
Go
SQL
Linux
jQuery
本地书签
首页
HTML
CSS
JS
本地书签
Search
Python3 教程
Python2 教程
Vue3 教程
vue2 教程
Bootstrap3 教程
Bootstrap4 教程
Bootstrap5 教程
Bootstrap2 教程
C 教程
C 语言教程
C 简介
C 环境设置
C 程序结构
C 基本语法
C 数据类型
C 变量
C 常量
C 存储类
C 运算符
C 判断
C 循环
C 函数
C 作用域规则
C 数组
C enum(枚举)
C 指针
C 函数指针与回调函数
C 字符串
C 结构体
C 共用体
C 位域
C typedef
C 输入 & 输出
C 文件读写
C 预处理器
C 头文件
C 强制类型转换
C 错误处理
C 递归
C 可变参数
C 内存管理
C 命令行参数
C 排序算法
C 语言实例
C 经典100例
C 标准库
C 标准库 - 参考手册
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 标准库 -
C 语言测验
C 简介
C 语言教程
C 语言是一种通用的、面向过程式的计算机程序设计语言。1972 年,为了移植与开发 UNIX 操作系统,丹尼斯·里奇在贝尔电话实验室设计开发了 C 语言。
C 语言是一种广泛使用的计算机语言,它与 Java 编程语言一样普及,二者在现代软件程序员之间都得到广泛使用。
当前最新的 C 语言标准为 C18 ,在它之前的 C 语言标准有 C17、C11...C99 等。
现在开始学习 C 编程!
C 在线工具
谁适合阅读本教程?
本教程是专门为需要从零开始了解 C 语言的软件程序员打造的。本教程将让您对 C 语言有足够的认识,从而提升您自己的专业知识水平。
阅读本教程前,您需要了解的知识:
在开始学习本教程之前,您需要对计算机编程术语有基本的了解。对任何一种编程语言有基本的了解将有助于您理解 C 语言编程概念,并有助于加快您的学习进度。
编译/执行 C 程序
实例
#include
int main()
{
/* 我的第一个 C 程序 */
printf("Hello, World! \n");
return 0;
}
运行实例 »
实例解析:
所有的 C 语言程序都需要包含 main() 函数。 代码从 main() 函数开始执行。
/* ... */ 用于注释说明。
printf() 用于格式化输出到屏幕。printf() 函数在 "stdio.h" 头文件中声明。
stdio.h 是一个头文件 (标准输入输出头文件) , #include 是一个预处理命令,用来引入头文件。
当编译器遇到 printf() 函数时,如果没有找到 stdio.h 头文件,会发生编译错误。
return 0; 语句用于表示退出程序。
C 简介
4 篇笔记
写笔记
#0 飞奔的蚂蚁2018 138***86735@163.com 2328运行 C 程序,main(int argc, char *argv[]) 函数传参,argc 为参数个数,argv 是字符串数组, 下标从 0 开始,第一个存放的是可执行程序的文件名字,然后依次存放传入的参数,举个例子 HelloWorld.c :
#include
int main(int argc, char *argv[])
{
/* 我的第一个 C 程序 */
printf("可执行程序 %s ,参数个数为[%d], 运行输出:[%s]\n",argv[0],argc,argv[1]);
return 0;
}
编译 gcc HelloWorld.c,得到可执行程序 a.out,运行程序:
./a.out Hello,World!
可执行程序 ./a.out ,参数个数为[2], 运行输出:[Hello,World!]飞奔的蚂蚁2018 飞奔的蚂蚁2018 138***86735@163.com6年前 (2018-05-31)
#0 codeJun 460***593@qq.com 1429当是 int main() 时,main() 的返回值是 int 类型,所以是 return 0; 现在 C 标准里规定 main() 返回值必须为 int,所以必须写成是 int main()。
#include
int main(){
/* 我的第一个 C 程序 */
printf("Hello, World!\n");
return 0;
}
当是 void main() 时,main() 的返回值是空,所以可以不写或者是 return; 但这是以前的写法了,现在很少用 void main() 了,也不推荐大家这么用。写出来的目的就是给大家提个醒,别犯一些低级错误。
#include
void main(){
/* 我的第一个 C 程序 */
printf("Hello, World!\n");
return ;
}codeJun codeJun 460***593@qq.com6年前 (2018-06-27)
#0 Bob 139***66638@139.com 参考地址 772warning: implicitly declaring library function 'printf' with type'int (const char *, ...)' [-Wimplicit-function-declaration]
以上警告一般发生在没有包含头文件 #include
int main(){
printf("Hello, World!\n");
return 0;
}
这句话提示的意思是:用类型“int (const char *,...)”隐式声明了库函数printf。
该提示的背景知识:因为 printf 这一类库函数太常用了,所以编译器在编译的时候,发现源文件中并没有声明 printf 这个函数就直接使用了它,那么编译器就会为 printf 函数隐式生成一个声明。你那个编译器提示你,它为printf生成的隐式声明是:int printf(const char *, ...)
该提示后果:通常情况下,这个提示只是一个 warning,而不是 error,编译仍然可以通过。
解决方案:要消除这个提示,只要加上 printf 的声明就行了。printf 函数是一个库函数,它的声明在 stdio.h 文件里。所以,你只要在源文件中 #include
#0 蓝 185***00@qq.com 1587#include
/*
这一句话是必须要的格式
stdio 表示系统文件库, 也可以声明其它的
.h 表示头文件,因为这些文件都是放在程序各文件的开头
#include 告诉预处理器将指定头文件的内容插入到预处理器命令的相应位 导入头文件的预编译指令
<> 表示系统自带的库
也可以写成" " 表示用户自定义的库
如果写成" "并且自定义的库里面没有这个文件系统会自动查找自带的库,如果还是没有报错
*/
int main() // 程序的入口
{ //程序从这里开始运行
/*
int 表示数字格式,返回一个数字
main()主函数 表示程序的入口 一个程序有且只能有一个main函数的存在
*/
printf("hello C"); //打印一个hello C
return 0; //返回一个整数0,因为它是int类型,所以只能返回整数
} //程序从这里结束蓝 蓝 185***00@qq.com5年前 (2019-04-21)
点我分享笔记
取消
分享笔记
昵称昵称 (必填)
邮箱邮箱 (必填)
引用地址引用地址
分类导航
HTML / CSSHTML 教程HTML5 教程CSS 教程CSS3 教程Bootstrap3 教程Bootstrap4 教程Bootstrap5 教程Font Awesome 教程Foundation 教程 JavaScriptJavaScript 教程HTML DOM 教程jQuery 教程AngularJS 教程AngularJS2 教程Vue.js 教程Vue3 教程React 教程TypeScript 教程jQuery UI 教程jQuery EasyUI 教程Node.js 教程AJAX 教程JSON 教程Echarts 教程Chart.js 教程Highcharts 教程Google 地图 教程 服务端Python 教程Python2.x 教程Linux 教程Docker 教程Ruby 教程Java 教程C 教程C++ 教程Perl 教程Servlet 教程JSP 教程Lua 教程Rust 教程Scala 教程Go 教程PHP 教程数据结构与算法Django 教程FastAPI 教程Zookeeper 教程设计模式正则表达式Maven 教程Verilog 教程ASP 教程AppML 教程VBScript 教程 数据库SQL 教程MySQL 教程PostgreSQL 教程SQLite 教程MongoDB 教程Redis 教程Memcached 教程 数据分析Python 教程NumPy 教程Pandas 教程Matplotlib 教程Scipy 教程R 教程Julia 教程 移动端Android 教程Swift 教程jQuery Mobile 教程ionic 教程Kotlin 教程 XML 教程XML 教程DTD 教程XML DOM 教程XSLT 教程XPath 教程XQuery 教程XLink 教程XPointer 教程XML Schema 教程XSL-FO 教程SVG 教程 ASP.NETASP.NET 教程C# 教程Web Pages 教程Razor 教程MVC 教程Web Forms 教程 Web ServiceWeb Service 教程WSDL 教程SOAP 教程RSS 教程RDF 教程 开发工具Eclipse 教程Git 教程Svn 教程Markdown 教程 网站建设HTTP 教程网站建设指南浏览器信息网站主机教程TCP/IP 教程W3C 教程网站品质
Advertisement
反馈/建议
在线实例
·HTML 实例
·CSS 实例
·JavaScript 实例
·Ajax 实例
·jQuery 实例
·XML 实例
·Java 实例
字符集&工具
· HTML 字符集设置
· HTML ASCII 字符集
· JS 混淆/加密
· PNG/JPEG 图片压缩
· HTML 拾色器
· JSON 格式化工具
· 随机数生成器
最新更新
·
Rust 宏
·
Seaborn 教程
·
Pandas 相关性分析
·
31.2k star, 免...
·
Dev Home —...
·
免费开源的 AI ...
·
11.2k star, 免...
站点信息
·
意见反馈
·
免责声明
·
关于我们
·
文章归档
关注微信
Copyright © 2013-2024 菜鸟教程
runoob.com All Rights Reserved. 备案号:闽ICP备15012807号-1
微信关注
带你了解什么是C语言! - 知乎
带你了解什么是C语言! - 知乎切换模式写文章登录/注册带你了解什么是C语言!无涯者安全渗透测试/软件开发/社会工程学/计算机底层原理 C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。尽管C语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,以一个标准规格写出的C语言程序可在包括类似嵌入式处理器以及超级计算机等作业平台的许多计算机平台上进行编译C语言C语言诞生于美国的贝尔实验室,由丹尼斯·里奇(Dennis MacAlistair Ritchie)以肯尼斯·蓝·汤普森(Kenneth Lane Thompson)设计的B语言为基础发展而来,在它的主体设计完成后,汤普森和里奇用它完全重写了UNIX,且随着UNIX的发展,c语言也得到了不断的完善。为了利于C语言的全面推广,许多专家学者和硬件厂商联合组成了C语言标准委员会,并在之后的1989年,诞生了第一个完备的C标准,简称“C89”,也就是“ANSI C”,截至2020年,最新的C语言标准为2018年6月发布的“C18”。 [5]C语言之所以命名为C,是因为C语言源自Ken Thompson发明的B语言,而B语言则源自BCPL语言。1967年,剑桥大学的Martin Richards对CPL语言进行了简化,于是产生了BCPL(Basic Combined Programming Language)语言。20世纪60年代,美国AT&T公司贝尔实验室(AT&T Bell Laboratories)的研究员肯·汤普森(Kenneth Lane Thompson)闲来无事,手痒难耐,想玩一个他自己编的,模拟在太阳系航行的电子游戏——Space Travel。他背着老板,找到了台空闲的小型计算机——PDP-7。但这台电脑没有操作系统,而游戏必须使用操作系统的一些功能,于是他着手为PDP-7开发操作系统。后来,这个操作系统被命名为——UNICS(Uniplexed Information and Computing Service)。1969年,美国贝尔实验室的Ken Thompson,以BCPL语言为基础,设计出很简单且很接近硬件的B语言(取BCPL的首字母),并且用B语言写了初版UNIX操作系统(叫UNICS)。1971年,同样酷爱Space Travel的丹尼斯·里奇为了能早点儿玩上游戏,加入了汤普森的开发项目,合作开发UNIX。他的主要工作是改造B语言,使其更成熟。 [6]1972年,美国贝尔实验室的丹尼斯·里奇在B语言的基础上最终设计出了一种新的语言,他取了BCPL的第二个字母作为这种语言的名字,这就是C语言。1973年初,C语言的主体完成。汤普森和里奇迫不及待地开始用它完全重写了UNIX。此时,编程的乐趣使他们已经完全忘记了那个“Space Travel”,一门心思地投入到了UNIX和C语言的开发中。随着UNIX的发展,C语言自身也在不断地完善。直到2020年,各种版本的UNIX内核和周边工具仍然使用C语言作为最主要的开发语言,其中还有不少继承汤普逊和里奇之手的代码。 [6]在开发中,他们还考虑把UNIX移植到其他类型的计算机上使用。C语言强大的移植性(Portability)在此显现。机器语言和汇编语言都不具有移植性,为x86开发的程序,不可能在Alpha、SPARC和ARM等机器上运行。而C语言程序则可以使用在任意架构的处理器上,只要那种架构的处理器具有对应的C语言编译器和库,然后将C源代码编译、连接成目标二进制文件之后即可在哪种架构的处理器运行。 [6]1977年,丹尼斯·里奇发表了不依赖于具体机器系统的C语言编译文本《可移植的C语言编译程序》。C语言继续发展,在1982年,很多有识之士和美国国家标准协会(ANSI)为了使C语言健康地发展下去,决定成立C标准委员会,建立C语言的标准。委员会由硬件厂商、编译器及其他软件工具生产商、软件设计师、顾问、学术界人士、C语言作者和应用程序员组成。1989年,ANSI发布了第一个完整的C语言标准——ANSI X3.159-1989,简称“C89”,不过人们也习惯称其为“ANSI C”。C89在1990年被国际标准化组织(International Standard Organization,ISO)一字不改地采纳,ISO官方给予的名称为:ISO/IEC 9899,所以ISO/IEC9899:1990也通常被简称为“C90”。1999年,在做了一些必要的修正和完善后,ISO发布了新的C语言标准,命名为ISO/IEC 9899:1999,简称“C99”。 [6] 在2011年12月8日,ISO又正式发布了新的标准,称为ISO/IEC9899:2011,简称为“C11”。C语言语言特点编辑 播报主要特点C语言是一种结构化语言,它有着清晰的层次,可按照模块的方式对程序进行编写,十分有利于程序的调试,且c语言的处理和表现能力都非常的强大,依靠非常全面的运算符和多样的数据类型,可以轻易完成各种数据结构的构建,通过指针类型更可对内存直接寻址以及对硬件进行直接操作,因此既能够用于开发系统程序,也可用于开发应用软件。通过对C语言进行研究分析,总结出其主要特点如下:(1)简洁的语言C语言包含的各种控制语句仅有9种,关键字也只有32个,程序的编写要求不严格且以小写字母为主,对许多不必要的部分进行了精简。实际上,语句构成与硬件有关联的较少,且C语言本身不提供与硬件相关的输入输出、文件管理等功能,如需此类功能,需要通过配合编译系统所支持的各类库进行编程,故c语言拥有非常简洁的编译系统。 [5](2)具有结构化的控制语句C语言是一种结构化的语言,提供的控制语句具有结构化特征,如for语句、if...else语句和switch语句等。可以用于实现函数的逻辑控制,方便面向过程的程序设计。 [5](3)丰富的数据类型C语言包含的数据类型广泛,不仅包含有传统的字符型、整型、浮点型、数组类型等数据类型,还具有其他编程语言所不具备的数据类型,其中以指针类型数据使用最为灵活,可以通过编程对各种数据结构进行计算。 [5](4)丰富的运算符C语言包含34个运算符,它将赋值、括号等均视作运算符来操作,使C程序的表达式类型和运算符类型均非常丰富。 [5](5)可对物理地址进行直接操作C语言允许对硬件内存地址进行直接读写,以此可以实现汇编语言的主要功能,并可直接操作硬件。C语言不但具备高级语言所具有的良好特性,又包含了许多低级语言的优势,故在系统软件编程领域有着广泛的应用。 [5](6)代码具有较好的可移植性C语言是面向过程的编程语言,用户只需要关注所被解决问题的本身,而不需要花费过多的精力去了解相关硬件,且针对不同的硬件环境,在用C语言实现相同功能时的代码基本一致,不需或仅需进行少量改动便可完成移植,这就意味着,对于一台计算机编写的C程序可以在另一台计算机上轻松地运行,从而极大的减少了程序移植的工作强度。 [5](7)可生成高质量、目标代码执行效率高的程序与其他高级语言相比,C语言可以生成高质量和高效率的目标代码,故通常应用于对代码质量和执行效率要求较高的嵌入式系统程序的编写。 [5]特有特点C语言是普适性最强的一种计算机程序编辑语言,它不仅可以发挥出高级编程语言的功用,还具有汇编语言的优点,因此相对于其它编程语言,它具有自己独特的特点。具体体现为以下三个方面:其一,广泛性。C语言的运算范围的大小直接决定了其优劣性。C语言中包含了34种运算符,因此运算范围要超出许多其它语言,此外其运算结果的表达形式也十分丰富。此外,C语言包含了字符型、指针型等多种数据结构形式,因此,更为庞大的数据结构运算它也可以应付。 [3]其二,简洁性。9类控制语句和32个关键字是C语言所具有的基础特性,使得其在计算机应用程序编写中具有广泛的适用性,不仅可以适用广大编程人员的操作,提高其工作效率,同时还能够支持高级编程,避免了语言切换的繁琐。 [3]其三,结构完善。C语言是一种结构化语言,它可以通过组建模块单位的形式实现模块化的应用程序,在系统描述方面具有显著优势,同时这一特性也使得它能够适应多种不同的编程要求,且执行效率高。 [3]缺点1.C语言的缺点主要表现为数据的封装性弱,这一点使得C在数据的安全性上有很大缺陷,这也是C和C++的一大区别。2.C语言的语法限制不太严格,对变量的类型约束不严格,影响程序的安全性,对数组下标越界不作检查等。从应用的角度,C语言比其他高级语言较难掌握。也就是说,对用C语言的人,要求对程序设计更熟练一些。 [7]语言组成编辑 播报基本构成数据类型C的数据类型包括:整型(short、int、long、long long)、字符型(char)、实型或浮点型(单精度float和双精度double)、枚举类型(enum)、数组类型、结构体类型(struct)、共用体类型(union)、指针类型和空类型(void)。常量与变量常量其值不可改变,符号常量名通常用大写。变量是以某标识符为名字,其值可以改变的量。标识符是以字母或下划线开头的一串由字母、数字或下划线构成的序列,请注意第一个字符必须为字母或下划线,否则为不合法的变量名。变量在编译时为其分配相应存储单元。数组如果一个变量名后面跟着一个有数字的中括号,这个声明就是数组声明。字符串也是一种数组。它们以ASCII的NULL作为数组的结束。要特别注意的是,中括号内的索引值是从0算起的。指针如果一个变量声明时在前面使用*号,表明这是个指针型变量。换句话说,该变量存储一个地址,而*(此处特指单目运算符*,下同。C语言中另有双目运算符*)则是取内容操作符,意思是取这个内存地址里存储的内容。指针是C语言区别于其他同时代高级语言的主要特征之一。指针不仅可以是变量的地址,还可以是数组、数组元素、函数的地址。通过指针作为形式参数可以在函数的调用过程得到一个以上的返回值,不同于return(z)这样的仅能得到一个返回值。指针是一把双刃剑,许多操作可以通过指针自然的表达,但是不正确的或者过分的使用指针又会给程序带来大量潜在的错误。字符串C语言的字符串其实就是以'\0'字符结尾的char型数组,使用字符型并不需要引用库,但是使用字符串就需要C标准库里面的一些用于对字符串进行操作的函数。它们不同于字符数组。使用这些函数需要引用头文件。文件输入/输出在C语言中,输入和输出是经由标准库中的一组函数来实现的。在ANSI C中,这些函数被定义在头文件;中。标准输入/输出有三个标准输入/输出是标准I/O库预先定义的:stdin标准输入stdout标准输出stderr输入输出错误运算C语言的运算非常灵活,功能十分丰富,运算种类远多于其它程序设计语言。在表达式方面较其它程序语言更为简洁,如自加、自减、逗号运算和三目运算使表达式更为简单,但初学者往往会觉的这种表达式难读,关键原因就是对运算符和运算顺序理解不透不全。当多种不同运算组成一个运算表达式,即一个运算式中出现多种运算符时,运算的优先顺序和结合规则就会显得十分重要。关键字关键字又称为保留字,就是已被C语言本身使用,不能作其它用途使用的字。例如关键字不能用作变量名、函数名等标识符。数据类型关键字short:修饰int,短整型数据,可省略被修饰的int。(K&R时期引入)long:修饰int,长整型数据,可省略被修饰的int。(K&R时期引入)long long:修饰int,超长整型数据,可省略被修饰的int。(C99标准新增)signed:修饰整型数据,有符号数据类型。(C89标准新增)unsigned:修饰整型数据,无符号数据类型。(K&R时期引入)restrict:用于限定和约束指针,并表明指针是访问一个数据对象的初始且唯一的方式。(C99标准新增)复杂类型关键字struct:结构体声明。(K&R时期引入)union:联合体声明。(K&R时期引入)enum:枚举声明。(C89标准新增)typedef:声明类型别名。(K&R时期引入)sizeof:得到特定类型或特定类型变量的大小。(K&R时期引入)inline:内联函数用于取代宏定义,会在任何调用它的地方展开。(C99标准新增)存储级别关键字auto:指定为自动变量,由编译器自动分配及释放。通常在栈上分配。与static相反。当变量未指定时默认为auto。(K&R时期引入)static:指定为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部。(K&R时期引入)register:指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数。(K&R时期引入)extern:指定对应变量为外部变量,即标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。(K&R时期引入)const:指定变量不可被当前线程改变(但有可能被系统或其他线程改变)。(C89标准新增)volatile:指定变量的值有可能会被系统或其他线程改变,强制编译器每次从内存中取得该变量的值,阻止编译器把该变量优化成寄存器变量。(C89标准新增)流程控制关键字跳转结构return:用在函数体中,返回特定值(如果是void类型,则不返回函数值)。(K&R时期引入)continue:结束当前循环,开始下一轮循环。(K&R时期引入)break:跳出当前循环或switch结构。(K&R时期引入)goto:无条件跳转语句。(K&R时期引入)分支结构if:条件语句,后面不需要放分号。(K&R时期引入)else:条件语句否定分支(与if连用)。(K&R时期引入)switch:开关语句(多重分支语句。(K&R时期引入)case:开关语句中的分支标记,与switch连用。(K&R时期引入)default:开关语句中的“其他”分支,可选。(K&R时期引入) [1] 集成开发环境Code::Blocks,开源免费的C/C++ IDECodeLite,开源、跨平台的C/C++集成开发环境Dev-C++,可移植的C/C++IDEC-FreeLight TableVisual Studio系列暂时的后退,是为了积蓄力量,以便让自己走得更远。 生存还是毁灭,这是一个值得思考的问题。这两年工地不好搞,好多外出打工的人都转行了我不停地转行,只为找到我自己的兴趣所在。这本成功转行有很大的帮助你成功转行。发布于 2023-03-30 23:23・IP 属地安徽C 语言入门C (编程语言) 初学C(编程语言)赞同 2添加评论分享喜欢收藏申请
百度百科-验证
百度百科-验证
《C 语言入门教程》发布了 - 阮一峰的网络日志
《C 语言入门教程》发布了 - 阮一峰的网络日志
阮一峰的网络日志 » 首页 » 档案
上一篇:科技爱好者周刊(第 1
下一篇:科技爱好者周刊(第 1
分类:
开发者手册
⇐
⇒
《C 语言入门教程》发布了
作者: 阮一峰
日期: 2021年9月 7日
向大家报告,我写了一本《C 语言入门教程》,已经上线了,欢迎访问。
我知道,这件事有点奇怪,让我来解释一下。
最近两三年,我想做一些服务器开发,一直在学习这方面的技术。去年发布的《Bash 脚本教程》,就是在学习 Shell 的时候写的。后来学习后端编程语言,深感好多基础的东西需要补课,就回过头重新开始看 C 语言。
我上一次学习 C 语言,还是在学校里。印象中,C 语言不容易,复杂类型很难声明和解读。但是,这一次重新学习,意外觉得 C 语言并不复杂,语法点少,没有类,只能使用命令式编程(imperative programming),跟脚本语言(比如 JavaScript)相比,语法描述要容易很多。加上网上很少 C 语言中文教程,质量也不理想,于是就萌生了自己写教程的念头。
最初的想法是,在我的学习笔记基础上,加一些示例就可以了。但是真的动手以后,发现工作量很大,尤其是后来决定 C 语言标准库也包括在教程中。C 的语法点虽然不多,但完整的教程至少要20几章,而且 C 代码写法太自由,不少疑难之处还要去查看参考书籍。所以写得很慢,从春节后到现在,整整写了六个多月,终于写完了。
与以往一样,这个教程是开源的,采用知识共享许可证,源码托管在 GitHub ,大家可以自由使用。点击下面网址,在线阅读全书。
wangdoc.com/clang
我对它还算满意,该讲的地方都讲到了,给出了许多示例,初学者完全够用了。但是,毕竟我平时很少有机会使用 C 语言编程,各种错误和遗漏之处,肯定有不少,欢迎大家到仓库提交补丁,或者发 issue 反映问题。
(完)
文档信息
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
发表日期: 2021年9月 7日
相关文章
2023.08.08: 《TypeScript 教程》发布了
长话短说,我写了一本《TypeScript 教程》,已经发布在网道,欢迎大家访问。
2023.03.21: 运维的未来是平台工程
互联网公司有一个重要工种,叫做"运维"。
2022.10.23: 最简单的 Git 服务器
程序员的代码仓库,总是需要托管一份在服务器,这样才保险,也方便使用。
2022.06.29: 云主机上手教程:轻量应用服务器体验
很多同学都希望架设自己的云服务,这就离不开云主机(cloud server)。
留言(66条)
Vince
说:
刚好最近也想重新复习一下,谢谢分享,已经在微信打赏了
2021年9月 7日 16:38
| #
| 引用
aduo
说:
佩服!!!
2021年9月 7日 16:58
| #
| 引用
coderfuns
说:
教程类文档只服阮大神,简单明了!
2021年9月 7日 17:12
| #
| 引用
steven
说:
先赞了再说????
2021年9月 7日 17:40
| #
| 引用
翻一会
说:
虽然不怎么用了,但有这个教程可以查询也很好,谢谢阮老师。
2021年9月 7日 18:19
| #
| 引用
chaoqi
说:
强力推荐研究一下 erlang, common lisp 这样的程序设计语言
2021年9月 7日 18:46
| #
| 引用
刘女士
说:
佩服阮老师的学习精神!真学无止境!
另外疑问留言为嘛要留电子邮件
2021年9月 7日 20:19
| #
| 引用
三天摸鱼两天闲逛
说:
太赞了,正想系统研究一下C,突然就更了,阮老师高产!!!
2021年9月 7日 20:26
| #
| 引用
Kholin
说:
看来是时候再出一本汇编教程了,然后是单片机教程
2021年9月 7日 20:54
| #
| 引用
pope
说:
啥时候出个 JavaScript教程呀
2021年9月 7日 21:23
| #
| 引用
undefined
说:
感谢阮老师。
2021年9月 8日 10:20
| #
| 引用
BoneSakura
说:
好耶!什么时候出个C++教程呀~
2021年9月 8日 14:36
| #
| 引用
JohnLu
说:
感谢阮老师。
教程很好,内容简明易懂,关键是比学校教的多出了许多实用内容(尤其是多文件项目部分)。
不管是0基础,还是已经在学校学过c的同学,都很适合看看。
2021年9月 8日 14:55
| #
| 引用
冰红茶
说:
引用pope的发言:
啥时候出个 JavaScript教程呀
已经有了啊 在 这个教程同一个网站
2021年9月 8日 16:20
| #
| 引用
youkyc
说:
引用pope的发言:
啥时候出个 JavaScript教程呀
有了啊
2021年9月 8日 21:54
| #
| 引用
youkyc
说:
Python的可以来一个,现在比较火的
2021年9月 8日 21:55
| #
| 引用
youkyc
说:
引用刘女士的发言:
佩服阮老师的学习精神!真学无止境!
另外疑问留言为嘛要留电子邮件
因为邮件现在都实名了,大家不要乱说话,没啥大不了的吧
2021年9月 8日 21:56
| #
| 引用
九监九介
说:
阮老师的文章每一篇都会准时看,太感谢阮老师无私的分享各种高质量的文章和教程
2021年9月 8日 22:56
| #
| 引用
wbc
说:
从程序员入门开始,一直看阮老师的文档,如果没有您的技术文档作伴,这条路上多出来的阻力不知要多多少。今天看到这篇文章,我已经在想象自己可以轻松入门c的场景了。千言万语,汇成一句话:谢谢
2021年9月 9日 08:27
| #
| 引用
Andrei
说:
https://akaedu.github.io/book/
这个教程也挺不错的,可以参考一下
2021年9月 9日 10:48
| #
| 引用
吴昊昊
说:
当年学c语言和数据结构的时候,是看郝斌的教程,差不多是20年以前的事情了
对于初学者还是建议看郝斌的c语言教程当然阮老师的也非常不错
目前个人认为,对于新人入门的话,选择python或者javascript是不错的,学c的话,大学老师已经在大一教过了
目前大多数人的学习环境是windows,甚至国家考试也是windows环境,这个如何治
2021年9月 9日 16:37
| #
| 引用
展翼骐骥
说:
能否把您写的几个教程都列出来,不是今天读到这边文章,还不知道有这么好的东西。
2021年9月 9日 22:08
| #
| 引用
haha
说:
有时觉得阮老师现在每周文章都内嵌各种广告保险 让人反感。但又看到在不断写各种教材 又让人可敬。矛盾~~
2021年9月10日 08:28
| #
| 引用
dong
说:
阮老师的作品总是言简意赅,通俗易懂,读起来简直是享受,js标准教程和es6教程让我受益匪浅
2021年9月10日 08:42
| #
| 引用
LabmenNoSOS
说:
引用展翼骐骥的发言:
能否把您写的几个教程都列出来,不是今天读到这边文章,还不知道有这么好的东西。
阮老师的文章是有分类的,你可以看看《开发者手册》这个分类
https://www.ruanyifeng.com/blog/developer/
2021年9月10日 10:23
| #
| 引用
ColdStone
说:
已 Star,赞
2021年9月10日 11:26
| #
| 引用
袁
说:
给咱留个打赏通道
2021年9月10日 17:00
| #
| 引用
黎明
说:
真心佩服,阮老师,真是前端布道大师
2021年9月11日 00:37
| #
| 引用
黎明
说:
教师节快乐!真正的传道授业解惑,加油!
2021年9月11日 00:39
| #
| 引用
zhchnchn
说:
很高兴阮老师开始涉足C语言了,学完语言,估计接下来就要开始学习Linux下的构建了,期待阮老师发布Makefile/CMake的技术教程。
2021年9月11日 01:01
| #
| 引用
Ca2OH4
说:
引用吴昊昊的发言:
目前大多数人的学习环境是windows,甚至国家考试也是windows环境,这个如何治
windows 和 c 有啥不兼容的呢?
2021年9月13日 09:39
| #
| 引用
xugaoxiang
说:
想请问下阮老师,github上的电子书是用什么工具写的?感谢
2021年9月13日 15:05
| #
| 引用
magura
说:
从开发的角度来说,文档写的真心很棒
2021年9月14日 11:10
| #
| 引用
Nan
说:
引用haha的发言:
有时觉得阮老师现在每周文章都内嵌各种广告保险 让人反感。但又看到在不断写各种教材 又让人可敬。矛盾~~
我还在上学的时候,也对广告这件事异常反感。直到我进入社会,我才知道广告是必要的,它可以促进 win-win-win 三赢局面:受众拥有可以白嫖的资源、广告投放商的信息被扩散、创作者获得激励和回报。
现在很多成功的创业案例都是这个模式,促成这个模式对所有人都是有益的,可以持续发展。
2021年9月14日 15:39
| #
| 引用
tl
说:
可以来个cocos creator的吗拜托啦
2021年9月15日 15:52
| #
| 引用
heq
说:
感谢阮老师,今年正想考研试试,这几天在啃谭浩强的c语言
2021年9月16日 08:59
| #
| 引用
靑雲子
说:
谢谢大佬 刚准备学c语言
2021年9月18日 11:04
| #
| 引用
阿长
说:
真好,最开始看的是js教程
2021年9月21日 17:12
| #
| 引用
thomas76
说:
C语言即没有看起来那样难,也没有看起来那样容易。例如宏这个概念,说白了就是文本的替换,用过WORD,写字本等工具的人都很快理解宏的概念。但是宏的更多知识,Self-Referential,PreScan,Stringification等不是一时半刻能理解透的,我也是经常翻翻这些知识点,因为有时遇到技术问题不知怎么解决。
2021年9月23日 09:38
| #
| 引用
Larry
说:
读了一遍,发现很多以前不理解只是记下来用的知识背后都是有原因的。谢谢阮老师!
2021年9月26日 10:45
| #
| 引用
小段
说:
阮老师出品,必属精品
2021年9月28日 09:08
| #
| 引用
谷雨
说:
有java教程就好了。
2021年9月28日 15:58
| #
| 引用
stywell
说:
当年大学,把谭浩强的c语言程序设换成您这本~ 也不至于让我成为一个node程序员
2021年9月30日 14:18
| #
| 引用
fave
说:
引用xugaoxiang的发言:
想请问下阮老师,github上的电子书是用什么工具写的?感谢
gitbook
2021年10月 8日 19:17
| #
| 引用
feifeifei
说:
感谢大佬
2021年10月11日 14:28
| #
| 引用
碌云
说:
现在不应该用Rust替代掉C吗,希望出Rust的教程
2021年10月12日 14:45
| #
| 引用
oy
说:
大佬牛逼 好多东西都是看大佬的东西学的
2021年10月18日 12:41
| #
| 引用
luopojianshi
说:
有些例子存在错误吧
https://wangdoc.com/clang/struct.html
struct 结构一章中 5.位字段的例子
typedef struct {
unsigned int ab:1;
unsigned int cd:1;
unsigned int ef:1;
unsigned int gh:1;
} synth;
synth.ab = 0;
synth.cd = 1;
这里的 typedef struct { ... } synth; 创建了一个匿名数据结构的别名 synth,并不是一个 匿名数据结构变量 synth,后面对 synth.ab、synth.cd 赋值会报错。
2021年10月18日 21:20
| #
| 引用
Elaine
说:
蹲一个 C++ 教程 ~!
2021年10月25日 09:39
| #
| 引用
nico zhang
说:
越到最后,越觉得C绕不开,好多概念的理解都要通过C.
同感,点赞!
2021年10月26日 11:10
| #
| 引用
learner
说:
第23.1章节中 前面对assert.h的描述:
上面代码在程序运行到这一行语句时,验证变量是否PI大于3。如果确实大于3,程序继续运行,否则就会终止运行,并且给出报错信息提示。
assert()宏接受一个表达式作为参数,如果表达式的返回值非零,assert()就会报错
========================
这里的描述貌似有错误,应该是: 如果表达式的返回值零,assert()就会报错。
2021年11月 1日 16:18
| #
| 引用
Wan9J1n
说:
想要C++的
2021年11月 5日 11:12
| #
| 引用
黄哈哈
说:
这本书怎么下载呀
2021年11月 7日 16:00
| #
| 引用
yuhui06
说:
为什么不是C++..
2021年11月12日 11:03
| #
| 引用
fq06
说:
老师 有没有兴趣搞直播 分享啊 技术 人生感悟 都可以
2021年11月14日 17:14
| #
| 引用
底层技术初学者
说:
阮大神如果再写一套c++教程、Go教程、Rust教程,那就世界无敌了!
2021年11月15日 16:14
| #
| 引用
Pan
说:
引用吴昊昊的发言:
当年学c语言和数据结构的时候,是看郝斌的教程,差不多是20年以前的事情了
对于初学者还是建议看郝斌的c语言教程当然阮老师的也非常不错
目前个人认为,对于新人入门的话,选择python或者javascript是不错的,学c的话,大学老师已经在大一教过了
目前大多数人的学习环境是windows,甚至国家考试也是windows环境,这个如何治
20年前?郝斌的数据结构与算法课,认真的吗?那现在得多大年龄了,我记得我是两年前在B站看过郝斌的数据结构,但是最后章节不全,我当时特别意难平,觉得那个老师讲的真的很不错,可惜到处找不到联系方式,没想到在阮老师这里看见了有人知道这个老师,还有点激动。
2021年11月25日 18:02
| #
| 引用
zhouyu0914k
说:
支持,感谢大神分享!!!
2021年12月10日 18:05
| #
| 引用
balefulScript
说:
引用stywell的发言:
当年大学,把谭浩强的c语言程序设换成您这本~ 也不至于让我成为一个node程序员
雀食,哈哈哈,谭的书真是一言难尽
2021年12月28日 17:54
| #
| 引用
sharkloc
说:
引用yuhui06的发言:
为什么不是C++..
C用时6个多月,C++估计更久
2021年12月31日 17:29
| #
| 引用
龚汉金
说:
什么时候出一下rust的学习教程
2022年1月12日 23:26
| #
| 引用
lucky111
说:
赞一个,佩服大神啊
2022年2月10日 18:31
| #
| 引用
Donald
说:
期待大神的C++和Rust教程
2022年3月16日 16:46
| #
| 引用
bing98
说:
牛皮,溜达论坛博客的时候,发现了老哥的博客网站,看了有两三个月时间,才发现我之前看的js教程也是老哥写的。。。。。
2023年6月 1日 17:47
| #
| 引用
路人乙
说:
想要C++的
2023年9月24日 08:48
| #
| 引用
sssss
说:
c语言普及教程不错, 求c语言的高级教程, 高级设计模式,高级宏编程等。看看有没有汇总的。。(数据结构方面的就不用了)
2024年1月27日 09:54
| #
| 引用
我要发表看法
您的留言
(HTML标签部分可用)
您的大名:
«-必填
电子邮件:
«-必填,不公开
个人网址:
«-我信任你,不会填写广告链接
记住个人信息?
正在发表您的评论,请稍候
«- 点击按钮
Weibo |
Twitter |
GitHub
Email: [email protected]
网络编程:程序员的基本功!教你如何自学C语言网络编程! - 知乎
网络编程:程序员的基本功!教你如何自学C语言网络编程! - 知乎首发于程序员相关文章切换模式写文章登录/注册网络编程:程序员的基本功!教你如何自学C语言网络编程!C语言入门教学悟空问答丨大学生编程指南网络编程在编程体系里面占据很大一部分,在离不开网络的时代,网络编程重要性越来越强,网络编程算是程序员要掌握的基本功了,很多人好奇的黑客,网络也是基本功。无论什么编程语言都需要支持网络编程,只不过在接口实现方式上,会根据自身编程语言的特性,对于socket进行封装。网络编程经典书籍:《协议:TCP/IP卷一》《UNIX网络编程》网络编程底层代码基本上C语言来实现的,建议在linux下用c语言,把底层原汁原味的linux socket编程走一遍,下图是一个socket原理图:socket常见接口现在无论java,python网络接口都接近上面的接口。如何学?1.先把网络编程的基本概念了解明白,知道大概协议,读懂网络传输的原理(把推荐的两本书)2.选择一门自己擅长的编程语言(C/C++),然后在上面练习网路编程(选择编程环境)3.亲自手动写一个网络编程实例,例如实现简单的局域网数据传输功能,模拟简单的qq聊天功能(功能实践)——————————————————————————————————————笔者是一个C/C++出身的程序员,自学C/C++编程有什么学习问题或者关于C/C++学习的路线的话可以看我个人介绍交流。 发布于 2019-08-16 15:15网络编程C / C++UNIX网络编程(书籍)赞同 5添加评论分享喜欢收藏申请转载文章被以下专栏收录程序员相关文章C/C++程序员资料分享Q群:951258