C 语言基础,来喽!(三)

简介: C 语言是一门抽象的、面向过程的语言,C 语言广泛应用于底层开发,C 语言在计算机体系中占据着不可替代的作用,可以说 C 语言是编程的基础,也就是说,不管你学习任何语言,都应该把 C 语言放在首先要学的位置上。下面这张图更好的说明 C 语言的重要性

return 语句

在入门例子程序中,return 语句是最后一条语句。int main(void) 中的 int 表明 main() 函数应返回一个整数。有返回值的 C 函数要有 return 语句,没有返回值的程序也建议大家保留 return 关键字,这是一种好的习惯或者说统一的编码风格。

分号

在 C 语言中,每一行的结尾都要用 ; 进行结束,它表示一个语句的结束,如果忘记或者会略分号会被编译器提示错误。

关键字

下面是 C 语言中的关键字,C 语言的关键字一共有 32 个,根据其作用不同进行划分

数据类型关键字

数据类型的关键字主要有 12 个,分别是

  • char: 声明字符型变量或函数
  • double: 声明双精度变量或函数
  • float: 声明浮点型变量或函数
  • int : 声明整型变量或函数
  • long: 声明长整型变量或函数
  • short : 声明短整型变量或函数
  • signed : 声明有符号类型变量或函数
  • _Bool:  声明布尔类型
  • _Complex :声明复数
  • _Imaginary: 声明虚数
  • unsigned : 声明无符号类型变量或函数
  • void : 声明函数无返回值或无参数,声明无类型指针

控制语句关键字

控制语句循环的关键字也有 12 个,分别是

循环语句

  • for : for 循环,使用的最多
  • do :循环语句的前提条件循环体
  • while:循环语句的循环条件
  • break : 跳出当前循环
  • continue:结束当前循环,开始下一轮循环

条件语句

  • if:条件语句的判断条件
  • else : 条件语句的否定分支,与 if 连用
  • goto: 无条件跳转语句

开关语句

  • switch: 用于开关语句
  • case:开关语句的另外一种分支
  • default : 开关语句中的其他分支

返回语句

retur:子程序返回语句(可以带参数,也看不带参数)

存储类型关键字

  • auto : 声明自动变量 一般不使用
  • extern : 声明变量是在其他文件正声明(也可以看做是引用变量)
  • register : 声明寄存器变量
  • static: 声明静态变量

其他关键字

  • const: 声明只读变量
  • sizeof : 计算数据类型长度
  • typedef: 用以给数据类型取别名
  • volatile : 说明变量在程序执行中可被隐含地改变

C 中的数据

我们在了解完上面的入门例子程序后,下面我们就要全面认识一下 C 语言程序了,首先我们先来认识一下 C 语言最基本的变量与常量。

变量和常量

变量和常量是程序处理的两种基本对象。

有些数据类型在程序使用之前就已经被设定好了,在整个过程中没有变化(这段话描述不准确,但是为了通俗易懂,暂且这么描述),这种数据被称为常量(constant)。另外一种数据类型在程序执行期间可能会发生改变,这种数据类型被称为 变量(variable)。例如 int number 就是一个变量,而3.1415 就是一个常量,因为 int number 一旦声明出来,你可以对其任意赋值,而 3.1415 一旦声明出来,就不会再改变。

变量名

