外观
C 语言入门(二)
前言
今天来学十分容易的第二章🤗
二、语法基础
2.1 程序的结构
再来解读一下经典的 C 程序😉
提示
所有的符号一律采用英文符号!
c
#include <stdio.h>
int main(void) {
// 打印 Hello World
printf("Hello World\n");
return 0;
}
#include <stdio.h>
:预处理器,加载头文件stdio.h
。int main(){}
:主函数,返回值为int型,小括号为形参,大括号为函数体。printf("Hello World\n");
:printf关键字,作用是打印。"Hello World\n"
是字符串。return 0;
:return关键字,返回值。每个语句表达式结尾要加;
代表语句结束。
2.2 注释
注释在C语言程序中不参与编译。是一种对程序的解释说明。也就是说,注释对实际代码没有影响。
C 语言的注释有两种表示方法
c
// 这是单行注释,只在一行有效,也可放在语句尾部
/*我是多行注释
可以换行
在多行有效*/
2.3 标识符和关键字
标识符
在编程语言中,标识符是用户编程时使用的名字,变量、常量、函数、语句块都有名字,是用来标识某个实体的一个符号。
C语言中标识符的命名规范
- 标识符由字母(包括大写和小写)、数字和下划线(
_
)组成,并且首字母不能是数字。 - 不能把C的关键字作为用户的标识符,不能重复标识。
- 标识符长度是由机器上的编译系统决定的,一般的限制为8字符。
- 标识符对大小写敏感,即严格区分大小写。一般对变量名用小写,符号常量命名用大写。
- 标识符命名应做到"见名知意"。
关键字
C语言的关键字,是C语言保留的一些有特殊作用词语。一共有32个关键字
自己搜一下看看吧,不需要记😶
2.4 数据类型
在 C 语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间,以及如何解释存储的位模式。
C 中的类型可分为以下几种:
整型
整数型可以是十进制、八进制或十六进制。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。整数型也可以带一个后缀,U 表示无符号整数[unsigned],L 表示长整数[long]。后缀对大小写不敏感,U 和 L 的顺序任意。
类型 | 存储大小 | 值范围 |
---|---|---|
char | 1 字节 | -128 到 127 或 0 到 255 |
unsigned char | 1 字节 | 0 到 255 |
signed char | 1 字节 | -128 到 127 |
int | 2 或 4 字节 | -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647 |
unsigned int | 2 或 4 字节 | 0 到 65,535 或 0 到 4,294,967,295 |
short | 2 字节 | -32,768 到 32,767 |
unsigned short | 2 字节 | 0 到 65,535 |
long | 4 字节 | -2,147,483,648 到 2,147,483,647 |
unsigned long | 4 字节 | 0 到 4,294,967,295 |
浮点型
浮点型由整数部分、小数点、小数部分和指数部分组成。当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。当使用指数形式表示时,必须包含小数点、指数,或同时包含两者。带符号的指数是用 e 或 E 引入的。
类型 | 存储大小 | 值范围 | 精度 |
---|---|---|---|
float | 4 字节 | 1.2E-38 到 3.4E+38 | 6 位有效位 |
double | 8 字节 | 2.3E-308 到 1.7E+308 | 15 位有效位 |
long double | 16 字节 | 3.4E-4932 到 1.1E+4932 | 19 位有效位 |
字符型
字符型是括在单引号中,可以是一个普通的字符(例如 x
)、一个转义序列(例如 \t
),或一个通用的字符(例如 \u02C0
)。
类型 | 存储大小 |
---|---|
char | 1 字节 |
char 变量名[] | n+1 字节 |
扩展
在 C 中,有一些特定的字符,当它们前面有反斜杠时,它们就具有特殊的含义,被用来表示如换行符(\n)或制表符(\t)等。
转义序列 | 含义 |
---|---|
\\ | \ 字符 |
\' | ' 字符 |
\" | " 字符 |
\? | ? 字符 |
\a | 警报铃声 |
\b | 退格键 |
\f | 换页符 |
\n | 换行符 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ooo | 一到三位的八进制数 |
\xhh . . . | 一个或多个数字的十六进制数 |
字符串
字符串字面值或常量是括在双引号 " " 中的。一个字符串包含类似于字符常量的字符,普通的字符、转义序列和通用的字符。字符串常量在内存中以结尾符 \0
(null 字符)结尾。
通常编译器会对字符串自动添加
\0
,不需要显式写出来😉
类型修饰符
void 类型
void 类型指定没有可用的值。它通常用于以下三种情况下:
类型 | 例子 |
---|---|
函数返回为空 | void exit (int status); |
函数参数为空 | int rand(void); |
指针指向 void | void *malloc( size_t size ); |
类型转换
类型转换是将一个数据类型的值转换为另一种数据类型的值。
C 语言中有两种类型转换:
- 隐式类型转换:在表达式中自动发生的,无需进行任何明确的指令或函数调用。通常是小向大自动转换类型。隐式类型转换也可能会导致数据精度丢失或数据截断。
- 显式类型转换:使用强制类型转换运算符,将一个数据类型的值强制转换为另一种数据类型的值。强制类型转换可以使程序员在必要时对数据类型进行更精确的控制,但也可能会导致数据丢失或截断。
c
// 隐式类型转换
int i = 10;
float f = 3.14;
double d = i + f; // 隐式将int类型转换为double类型
// 显式类型转换实例
double d = 3.14159;
int i = (int)d; // 显式将double类型转换为int类型
2.5 变量和常量
变量的声明
C 语言的变量,必须先声明后使用。每个变量都有自己的类型[type]。声明变量时,必须把变量的类型告诉编译器。
c
int height;
如果几个变量具有相同类型,可以在同一行声明。
c
int height, width;
// 等同于
int height;
int width;
变量的赋值
注意
C 语言在变量声明时,就为它分配内存空间,但是不会清除内存里面原来的值。这导致声明变量以后,变量会是一个随机的值。所以,变量一定要赋值以后才能使用。
变量的值应该与类型一致,不应该赋予不相符的值,比如 num
的类型是整数,就不应该赋值为小数。虽然 C 语言会自动转换类型,但是应该避免赋值运算符两侧的类型不一致。
c
int num;
num = 42;
// or
int num = 42;
// or
// 多个相同类型变量的赋值,可以写在同一行。
int x = 1, y = 2;
扩展
C 语言有左值[left value]和右值[right value]的概念:左值是可以放在赋值运算符左边的值,一般是变量;右值是可以放在赋值运算符右边的值,一般是一个具体的值。这是为了强调有些值不能放在赋值运算符的左边。
变量的作用域
作用域[scope]指的是变量生效的范围。C 语言的变量作用域主要有两种:文件作用域[file scope]和块作用域[block scope]。
- 文件作用域[file scope]:在源码文件顶层声明的变量,从声明的位置到文件结束都有效。
c
// 任何地方可见
int x = 1;
int main(void) {
printf("%i\n", x);
}
- 块作用域[block scope]:由大括号
{}
组成的代码块,它形成一个单独的作用域。凡是在块作用域里面声明的变量,只在当前代码块有效,代码块外部不可见。
c
int a = 12;
if (a == 12) {
int b = 99;
// 只在块内可见
printf("%d %d\n", a, b); // 12 99
}
printf("%d\n", a); // 12
printf("%d\n", b); // 出错
- 嵌套代码块:代码块内部还有代码块,这时就形成了多层的块作用域。它的规则是:内层代码块可以使用外层声明的变量,但外层不可以使用内层声明的变量。如果内层的变量与外层同名,那么会在当前作用域覆盖外层变量。通常遵循就近原则。
c
{
int i = 10;
{
int i = 20;
printf("%d\n", i); // 20
}
printf("%d\n", i); // 10
}
常量
常量是固定值,相比于变量,只不过常量的值在定义后不能进行修改。
不让改就别改,咋这犟,这孩子😤
定义常量
在 C 中,有两种简单的定义常量的方式:
- 使用
#define
预处理器:#define
可以在程序中定义一个常量,它在编译时会被替换为其对应的值。 - 使用
const
关键字:const
关键字用于声明一个只读变量,即该变量的值不能在程序运行时修改。
#define 预处理器
下面是使用 #define
预处理器定义常量的形式:
c
#define PI 3.14159
// 在程序中使用该常量时,编译器会将所有的 PI 替换为 3.14159。
扩展
#define
预处理指令,在定义常量时,预处理器会在编译之前将所有使用定义的常量的地方替换为定义的值。这种替换是简单的文本替换,不会进行类型检查或其他编译时检查而且也并不会在内存中分配空间给常量。因此,#define
定义的常量实际上是一种文本替换,而不是真正意义上的变量。
const 关键字
请记住,把常量定义为大写字母形式,是一个很好的编程习惯😇
可以使用 const
前缀声明指定类型的常量,如下所示:
c
const int MAX_VALUE = 100;
// 在程序中使用该常量时,其值将始终为100,并且不能被修改。
#define 与 const 区别
通常情况下,还是建议使用
const
关键字来定义常量,因为它具有类型检查和作用域的优势,而#define
仅进行简单的文本替换,可能会导致一些意外的问题🤨
#define
预处理指令和 const
关键字在定义常量时有一些区别:
- 替换机制:
#define
是进行简单的文本替换,而const
是声明一个具有类型的常量。#define
定义的常量在编译时会被直接替换为其对应的值,而const
定义的常量在程序运行时会分配内存,并且具有类型信息。 - 类型检查:
#define
不进行类型检查,因为它只是进行简单的文本替换。而const
定义的常量具有类型信息,编译器可以对其进行类型检查。这可以帮助捕获一些潜在的类型错误。 - 作用域:
#define
定义的常量没有作用域限制,它在定义之后的整个代码中都有效。而const
定义的常量具有块级作用域,只在其定义所在的作用域内有效。 - 调试和符号表:使用
#define
定义的常量在符号表中不会有相应的条目,因为它只是进行文本替换。而使用const
定义的常量会在符号表中有相应的条目,有助于调试和可读性。
写在最后
其实还有许多和 C 语言风格不同的编程语言(比如 Lisp),感兴趣可以去看看🧐
这些是 C 语言最基础的知识,其他流行高级语言也和它 ”不谋而合“。