C - 快速指南
C 是一种通用的高级语言,最初由 Dennis M. Ritchie 在贝尔实验室开发 UNIX 操作系统。C 最初于 1972 年在 DEC PDP-11 计算机上首次实现。
1978 年,Brian Kernighan 和 Dennis Ritchie 制作了第一个公开可用的 C 描述,现在称为 K&R 标准。
UNIX 操作系统、C 编译器和基本上所有 UNIX 应用程序都是用 C 编写的。由于各种原因,C 现在已成为一种广泛使用的专业语言 -
- 简单易学
- 结构化语言
- 它产生高效的程序
- 它可以处理低级活动
- 可以在多种计算机平台上编译
关于 C 的事实
C 的发明是为了编写一个名为 UNIX 的操作系统。
C 语言是 20 世纪 70 年代初推出的 B 语言的继承者。
该语言于 1988 年由美国国家标准协会 (ANSI) 正式确定。
UNIX 操作系统完全是用 C 编写的。
如今,C 是使用最广泛和流行的系统编程语言。
大多数最先进的软件都是使用 C 语言实现的。
当今最流行的 Linux 操作系统和 RDBMS MySQL 都是用 C 编写的。
为什么使用C?
C 最初用于系统开发工作,特别是构成操作系统的程序。C 被采用作为系统开发语言,因为它生成的代码运行速度几乎与用汇编语言编写的代码一样快。使用 C 的一些例子可能是 -
- 操作系统
- 语言编译器
- 装配工
- 文本编辑器
- 后台打印程序
- 网络驱动程序
- 现代节目
- 数据库
- 语言口译员
- 公用事业
C 程序
AC程序可以从3行到数百万行不等,应写入一个或多个扩展名为“.c”的文本文件中;例如,hello.c。您可以使用“vi”、“vim”或任何其他文本编辑器将 C 程序写入文件。
本教程假设您知道如何编辑文本文件以及如何在程序文件中编写源代码。
C - 环境设置
本地环境设置
如果您想设置 C 编程语言环境,您的计算机上需要以下两个可用的软件工具:(a) 文本编辑器和 (b) C 编译器。
文本编辑器
这将用于输入您的程序。一些编辑器的示例包括 Windows 记事本、操作系统编辑命令、Brief、Epsilon、EMACS 和 vim 或 vi。
文本编辑器的名称和版本在不同操作系统上可能有所不同。例如,记事本将在 Windows 上使用,vim 或 vi 可以在 Windows 上使用,也可以在 Linux 或 UNIX 上使用。
您使用编辑器创建的文件称为源文件,它们包含程序源代码。C 程序的源文件通常以扩展名“ .c ”命名。
在开始编程之前,请确保您有一个文本编辑器,并且您有足够的经验来编写计算机程序、将其保存在文件中、编译并最终执行它。
C 编译器
源文件中编写的源代码是程序的人类可读源。它需要被“编译”成机器语言,以便您的 CPU 可以实际按照给定的指令执行程序。
编译器将源代码编译成最终的可执行程序。最常用且免费的编译器是 GNU C/C++ 编译器,否则,如果您有相应的操作系统,则可以使用 HP 或 Solaris 的编译器。
以下部分介绍如何在各种操作系统上安装 GNU C/C++ 编译器。我们不断地一起提及 C/C++,因为 GNU gcc 编译器适用于 C 和 C++ 编程语言。
在 UNIX/Linux 上安装
如果您使用的是Linux 或 UNIX,请通过从命令行输入以下命令来检查您的系统上是否安装了 GCC -
$ gcc -v
如果你的机器上安装了 GNU 编译器,那么它应该打印一条消息,如下所示 -
Using built-in specs. Target: i386-redhat-linux Configured with: ../configure --prefix=/usr ....... Thread model: posix gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)
如果未安装 GCC,则您必须使用https://gcc.gnu.org/install/上提供的详细说明自行安装它
本教程是基于 Linux 编写的,所有给出的示例都是在 Linux 系统的 Cent OS 版本上编译的。
Mac 操作系统上的安装
如果您使用 Mac OS X,获取 GCC 的最简单方法是从 Apple 网站下载 Xcode 开发环境并按照简单的安装说明进行操作。设置 Xcode 后,您将能够使用 C/C++ 的 GNU 编译器。
Xcode 目前可在developer.apple.com/technologies/tools/上获取。
在 Windows 上安装
要在Windows上安装GCC,您需要安装MinGW。要安装 MinGW,请访问 MinGW 主页www.mingw.org,然后点击链接进入 MinGW 下载页面。下载最新版本的 MinGW 安装程序,该程序应命名为 MinGW-<version>.exe。
安装 Min GW 时,您至少必须安装 gcc-core、gcc-g++、binutils 和 MinGW 运行时,但您可能希望安装更多。
将 MinGW 安装的 bin 子目录添加到PATH环境变量中,以便您可以在命令行上通过简单名称指定这些工具。
安装完成后,您将能够从 Windows 命令行运行 gcc、g++、ar、ranlib、dlltool 和其他几个 GNU 工具。
C - 程序结构
在我们学习 C 编程语言的基本构建块之前,让我们看一下最基本的 C 程序结构,以便我们可以在接下来的章节中将其作为参考。
你好世界示例
AC 程序基本上由以下部分组成 -
- 预处理器命令
- 功能
- 变量
- 陈述和表达式
- 评论
让我们看一个简单的代码,它将打印“Hello World”一词 -
#include <stdio.h> int main() { /* my first program in C */ printf("Hello, World! \n"); return 0; }
让我们看一下上述程序的各个部分 -
程序的第一行#include <stdio.h>是一个预处理器命令,它告诉 C 编译器在进行实际编译之前包含 stdio.h 文件。
下一行int main()是程序开始执行的主函数。
下一行 /*...*/ 将被编译器忽略,它已被添加到程序中添加附加注释。所以这样的行在程序中称为注释。
下一行printf(...)是 C 中另一个可用的函数,它会产生消息“Hello, World!” 要显示在屏幕上。
下一行返回0;终止 main() 函数并返回值 0。
编译并执行C程序
让我们看看如何将源代码保存在文件中,以及如何编译和运行它。以下是简单的步骤 -
打开文本编辑器并添加上述代码。
将文件另存为hello.c
打开命令提示符并转到保存文件的目录。
输入gcc hello.c并按 Enter 编译代码。
如果代码中没有错误,命令提示符将带您进入下一行并生成.out可执行文件。
现在,输入a.out来执行您的程序。
您将在屏幕上看到输出“Hello World” 。
$ gcc hello.c $ ./a.out Hello, World!
确保 gcc 编译器位于您的路径中,并且您正在包含源文件 hello.c 的目录中运行它。
C - 基本语法
您已经了解了 C 程序的基本结构,因此很容易理解 C 编程语言的其他基本构建块。
C 中的令牌
AC 程序由各种标记组成,标记可以是关键字、标识符、常量、字符串文字或符号。例如,以下 C 语句由五个标记组成 -
printf("Hello, World! \n");
各个令牌是 -
printf ( "Hello, World! \n" ) ;
分号
在 C 程序中,分号是语句终止符。也就是说,每个单独的语句必须以分号结束。它表示一个逻辑实体的结束。
下面给出两种不同的说法 -
printf("Hello, World! \n"); return 0;
评论
注释就像 C 程序中的帮助文本一样,它们会被编译器忽略。它们以 /* 开头并以字符 */ 结尾,如下所示 -
/* my first program in C */
注释中不能有注释,并且注释不会出现在字符串或字符文本中。
身份标识
AC 标识符是用于标识变量、函数或任何其他用户定义项的名称。标识符以字母 A 到 Z、a 到 z 或下划线“_”开头,后跟零个或多个字母、下划线和数字(0 到 9)。
C 不允许在标识符中使用标点符号,例如 @、$ 和 %。C 是一种区分大小写的编程语言。因此,Manpower和manpower是 C 中两个不同的标识符。以下是可接受的标识符的一些示例 -
mohd zara abc move_name a_123 myname50 _temp j a23b9 retVal
关键词
下面的列表显示了 C 中的保留字。这些保留字不能用作常量、变量或任何其他标识符名称。
汽车 | 别的 | 长的 | 转变 |
休息 | 枚举 | 登记 | 类型定义 |
案件 | 外部的 | 返回 | 联盟 |
字符 | 漂浮 | 短的 | 未签名 |
常量 | 为了 | 签 | 空白 |
继续 | 去 | 大小 | 易挥发的 |
默认 | 如果 | 静止的 | 尽管 |
做 | 整数 | 结构体 | _包装好的 |
双倍的 |
C 中的空白
仅包含空格(可能带有注释)的行称为空行,C 编译器完全忽略它。
空白是 C 语言中用来描述空白、制表符、换行符和注释的术语。空格将语句的一部分与另一部分分隔开,并使编译器能够识别语句中一个元素(例如 int)的结束位置和下一个元素的开始位置。因此,在以下声明中 -
int age;
int 和age 之间必须至少有一个空白字符(通常是空格),以便编译器能够区分它们。另一方面,在以下声明中 -
fruit = apples + oranges; // get the total fruit
水果和 = 之间或 = 和苹果之间不需要空格字符,但如果您希望提高可读性,可以自由地包含一些空格字符。
C - 数据类型
c 中的数据类型是指用于声明不同类型的变量或函数的广泛系统。变量的类型决定了它在存储中占用多少空间以及如何解释存储的位模式。
C 中的类型可以分类如下 -
先生。 | 类型和描述 |
---|---|
1 | 基本类型 它们是算术类型,并进一步分为:(a)整数类型和(b)浮点类型。 |
2 | 枚举类型 它们又是算术类型,用于定义在整个程序中只能分配某些离散整数值的变量。 |
3 | 类型无效 类型说明符void表示没有可用值。 |
4 | 派生类型 它们包括 (a) 指针类型、(b) 数组类型、(c) 结构类型、(d) 联合类型和 (e) 函数类型。 |
数组类型和结构类型统称为聚合类型。函数的类型指定函数的返回值的类型。我们将在下一节中看到基本类型,其他类型将在接下来的章节中介绍。
整数类型
下表提供了标准整数类型及其存储大小和值范围的详细信息 -
类型 | 存储大小 | 取值范围 |
---|---|---|
字符 | 1字节 | -128 至 127 或 0 至 255 |
无符号字符 | 1字节 | 0 至 255 |
签名字符 | 1字节 | -128 至 127 |
整数 | 2 或 4 字节 | -32,768 至 32,767 或 -2,147,483,648 至 2,147,483,647 |
无符号整数 | 2 或 4 字节 | 0 至 65,535 或 0 至 4,294,967,295 |
短的 | 2字节 | -32,768 至 32,767 |
无符号短 | 2字节 | 0 至 65,535 |
长的 | 8字节 | -9223372036854775808 至 9223372036854775807 |
无符号长 | 8字节 | 0 至 18446744073709551615 |
要获取特定平台上类型或变量的确切大小,可以使用sizeof运算符。表达式sizeof(type)生成对象或类型的存储大小(以字节为单位)。下面给出了一个示例,使用limits.h头文件中定义的不同常量来获取机器上各种类型的大小 -
#include <stdio.h> #include <stdlib.h> #include <limits.h> #include <float.h> int main(int argc, char** argv) { printf("CHAR_BIT : %d\n", CHAR_BIT); printf("CHAR_MAX : %d\n", CHAR_MAX); printf("CHAR_MIN : %d\n", CHAR_MIN); printf("INT_MAX : %d\n", INT_MAX); printf("INT_MIN : %d\n", INT_MIN); printf("LONG_MAX : %ld\n", (long) LONG_MAX); printf("LONG_MIN : %ld\n", (long) LONG_MIN); printf("SCHAR_MAX : %d\n", SCHAR_MAX); printf("SCHAR_MIN : %d\n", SCHAR_MIN); printf("SHRT_MAX : %d\n", SHRT_MAX); printf("SHRT_MIN : %d\n", SHRT_MIN); printf("UCHAR_MAX : %d\n", UCHAR_MAX); printf("UINT_MAX : %u\n", (unsigned int) UINT_MAX); printf("ULONG_MAX : %lu\n", (unsigned long) ULONG_MAX); printf("USHRT_MAX : %d\n", (unsigned short) USHRT_MAX); return 0; }
当您编译并执行上述程序时,它会在 Linux 上产生以下结果 -
CHAR_BIT : 8 CHAR_MAX : 127 CHAR_MIN : -128 INT_MAX : 2147483647 INT_MIN : -2147483648 LONG_MAX : 9223372036854775807 LONG_MIN : -9223372036854775808 SCHAR_MAX : 127 SCHAR_MIN : -128 SHRT_MAX : 32767 SHRT_MIN : -32768 UCHAR_MAX : 255 UINT_MAX : 4294967295 ULONG_MAX : 18446744073709551615 USHRT_MAX : 65535
浮点类型
下表提供了标准浮点类型的详细信息,包括存储大小、值范围及其精度 -
类型 | 存储大小 | 取值范围 | 精确 |
---|---|---|---|
漂浮 | 4字节 | 1.2E-38 至 3.4E+38 | 小数点后 6 位 |
双倍的 | 8字节 | 2.3E-308至1.7E+308 | 小数点后 15 位 |
长双 | 10字节 | 3.4E-4932 至 1.1E+4932 | 小数点后 19 位 |
头文件 float.h 定义了宏,允许您在程序中使用这些值以及有关实数二进制表示形式的其他详细信息。以下示例打印浮点类型及其范围值占用的存储空间 -
#include <stdio.h> #include <stdlib.h> #include <limits.h> #include <float.h> int main(int argc, char** argv) { printf("Storage size for float : %d \n", sizeof(float)); printf("FLT_MAX : %g\n", (float) FLT_MAX); printf("FLT_MIN : %g\n", (float) FLT_MIN); printf("-FLT_MAX : %g\n", (float) -FLT_MAX); printf("-FLT_MIN : %g\n", (float) -FLT_MIN); printf("DBL_MAX : %g\n", (double) DBL_MAX); printf("DBL_MIN : %g\n", (double) DBL_MIN); printf("-DBL_MAX : %g\n", (double) -DBL_MAX); printf("Precision value: %d\n", FLT_DIG ); return 0; }
当您编译并执行上述程序时,它会在 Linux 上产生以下结果 -
Storage size for float : 4 FLT_MAX : 3.40282e+38 FLT_MIN : 1.17549e-38 -FLT_MAX : -3.40282e+38 -FLT_MIN : -1.17549e-38 DBL_MAX : 1.79769e+308 DBL_MIN : 2.22507e-308 -DBL_MAX : -1.79769e+308 Precision value: 6
虚空类型
void 类型指定没有可用值。它用于三种情况 -
先生。 | 类型和描述 |
---|---|
1 | 函数返回 void C 中有多种函数不返回任何值,或者您可以说它们返回 void。无返回值的函数的返回类型为 void。例如,void exit(int status); |
2 | 函数参数为 void C 中有多种不接受任何参数的函数。没有参数的函数可以接受 void。例如,int rand(void); |
3 | 指向 void 的指针 void * 类型的指针表示对象的地址,但不表示其类型。例如,内存分配函数void *malloc( size_t size ); 返回一个指向 void 的指针,该指针可以转换为任何数据类型。 |
C - 变量
变量只不过是我们的程序可以操作的存储区域的名称。C中的每个变量都有一个特定的类型,它决定了变量内存的大小和布局;该内存中可以存储的值的范围;以及可以应用于变量的操作集。
变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。大写和小写字母是不同的,因为 C 区分大小写。基于上一章中解释的基本类型,将有以下基本变量类型 -
先生。 | 类型和描述 |
---|---|
1 | 字符 通常是一个八位位组(一个字节)。它是一个整数类型。 |
2 | 整数 机器最自然的整数大小。 |
3 | 漂浮 单精度浮点值。 |
4 | 双倍的 双精度浮点值。 |
5 | 空白 代表没有类型。 |
C 编程语言还允许定义各种其他类型的变量,我们将在后续章节中介绍这些变量,例如枚举、指针、数组、结构体、联合等。在本章中,我们只研究基本变量类型。
C 中的变量定义
变量定义告诉编译器在何处以及为变量创建多少存储空间。变量定义指定一种数据类型并包含该类型的一个或多个变量的列表,如下所示 -
type variable_list;
这里,type必须是有效的 C 数据类型,包括 char、w_char、int、float、double、bool 或任何用户定义的对象;variable_list可以由一个或多个以逗号分隔的标识符名称组成。这里显示了一些有效的声明 -
int i, j, k; char c, ch; float f, salary; double d;
该行int i, j, k; 声明并定义变量 i、j 和 k;它指示编译器创建名为 i、j 和 k 的 int 类型变量。
变量可以在其声明中初始化(分配初始值)。初始化器由一个等号后跟一个常量表达式组成,如下所示 -
type variable_name = value;
一些例子是 -
extern int d = 3, f = 5; // declaration of d and f. int d = 3, f = 5; // definition and initializing d and f. byte z = 22; // definition and initializes z. char x = 'x'; // the variable x has the value 'x'.
对于没有初始化器的定义:具有静态存储持续时间的变量隐式初始化为 NULL(所有字节的值为 0);所有其他变量的初始值均未定义。
C 中的变量声明
变量声明向编译器保证存在具有给定类型和名称的变量,以便编译器可以继续进行进一步编译,而不需要有关该变量的完整详细信息。变量定义仅在编译时才有意义,编译器在链接程序时需要实际的变量定义。
当您使用多个文件并且在链接程序时可用的文件之一中定义变量时,变量声明非常有用。您将在任何地方使用关键字extern声明变量。尽管您可以在 C 程序中多次声明一个变量,但它只能在文件、函数或代码块中定义一次。
例子
尝试以下示例,其中变量已在顶部声明,但它们已在主函数内定义和初始化 -
#include <stdio.h> // Variable declaration: extern int a, b; extern int c; extern float f; int main () { /* variable definition: */ int a, b; int c; float f; /* actual initialization */ a = 10; b = 20; c = a + b; printf("value of c : %d \n", c); f = 70.0/3.0; printf("value of f : %f \n", f); return 0; }
当上面的代码被编译并执行时,它会产生以下结果 -
value of c : 30 value of f : 23.333334
相同的概念适用于函数声明,您在声明时提供函数名称,而其实际定义可以在其他任何地方给出。例如 -
// function declaration int func(); int main() { // function call int i = func(); } // function definition int func() { return 0; }
C 中的左值和右值
C 中有两种表达式 -
左值- 引用内存位置的表达式称为“左值”表达式。左值可以显示为赋值的左侧或右侧。
右值- 术语右值是指存储在内存中某个地址的数据值。右值是一个不能赋值的表达式,这意味着右值可以出现在赋值的右侧,但不能出现在左侧。
变量是左值,因此它们可能出现在赋值的左侧。数字文字是右值,因此它们可能不会被赋值,也不能出现在左侧。看看以下有效和无效的陈述 -
int g = 20; // valid statement 10 = 20; // invalid statement; would generate compile-time error
C - 常量和文字
常量是指程序在执行过程中不能改变的固定值。这些固定值也称为文字。
常量可以是任何基本数据类型,例如整型常量、浮点常量、字符常量或字符串常量。还有枚举常量。
常量的处理方式与常规变量一样,只是它们的值在定义后不能修改。
整数文字
整数文字可以是十进制、八进制或十六进制常量。前缀指定基数或基数:0x 或 0X 表示十六进制,0 表示八进制,没有任何内容表示十进制。
整数文字还可以具有 U 和 L 的组合后缀,分别表示无符号和长整型。后缀可以是大写或小写,并且可以是任何顺序。
以下是整数文字的一些示例 -
212 /* Legal */ 215u /* Legal */ 0xFeeL /* Legal */ 078 /* Illegal: 8 is not an octal digit */ 032UU /* Illegal: cannot repeat a suffix */
以下是各种类型整数文字的其他示例 -
85 /* decimal */ 0213 /* octal */ 0x4b /* hexadecimal */ 30 /* int */ 30u /* unsigned int */ 30l /* long */ 30ul /* unsigned long */
浮点文字
浮点文字具有整数部分、小数点、小数部分和指数部分。您可以用十进制形式或指数形式表示浮点文字。
表示小数形式时,必须包含小数点、指数或两者;在表示指数形式时,必须包含整数部分、小数部分或两者。带符号指数由 e 或 E 引入。
以下是浮点文字的一些示例 -
3.14159 /* Legal */ 314159E-5L /* Legal */ 510E /* Illegal: incomplete exponent */ 210f /* Illegal: no decimal or exponent */ .e55 /* Illegal: missing integer or fraction */
字符常量
字符文字用单引号括起来,例如,'x' 可以存储在char类型的简单变量中。
字符文字可以是普通字符(例如“x”)、转义序列(例如“\t”)或通用字符(例如“\u02C0”)。
C 中的某些字符在前面加反斜杠时表示特殊含义,例如换行符 (\n) 或制表符 (\t)。
以下是显示一些转义序列字符的示例 -
#include <stdio.h> int main() { printf("Hello\tWorld\n\n"); return 0; }
当上面的代码被编译并执行时,它会产生以下结果 -
Hello World
字符串文字
字符串文字或常量用双引号“”括起来。字符串包含与字符文字类似的字符:普通字符、转义序列和通用字符。
您可以使用字符串文字将长行分成多行,并使用空格分隔它们。
以下是字符串文字的一些示例。所有三种形式都是相同的字符串。
"hello, dear" "hello, \ dear" "hello, " "d" "ear"
定义常量
C 中有两种简单的方法来定义常量 -
使用#define预处理器。
使用const关键字。
#define 预处理器
下面给出的是使用 #define 预处理器定义常量的形式 -
#define identifier value
下面的例子详细解释了它 -
#include <stdio.h> #define LENGTH 10 #define WIDTH 5 #define NEWLINE '\n' int main() { int area; area = LENGTH * WIDTH; printf("value of area : %d", area); printf("%c", NEWLINE); return 0; }
当上面的代码被编译并执行时,它会产生以下结果 -
value of area : 50
const 关键字
您可以使用const前缀来声明特定类型的常量,如下所示 -
const type variable = value;
下面的例子详细解释了它 -
#include <stdio.h> int main() { const int LENGTH = 10; const int WIDTH = 5; const char NEWLINE = '\n'; int area; area = LENGTH * WIDTH; printf("value of area : %d", area); printf("%c", NEWLINE); return 0; }
当上面的代码被编译并执行时,它会产生以下结果 -
value of area : 50
请注意,以大写字母定义常量是一种良好的编程习惯。
C - 存储类
存储类定义 C 程序中变量和/或函数的范围(可见性)和生命周期。它们位于它们所修改的类型之前。我们在 C 程序中有四种不同的存储类别 -
- 汽车
- 登记
- 静止的
- 外部的
自动存储类
auto存储类别是所有局部变量的默认存储类别。
{ int mount; auto int month; }
上面的示例定义了同一存储类中的两个变量。'auto' 只能在函数内使用,即局部变量。
寄存器存储类
寄存器存储类用于定义应存储在寄存器而不是 RAM 中的局部变量。这意味着该变量的最大大小等于寄存器大小(通常是一个字),并且不能对其应用一元“&”运算符(因为它没有内存位置)。
{ register int miles; }
该寄存器只能用于需要快速访问的变量,例如计数器。还应该注意的是,定义“寄存器”并不意味着变量将存储在寄存器中。这意味着它可能存储在寄存器中,具体取决于硬件和实现限制。
静态存储类
静态存储类指示编译器在程序的生命周期内保持局部变量的存在,而不是在每次进入和离开作用域时创建和销毁它。因此,将局部变量设为静态可以让它们在函数调用之间保持其值。
static 修饰符也可以应用于全局变量。完成此操作后,会导致该变量的范围仅限于声明它的文件。
在 C 编程中,当在全局变量上使用static时,它只会导致该成员的一个副本被该类的所有对象共享。
#include <stdio.h> /* function declaration */ void func(void); static int count = 5; /* global variable */ main() { while(count--) { func(); } return 0; } /* function definition */ void func( void ) { static int i = 5; /* local static variable */ i++; printf("i is %d and count is %d\n", i, count); }
当上面的代码被编译并执行时,它会产生以下结果 -
i is 6 and count is 4 i is 7 and count is 3 i is 8 and count is 2 i is 9 and count is 1 i is 10 and count is 0
外部存储类
extern存储类用于提供对所有程序文件可见的全局变量的引用。当您使用“extern”时,该变量无法初始化,但是它会将变量名称指向先前定义的存储位置。
当你有多个文件并且定义了一个全局变量或函数,并且该全局变量或函数也会在其他文件中使用时,那么extern将在另一个文件中使用,以提供定义的变量或函数的引用。只是为了便于理解,extern用于在另一个文件中声明全局变量或函数。
当有两个或多个文件共享相同的全局变量或函数时,最常使用 extern 修饰符,如下所述。
第一个文件:main.c
#include <stdio.h> int count ; extern void write_extern(); main() { count = 5; write_extern(); }
第二个文件:support.c
#include <stdio.h> extern int count; void write_extern(void) { printf("count is %d\n", count); }
这里,extern用于在第二个文件中声明count,因为它在第一个文件 main.c 中有其定义。现在,编译这两个文件如下 -
$gcc main.c support.c
它将生成可执行程序a.out。当执行该程序时,它会产生以下结果 -
count is 5
C - 操作员
运算符是告诉编译器执行特定数学或逻辑函数的符号。C语言有丰富的内置运算符,并提供以下类型的运算符 -
- 算术运算符
- 关系运算符
- 逻辑运算符
- 按位运算符
- 赋值运算符
- 杂项运算符
在本章中,我们将研究每个运算符的工作方式。
算术运算符
下表列出了C语言支持的所有算术运算符。假设变量A为 10,变量B为 20,则 -
操作员 | 描述 | 例子 |
---|---|---|
+ | 添加两个操作数。 | A + B = 30 |
- | 从第一个操作数中减去第二个操作数。 | A − B = -10 |
* | 将两个操作数相乘。 | A * B = 200 |
/ | 将分子除以分子。 | 乙/甲=2 |
% | 模数运算符和整数除法后的余数。 | B % A = 0 |
++ | 自增运算符将整数值加一。 | A++ = 11 |
-- | 自减运算符将整数值减一。 | A-- = 9 |
关系运算符
下表显示了 C 支持的所有关系运算符。假设变量A为 10,变量B为 20,则 -
操作员 | 描述 | 例子 |
---|---|---|
== | 检查两个操作数的值是否相等。如果是,则条件成立。 | (A == B) 不正确。 |
!= | 检查两个操作数的值是否相等。如果值不相等,则条件成立。 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值。如果是,则条件成立。 | (A > B) 不正确。 |
< | 检查左操作数的值是否小于右操作数的值。如果是,则条件成立。 | (A < B) 为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值。如果是,则条件成立。 | (A >= B) 不正确。 |
<= | 检查左操作数的值是否小于或等于右操作数的值。如果是,则条件成立。 | (A <= B) 为真。 |
逻辑运算符
下表列出了C语言支持的所有逻辑运算符。假设变量A为 1,变量B为 0,则 -
操作员 | 描述 | 例子 |
---|---|---|
&& | 称为逻辑与运算符。如果两个操作数均非零,则条件为真。 | (A && B) 是错误的。 |
|| | 称为逻辑或运算符。如果两个操作数中的任何一个非零,则条件为真。 | (A || B) 为真。 |
! | 称为逻辑非运算符。它用于反转其操作数的逻辑状态。如果条件为真,则逻辑 NOT 运算符会将其设为假。 | !(A && B) 为真。 |
按位运算符
位运算符作用于位并执行逐位运算。&、| 和 ^ 的真值表如下 -
p | q | 质与问 | p| q | p^q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
假设二进制格式 A = 60 和 B = 13,它们将如下 -
A = 0011 1100
B = 0000 1101
-----------------
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
〜A = 1100 0011
下表列出了 C 支持的按位运算符。假设变量“A”保存 60,变量“B”保存 13,则 -
操作员 | 描述 | 例子 |
---|---|---|
& | 如果两个操作数中都存在,则二进制 AND 运算符会将一位复制到结果中。 | (A & B) = 12,即 0000 1100 |
| | 如果任一操作数中存在该位,则二元或运算符会复制该位。 | (A | B) = 61,即 0011 1101 |
^ | 如果在一个操作数中设置了该位,但不是在两个操作数中都设置了该位,则二进制 XOR 运算符会复制该位。 | (A^B)=49,即0011 0001 |
〜 | 二进制一的补码运算符是一元的,具有“翻转”位的效果。 | (~A) = ~(60),即。-0111101 |
<< | 二进制左移运算符。左操作数的值向左移动右操作数指定的位数。 | A << 2 = 240 即 1111 0000 |
>> | 二进制右移运算符。左操作数的值向右移动右操作数指定的位数。 | A >> 2 = 15 即 0000 1111 |
赋值运算符
下表列出了 C 语言支持的赋值运算符 -
操作员 | 描述 | 例子 |
---|---|---|
= | 简单的赋值运算符。将右侧操作数中的值分配给左侧操作数 | C = A + B 将把 A + B 的值赋给 C |
+= | 添加 AND 赋值运算符。它将右操作数添加到左操作数,并将结果分配给左操作数。 | C += A 等价于 C = C + A |
-= | 减法 AND 赋值运算符。它从左操作数中减去右操作数,并将结果赋给左操作数。 | C -= A 相当于 C = C - A |
*= | 乘法与赋值运算符。它将右操作数与左操作数相乘,并将结果赋给左操作数。 | C *= A 相当于 C = C * A |
/= | 除法与赋值运算符。它将左操作数与右操作数相除,并将结果赋给左操作数。 | C /= A 相当于 C = C / A |
%= | 模 AND 赋值运算符。它使用两个操作数取模并将结果分配给左侧操作数。 | C %= A 相当于 C = C % A |
<<= | 左移 AND 赋值运算符。 | C <<= 2 与 C = C << 2 相同 |
>>= | 右移与赋值运算符。 | C >>= 2 与 C = C >> 2 相同 |
&= | 按位与赋值运算符。 | C &= 2 与 C = C & 2 相同 |
^= | 按位异或和赋值运算符。 | C ^= 2 与 C = C ^ 2 相同 |
|= | 按位包含 OR 和赋值运算符。 | C |= 2 与 C = C | 相同 2 |
其他运算符 ↦ sizeof 和三元
除了上面讨论的运算符之外,还有一些其他重要的运算符,包括sizeof和? :由C语言支持。
操作员 | 描述 | 例子 |
---|---|---|
大小() | 返回变量的大小。 | sizeof(a),其中 a 是整数,将返回 4。 |
& | 返回变量的地址。 | &A; 返回变量的实际地址。 |
* | 指向变量的指针。 | *A; |
?: | 条件表达式。 | 如果条件为真?然后值 X :否则值 Y |
C 中的运算符优先级
运算符优先级决定表达式中术语的分组并决定表达式的计算方式。某些运算符的优先级高于其他运算符;例如,乘法运算符的优先级高于加法运算符。
例如,x = 7 + 3 * 2;此处,x 被分配为 13,而不是 20,因为运算符 * 的优先级高于 +,因此它首先乘以 3*2,然后添加到 7。
在这里,优先级最高的运算符出现在表的顶部,优先级最低的运算符出现在底部。在表达式中,将首先计算优先级较高的运算符。
类别 | 操作员 | 关联性 |
---|---|---|
后缀 | () [] -> . ++ - - | 左到右 |
一元 | + - ! ~ ++ - - (类型)* & sizeof | 右到左 |
乘法 | * / % | 左到右 |
添加剂 | + - | 左到右 |
转移 | <<>> | 左到右 |
关系型 | <<=>>= | 左到右 |
平等 | ==!= | 左到右 |
按位与 | & | 左到右 |
按位异或 | ^ | 左到右 |
按位或 | | | 左到右 |
逻辑与 | && | 左到右 |
逻辑或 | || | 左到右 |
有条件的 | ?: | 右到左 |
任务 | = += -= *= /= %=>>= <<= &= ^= |= | 右到左 |
逗号 | , | 左到右 |
C - 决策
决策结构要求程序员指定要由程序评估或测试的一个或多个条件,以及如果确定条件为真则要执行的一个或多个语句,以及可选地如果条件确定则要执行的其他语句确定为假。
下面显示的是大多数编程语言中典型决策结构的一般形式 -
C 编程语言将任何非零和非空值假定为true,如果它为零或null ,则将其假定为false值。
C 编程语言提供以下类型的决策语句。
先生。 | 声明及说明 |
---|---|
1 | if 语句
if语句由一个布尔表达式后跟一个或多个语句组成。 |
2 | if...else 语句
if语句后面可以跟一个可选的else 语句,该语句在布尔表达式为 false 时执行。 |
3 | 嵌套 if 语句
您可以在另一个if或else if语句中使用一个if或else if语句。 |
4 | switch语句
switch语句允许测试变量是否与值列表相等。 |
5 | 嵌套 switch 语句
您可以在另一个switch语句中使用一个switch语句。 |
这 ?: 操作员
我们已经介绍了条件运算符 ? :在上一章中可以用来替换if...else语句。它具有以下一般形式 -
Exp1 ? Exp2 : Exp3;
其中 Exp1、Exp2 和 Exp3 是表达式。注意冒号的使用和位置。
的值?表达式是这样确定的 -
对 Exp1 进行评估。如果为真,则计算 Exp2 并成为整个 ? 的值。表达。
如果 Exp1 为 false,则计算 Exp3 并且其值成为表达式的值。
C - 循环
您可能会遇到这样的情况:一段代码需要执行多次。一般来说,语句是按顺序执行的:首先执行函数中的第一个语句,然后执行第二个语句,依此类推。
编程语言提供了各种控制结构,允许更复杂的执行路径。
循环语句允许我们多次执行一条语句或一组语句。下面给出的是大多数编程语言中循环语句的一般形式 -
C 编程语言提供以下类型的循环来处理循环要求。
先生。 | 循环类型和描述 |
---|---|
1 | while 循环
当给定条件为真时,重复一个语句或一组语句。它在执行循环体之前测试条件。 |
2 | for循环
多次执行一系列语句并缩写管理循环变量的代码。 |
3 | do...while 循环
它更像是一个 while 语句,只不过它测试循环体末尾的条件。 |
4 | 嵌套循环
您可以在任何其他 while、for 或 do..while 循环中使用一个或多个循环。 |
循环控制语句
循环控制语句改变其正常顺序的执行。当执行离开作用域时,在该作用域中创建的所有自动对象都将被销毁。
C 支持以下控制语句。
先生。 | 控制语句和描述 |
---|---|
1 | 中断语句
终止循环或switch语句并将执行转移到紧随循环或 switch 之后的语句。 |
2 | 继续声明
导致循环跳过其主体的其余部分并在重复之前立即重新测试其条件。 |
3 | 转到语句
将控制转移到带标签的语句。 |
无限循环
如果条件永远不会变为假,则循环将成为无限循环。for循环传统上用于此目的。由于形成“for”循环的三个表达式都不是必需的,因此您可以通过将条件表达式留空来创建无限循环。
#include <stdio.h> int main () { for( ; ; ) { printf("This loop will run forever.\n"); } return 0; }
当条件表达式不存在时,假定为真。您可能有一个初始化和增量表达式,但 C 程序员更常用 for(;;) 构造来表示无限循环。
注意- 您可以通过按 Ctrl + C 键终止无限循环。
C-函数
函数是一组共同执行任务的语句。每个 C 程序都至少有一个函数,即main(),并且所有最简单的程序都可以定义附加函数。
您可以将代码划分为单独的函数。如何在不同的函数之间划分代码取决于您,但逻辑上的划分是每个函数执行特定的任务。
函数声明告诉编译器函数的名称、返回类型和参数。函数定义提供了函数的实际主体。
C 标准库提供了许多您的程序可以调用的内置函数。例如,用于连接两个字符串的strcat() 、用于将一个内存位置复制到另一位置的memcpy()以及更多函数。
函数也可以称为方法、子例程或过程等。
定义函数
C 编程语言中函数定义的一般形式如下 -
return_type function_name( parameter list ) { body of the function }
C 编程中的函数定义由函数头和函数体组成。这是函数的所有部分 -
返回类型- 函数可以返回一个值。return_type是函数返回值的数据类型。有些函数执行所需的操作而不返回值。在本例中, return_type 是关键字void。
函数名称- 这是函数的实际名称。函数名和参数列表共同构成函数签名。
参数- 参数就像占位符。当调用函数时,您将一个值传递给参数。该值称为实际参数或参数。参数列表是指函数参数的类型、顺序和数量。参数可选;也就是说,函数可以不包含参数。
函数体- 函数体包含定义函数功能的语句集合。
例子
下面给出的是名为max()的函数的源代码。该函数采用两个参数 num1 和 num2 并返回两者之间的最大值 -
/* function returning the max between two numbers */ int max(int num1, int num2) { /* local variable declaration */ int result; if (num1 > num2) result = num1; else result = num2; return result; }
函数声明
函数声明告诉编译器函数名称以及如何调用该函数。函数的实际主体可以单独定义。
函数声明包含以下部分 -
return_type function_name( parameter list );
对于上面定义的函数 max(),函数声明如下 -
int max(int num1, int num2);
参数名称在函数声明中并不重要,只需要它们的类型,因此以下也是有效的声明 -
int max(int, int);
当您在一个源文件中定义函数并在另一文件中调用该函数时,需要进行函数声明。在这种情况下,您应该在调用该函数的文件顶部声明该函数。
调用函数
创建 C 函数时,您需要定义该函数必须执行的操作。要使用函数,您必须调用该函数来执行定义的任务。
当程序调用函数时,程序控制权转移给被调用的函数。被调用函数执行已定义的任务,当执行其返回语句或到达其函数结束右大括号时,它将程序控制权返回给主程序。
要调用函数,您只需传递所需的参数和函数名称,如果函数有返回值,则可以存储返回值。例如 -
#include <stdio.h> /* function declaration */ int max(int num1, int num2); int main () { /* local variable definition */ int a = 100; int b = 200; int ret; /* calling a function to get max value */ ret = max(a, b); printf( "Max value is : %d\n", ret ); return 0; } /* function returning the max between two numbers */ int max(int num1, int num2) { /* local variable declaration */ int result; if (num1 > num2) result = num1; else result = num2; return result; }
我们保留了 max() 和 main() 并编译了源代码。运行最终的可执行文件时,它将产生以下结果 -
Max value is : 200
函数参数
如果函数要使用参数,则它必须声明接受参数值的变量。这些变量称为函数的形式参数。
形式参数的Behave与函数内的其他局部变量类似,在进入函数时创建并在退出时销毁。
调用函数时,有两种方法可以将参数传递给函数 -