有必要在聊数据类型之前先说一说变量名的概念。变量名是由字母和数字组成的序列,第一个字符必须是字母。在变量名的命名过程中,下划线 _ 被看作字母,下划线一般用于名称较长的变量名,这样能够提高程序的可读性。变量名通常不会以下划线来开头。在 C 中,大小写是有区别的,也就是说,a 和 A 完全是两个不同的变量。一般变量名使用小写字母,符号常量(#define 定义的)全都使用大写。选择变量名的时候,尽量能够从字面上描述出变量的用途,切忌起这种 abc 毫无意义的变量。

还需要注意一般局部变量都会使用较短的变量名,外部变量使用较长的名字。

数据类型

在了解数据类型之前,我们需要先了解一下这些概念 位、字节和字

位、字节和字都是对计算机存储单元的描述。在计算机世界中,最小的单元是 位(bit),一个位就表示一个 0 或 1,一般当你的小伙伴问你的电脑是 xxx 位,常见的有 32 位或者 64 位,这里的位就指的是比特,比特就是 bit 的中文名称,所以这里的 32 位或者 64 位指的就是 32 bit 或者 64 bit。字节是基本的存储单元,基本存储单元说的是在计算机中都是按照字节来存储的,一个字节等于 8 位,即 1 byte = 8 bit。字是自然存储单位,在现代计算机中,一个字等于 2 字节。

C 语言的数据类型有很多,下面我们就来依次介绍一下。

整型

C 语言中的整型用 int 来表示,可以是正整数、负整数或零。在不同位数的计算机中其取值范围也不同。不过在 32 位和 64 位计算机中,int 的取值范围是都是 2^32 ,也就是 -2147483648 ~ +2147483647,无符号类型的取值范围是 0 ~ 4294967295。

整型以二进制整数存储,分为有符号数和无符号数两种形态,有符号数可以存储正整数、负整数和零;无符号只能存储正整数和零。

可以使用 printf 打印出来 int 类型的值,如下代码所示。

#include <stdio.h> 
int main(){
 int a = -5;
 printf("%d\n",a);
 unsigned int b = 6;
 printf("%d\n",b);
}

C 语言还提供 3 个附属关键字修饰整数类型,即 short、long 和 unsigned

  • short int 类型(或者简写为 short)占用的存储空间可能比 int 类型少,适合用于数值较小的场景。
  • long int 或者 long 占用的存储空间可能比 int 类型多,适合用于数值较大的场景。
  • long long int 或者 long long(C99 加入)占用的存储空间比 long 多,适用于数值更大的场合,至少占用 64 位,与 int 类似,long long 也是有符号类型。
  • unsigned int 或 unsigned 只用于非负值的场景,这种类型的取值范围有所不同,比如 16 位的 unsigned int 表示的范围是 0 ~ 65535 ,而不是 -32768 ~ 32767。
  • 在 C90 标准中,添加了 unsigned long int 或者 unsigned long 和 unsigned short int 或 unsigned short 类型,在 C99 中又添加了 unsigned long long int 或者 unsigned long long 。
  • 在任何有符号类型前面加 signed ,可强调使用有符号类型的意图。比如 short、short int、signed short、signed short int 都表示一种类型。

比如上面这些描述可以用下面这些代码来声明:

long int lia;
long la;
long long lla;
short int sib;
short sb;
unsigned int uic;
unsigned uc;
unsigned long uld;
unsigned short usd;

这里需要注意一点,unsigned 定义的变量,按照 printf 格式化输出时,是能够显示负值的,为什么呢?不是 unsigned 修饰的值不能是负值啊,那是因为 unsigned 修饰的变量,在计算时会有用,输出没什么影响,这也是 cxuan 刚开始学习的时候踩的坑。

我们学过 Java 的同学刚开始都对这些定义觉得莫名其妙,为什么一个 C 语言要对数据类型有这么多定义?C 语言真麻烦,我不学了!

千万不要有这种想法,如果有这种想法的同学,你一定是被 JVM 保护的像个孩子!我必须从现在开始纠正你的这个想法,因为 Java 有 JVM 的保护,很多特性都做了优化,而 C 就像个没有伞的孩子,它必须自己和这个世界打交道!

上面在说 short int 和 long int 的时候,都加了一个可能,怎么,难道 short int 和 long int 和 int 还不一样吗?

这里就是 C 语言数据类型一个独特的风格。

为什么说可能,这是由于 C 语言为了适配不同的机器来设定的语法规则,在早起的计算机上,int 类型和 short 类型都占 16 位,long 类型占 32 位,在后来的计算机中,都采用了 16 位存储 short 类型,32 位存储 int 类型和 long 类型,现在,计算机普遍使用 64 位 CPU,为了存储 64 位整数,才引入了 long long 类型。所以,一般现在个人计算机上常见的设置是 long long 占用 64 位,long 占用 32 位,short 占用 16 位,int 占用 16 位或者 32 位。

char 类型

char 类型一般用于存储字符,表示方法如下

char a = 'x';
char b = 'y';

char 被称为字符类型,只能用单引号 '' 来表示,而不能用双引号 “” 来表示,这和字符串的表示形式相反。

char 虽然表示字符,但是 char 实际上存储的是整数而不是字符,计算机一般使用 ASCII 来处理字符,标准 ASCII 码的范围是 0 - 127 ,只需 7 位二进制数表示即可。C 语言中规定 char 占用 1 字节。

其实整型和字符型是相通的,他们在内存中的存储本质是相通的,编译器发现 char ,就会自动转换为整数存储,相反的,如果给 int 类型赋值英文字符,也会转换成整数存储,如下代码

#include <stdio.h>
int main(){
 char a = 'x';
 int b;
 b = 'y';
 printf("%d\n%d\n",a,b);
}

输出

120

121

所以,int 和 char 只是存储的范围不同,整型可以是 2 字节,4 字节,8 字节,而字符型只占 1 字节。

有些 C 编译器把 char 实现为有符号类型,这意味着 char 可表示的范围是 -128 ~ 127,而有些编译器把 char 实现为无符号类型,这种情况下 char 可表示的范围是 0 - 255。signed char 表示的是有符号类型,unsigned char 表示的是无符号类型。

_Bool 类型

_Bool 类型是 C99 新增的数据类型,用于表示布尔值。也就是逻辑值 true 和 false。在 C99 之前,都是用 int 中的 1 和 0 来表示。所以 _Bool 在某种程度上也是一种数据类型。表示 0 和 1 的话,用 1 bit(位)表示就够了。

float、double 和 long double

整型对于大多数软件开发项目而言就已经够用了。然而,在金融领域和数学领域还经常使用浮点数。C 语言中的浮点数有 float、double 和 long double 类型。浮点数类型能够表示包括小数在内更大范围的数。浮点数能表示小数,而且表示范围比较大。浮点数的表示类似于科学技术法。下面是一些科学记数法示例:

数字 科学记数法 指数记数法
1000000000 1 * 10^9 1.0e9
456000 4.56 * 10^5 4.56e5
372.85 3.7285 * 10 ^ 2 3.7285e2
0.0025 2.5 * 10 ^ -3 2.5e-3

C 规定 float 类型必须至少能表示 6 位有效数字,而且取值范围至少是 10^-37 ~ 10^+37。通常情况下,系统存储一个浮点数要占用 32 位。

C 提供的另一种浮点类型是 double(双精度类型)。一般来说,double 占用的是 64 位而不是 32 位。

C 提供的第三种类型是 long double ,用于满足比 double 类型更高的精度要求。不过,C 只保证了 long double 类型至少与 double 类型相同。

浮点数的声明方式和整型类似,下面是一些浮点数的声明方式。

#include <stdio.h>
int main(){
 float aboat = 2100.0;
 double abet = 2.14e9;
 long double dip = 5.32e-5;
 printf("%f\n", aboat);
 printf("%e\n", abet);
 printf("%Lf\n", dip);
}

printf() 函数使用 %f 转换说明打印十进制计数法的 float 和 double 类型浮点数,用 %e 打印指数记数法的浮点数。打印 long double 类型要使用 %Lf 转换说明。

关于浮点数,还需要注意其上溢下溢的问题。

上溢指的是是指由于数字过大,超过当前类型所能表示的范围,如下所示

float toobig = 3.4E38 * 100.0f;
printf("%e\n",toobig);

输出的内容是 inf,这表示 toobig 的结果超过了其定义的范围,C 语言就会给 toobig 赋一个表示无穷大的特定值,而且 printf 显示值为 inf 或者 infinity 。

下溢:是指由于数值太小,低于当前类型所能表示的最小的值,计算机就只好把尾数位向右移,空出第一个二进制位,但是与此同时,却损失了原来末尾有效位上面的数字,这种情况就叫做下溢。比如下面这段代码

float toosmall = 0.1234e-38/10;
printf("%e\n", toosmall);

复数和虚数类型

许多科学和工程计算都需要用到复数和虚数,C99 标准支持复数类型和虚数类型,C 语言中有 3 种复数类型:float _Complex、double _Complex 和 long double  _Complex

C 语言提供的 3 种虚数类型:float _Imaginary、 double _Imaginary 和 long double _Imaginary

如果包含 complex.h 头文件的话,便可使用 complex 替换 _Complex,用 imaginary 替代 _Imaginary。

其他类型

除了上述我们介绍过的类型之外,C 语言中还有其他类型,比如数组、指针、结构和联合,虽然 C 语言没有字符串类型,但是 C 语言却能够很好的处理字符串。

常量

在很多情况下我们需要常量,在整个程序的执行过程中,其值不会发生改变,比如一天有 24 个小时,最大缓冲区的大小,滑动窗口的最大值等。这些固定的值,即称为常量,又可以叫做字面量

常量也分为很多种,整型常量,浮点型常量,字符常量,字符串常量,下面我们分别来介绍

整数常量

整数常量可以表示为十进制、八进制或十六进制。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。

330         /* 合法的 */
315u        /* 合法的 */
0xFeeL      /* 合法的 */
048         /* 非法的:8 进制不能定义 8 */

浮点型常量

浮点型常量由整数部分、小数点、小数部分和指数部分组成。你可以使用小数形式或者指数形式来表示浮点常量。

当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。当使用指数形式表示时, 必须包含小数点、指数,或同时包含两者。带符号的指数是用 e 或 E 引入的。

3.14159       /* 合法的 */
314159E-5L    /* 合法的 */
510E          /* 非法的:不完整的指数 */
210f          /* 非法的:没有小数或指数 */

字符常量

C 语言中的字符常量使用单引号(即撇号)括起来的一个字符。如‘a’,‘x’,'D',‘?’,‘$’ 等都是字符常量。注意,‘a’ 和 ‘A’ 是不同的字符常量。

除了以上形式的字符常量外,C 还允许用一种特殊形式的字符常量,就是以一个 “\” 开头的字符序列。例如,前面已经遇到过的,在 printf 函数中的‘\n’,它代表一个换行符。这是一种控制字符,在屏幕上是不能显示的。

常用的以 “\” 开头的特殊字符有

微信图片_20220417160502.png

表中列出的字符称为“转义字符”,意思是将反斜杠(\)后面的字符转换成另外的意义。如 ‘\n’ 中的 “n” 不代表字母 n 而作为“换行”符。

表中最后第 2 行是用ASCII码(八进制数)表示一个字符,例如 ‘\101’ 代表 ASCII 码(十进制数)为 65 的字符 “A”。‘\012’(十进制 ASCII 码为 10)代表换行。

需要注意的是 ‘\0’ 或 ‘\000’ 代表 ASCII 码为 0 的控制字符,它用在字符串中。

字符串常量

字符串常量通常用 "" 进行表示。字符串就是一系列字符的集合。一个字符串包含类似于字符常量的字符:普通的字符、转义序列和通用的字符。

常量定义

C 语言中,有两种定义常量的方式。

  1. 使用 #define 预处理器进行预处理
  2. 使用 const 关键字进行处理

下面是使用 #define 预处理器进行常量定义的代码。

#include <stdio.h>
#define LENGTH 5
#define WIDTH 10
int main(){
 int area = LENGTH * WIDTH;
 printf("area = %d\n", area);
}

同样的,我们也可以使用 const 关键字来定义常量,如下代码所示

#include <stdio.h>
int main(){
 const int LENGTH = 10;
 const int WIDTH = 5;
 int area;
 area = LENGTH * WIDTH;
 printf("area = %d\n", area);
}

那么这两种常量定义方式有什么不同呢?

编译器处理方式不同

使用 #define 预处理器是在预处理阶段进行的,而 const 修饰的常量是在编译阶段进行。

类型定义和检查不同

使用 #define 不用声明数据类型,而且不用类型检查,仅仅是定义;而使用 const 需要声明具体的数据类型,在编译阶段会进行类型检查。

相关文章
|
28天前
R 语言教程 之 R 语言基础 1
本教程介绍R语言基础,涵盖从“Hello, World!”程序到变量命名规则及赋值方法等内容。示例展示了如何使用不同符号进行变量赋值,以及如何查看和删除已定义的变量。
26 1
|
26天前
R 语言教程 之 R 语言基础 5
R语言基础教程第五部分,介绍如何使用 `sink()` 函数将控制台输出重定向至文件,支持覆盖或追加写入,并可通过设置 `split` 参数同时在控制台和文件中显示输出。
20 1
|
26天前
|
Windows
R 语言教程 之 R 语言基础 4
本节介绍了 R 语言中的 `cat()` 函数,用于文本输出和文件写入。`cat()` 可以连接多个参数并输出,自动在各参数间添加空格。通过设置 `file` 参数,可将输出内容保存至指定文件,使用 `append=TRUE` 可实现内容追加而非覆盖。
25 1
|
27天前
|
JavaScript Python
R 语言教程 之 R 语言基础 3
《R 语言教程之 R 语言基础 3》介绍了 R 语言中的基本输入输出操作,重点讲解了 `print()` 函数的使用方法及其在输出数字、字符串时的表现。此外,还简要说明了 R 语言作为解释型语言的特点,可以直接在命令行中执行并显示结果。
22 1
|
27天前
R 语言教程 之 R 语言基础 2
R 语言基础教程第二部分,介绍交互式编程与文件脚本。通过命令行启动 R 解释器进行实时编码,使用 `q()` 退出。示例文件 `Baidu-test.R` 展示了如何创建和运行 R 脚本,输出字符串 &quot;Baidu&quot;。
28 1
|
25天前
|
Java Shell Python
R 语言教程 之 R 语言基础 6
《R 语言教程之 R 语言基础 6》介绍了 R 语言中的输入输出功能,重点讲解了文字输入及从文件读取文字的方法。R 语言作为解释型语言,其输入输出机制与 C、Java 等编译型语言不同,更接近于终端脚本语言。文中通过 `readLines` 函数示例,演示了如何从文件中读取内容为字符串,并强调了文本文件每行结尾需有换行符的要求。
22 0
|
25天前
R 语言教程 之 R 语言基础 7
R语言基础第七课,介绍了R语言中的输入输出方法,包括数据结构直接保存为CSV、Excel等格式的功能。此外,还讲解了如何使用`getwd()`和`setwd()`函数获取和设置工作目录,示例代码展示了设置及查看工作目录的操作。
23 0
|
6月前
|
存储 编译器 程序员
C++语言基础学习
C++语言基础学习
|
6月前
|
存储 编译器 C++
|
安全 Java C#
C#语言基础知识
C#语言基础知识
68 0
下一篇
DataWorks