C语言基础
一段简单的代码分析
# include <stdio.h>
int main() { // 程序里面有且仅有一个主函数
printf("Hello,World!\n");
return 0;
}
程序的第一行 #include <stdio.h> 是预处理器指令,告诉 C 编译器在实际编译之前要包含 stdio.h 文件。
第二行 int main() 是主函数,程序在这里执行,C语言程序都是从 main 函数开始执行。
第三行 printf(...) 是 C 中另一个可用的函数,会在屏幕上显示消息 “Hello World”。
最后一行 return 0; 终止 main() 函数,并返回值 0 。
基础语法
-
英文分号
;,在 C 程序中,分号是语句结束符。也就是说,每个语句必须以分号结束。 -
C 语言中的注释有两种: 以
//开始的单行注释,这种注释可以单独占一行 ;/* */这种个数的注释可以单行或者多行;不能在注释内嵌套注释,注释也不能出现在字符串或字符值中。 -
C 标识符是用来标识变量、函数,或任何其它用户自定义项目的名称。
- 一个标识符以字母 A-Z 或 a-z 或 下划线_ 开始,不能以数字开始,后面跟零个或多个字母、下划线和数字(0-9)。
- C 标识符内不允许出现标点符号,比如 @、$ 和 %。
- C 是区分大小写的编程语言。
-
C 语言自己保留的关键字,编写程序时不能与之重复,如变量 定义
int/char/double等保留字。 -
C 中的空格
- 只包含空格的行,被称为空白行,可能带有注释,C 编译器会完全忽略它。
- 在 C 中,空格用于描述空白符、制表符和注释。空格分割语句的各个部分,让编译器能识别语句中的某个元素(比如 int),在哪里结束,下一个元素从哪里开始。
int age,int 和 age 之间必须至少有一个空格字符(通常是一个空白符),这样编译器才能够区分它们。fruit = apples + oranges; // 获取水果的总数fruit 和 =,或者 = 和 apples 之间的空格字符不是必需的,但是为了增强可读性,可以根据需要适当增加一些空格。
-
sizeof 获取存储字节: 为了得到某个类型或某个变量在特定平台的准确大小,可以使用 sizeof 运算符。表示式 sizeof(type) 得到对象或类型的存储字节大小。,比如: sizeof(int)、sizeof(12)
-
void 类型用于 指定没有可用的值。它通常用于以下三种情况:
| 1 | 函数返回值为空 C 中有各种函数都不返回值,不返回值的返回类型为空 例如: void exit(int status); |
| 2 | 函数参数为空 C 中有各种函数不接受任何参数。不带参数可以接受一个 void,可以直接不写。 例如 int rand(void); |
| 3 | 指针指向 void 类型为 void* 的指针代表对象的地址,而不是类型。 例如,内存分配函数 void * malloc(size_tsize);返回指向 void 的指针,可以转换为任意类型 |
变量
变量其实只不过是程序可操作的存储区的名称。C 中每个变量都有特定的类型,类型决定了变量的大小和布局,该范围内的值可以存储在内存中,运算符可应用于变量上。
变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。大写字母和小写字母是不同的,因为 C 是大小写敏感的。
变量定义:指定一个数据类型,并包含该类型的一个或多个变量的列表,如下所示:
type variable_list;
在这里 type 必须是一个有效的 c 数据类型,可以是 char、w_char、int、float、double 或任何用户自定义的对象, variable_list 可以由一个或多个标识符名称组成,多个标识符之间用逗号分割。下面列出几个有效的声明:
int i,j,k;
变量可以在声明的时候被初始化(指定一个初始值)。初始化器由一个等号,后跟一个常量表达式组成,如下所示:
type variable_name = value;
下面是几个实例:
int d = 3, f =5; // 定义并初始化整型变量 d 和 f
char x = 'x'; //字符型变量 x 的值为 x'
定义一维数组
定义一维数组
type arrayName[arraySize]
定义枚举类型
枚举第一个元素默认为 0, 可以赋其它值。
枚举元素的值 默认在前一个元素基础上加1;
enum DAY {
MON = 1,TUE,WED,THU,FRI,SAT,SUN
};
表达式
C 中有两种类型的表达式:
左值(lvalue): 指向内存位置的表达式被称为左值(lvalue)表达式。左值表达式可以出现在赋值号的左边或右边。
右值(rvalue):术语右值(rvalue) 指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。
常量
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0表示八进制,不带前缀则默认表示十进制。
浮点常量由 整数部分、小数点、小数部分和指数部分组成。可以使用小数形式或者指数形式来表示浮点常量,如:
3.14159
314159E-5
字符常量是括在单引号中,可以是一个普通的字符(例如 'x')、一个转义序列(例如 '\t')。 在 C 中,有一些特定的字符,当它们前面有反斜杠时,它们就具有特殊的含义,被用来表示如换行符 (\n) 或制表符 (\t)
字符串的字面值或常量是括在双引号 "" 中的。一个字符串包含类似于字符常量的字符: 普通字符、转义序列和通用的字符。
宏定义
#define 用来定义一个可以代替值的宏,语法格式如下:
# define 宏名称 值
例如
# define LENGTH 10 // 后续使用可用 LENGTH 代替 10 这个常量。
关键字
const 关键字
const 关键字定义一个 只读的变量,本质是修改了变量的存储方式为只读。
const int LENGTH = 10;// 定义变量 LENGTH = 10 ,且只读,即无法修改 LENGTH 的值。
static 关键字
使用 static 修饰局部变量可以在函数调用之间保持局部变量的值,这种方式不推荐。
static 修饰符 也可以应用于全局变量或函数。当 static 修饰全局变量或函数时,会使变量或函数的作用域限制在声明它的文件内。
避免被其它文件误用。
extern 关键字
extern 关键字用于 提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。
可以这么理解,extern 是 用来在另一个文件中声明一个全局变量或函数。extern 修饰符通常用于当有 两个或多个文件共享相同的全局变量或函数的时候
typedef 关键字
typedef 关键字为 类型取一个新的名字。下面的实例为单字节数字定义了一个术语 BYTE: typedef unsigned char BYTE
在这个类型定义之后,标识符 BYTE 可以作为类型 unsigned char 的缩写,例如: BYTE b1,b2;
#define 为值取一个名字,typedef 为类型取一个名字。
运算符
算数运算符
下表显示了 C 语言支持的所有算数运算符。假设变量 A 的值为 10,变量 B 的值 为 20 ,则:
| 运算符 | 描述 | 实例 |
|---|---|---|
| + | 把两个操作数相加 | A+B = 30 |
| - | 把两个操作数相减 | A-B = -10 |
| * | 把两个操作数相乘 | A*B = 200 |
| ÷ | 分子除以分母 | B / A = 2 |
| % | 取模运算符,整除后的余数 | B % A = 0 |
| ++ | 自增运算符,整数值增加 1 | A++ 将得到 11 |
| -- | 自减运算符,整数值减少 1 | 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)为真 |
| ! | 称为逻辑非运算符,用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假 | !(A && B)为真 |
杂项运算符
下表列出了 C 语言支持的其它一些重要的运算符,包括 sizeof 和 ?:
| 运算符 | 描述 | 实例 |
|---|---|---|
| sizeof() | 返回变量的大小,字节大小 | sizeof(a) 将返回 4,其中 a 是整数。 |
| & | 返回变量的地址,取地址符号 | &a; 将给出变量的实际地址 |
| * | 指向一个变量 | *a; 将指向一个变量 |
| ? | 条件表达式 | 如果条件为真 ? 则值为 X : 否则值为 Y |
判断语句
判断结构要求程序员指定一个或多个要评估或测试的条件,以及条件为真时要执行的语句(必需的)和条件为假时要执行的语句(可选的)。C 语言把 任何非零或非空的值假定为 true,把 零 或 null 假定为 false
if(boolean_expression){
//如果布尔表达式为真将执行的语句
}
if(boolean_expression){
//如果布尔表达式为真将执行的语句
}
switch(boolean_expression){
case constant_expression:
statement(s);
break;
case constant_expression:
statement(s);
break;
// 可以有任意数量的 case 语句
default: // 可选的
statement(s);
}
循环语句
循环语句允许我们多次执行一个语句或语句组,C 语言提供了以下几种循环类型:
while(condition){
statement(s);
}
for(init; condition; increment) {
statement(s);
}
do {
statement(s);
} while (condition);
break 语句
C 语言中的 break 语句有以下两种用法:
-
当 break 语句出现在 一个循环内时,循环会立即终止,且程序流将 继续执行紧接着循环的下一条语句
-
它 可用于终止 switch 语句中的一个 case 。
如果使用的是嵌套循环(即一个循环内嵌套另一个循环),break 语句会停止执行最内层的循环,然后开始执行该块之后的下一行代码。
continue 语句
C 语言中的 continue 语句会跳过当前循环中的代码,强迫开始下一次循环。
对于 for 循环,continue 语句执行后自增语句仍然会执行。对于 while 和 do...while 循环,continue 语句重新执行语句判断条件。
goto 语句
C 语言中的 goto 语句允许把控制无条件转移到同一函数内的被标记的语句
C 作用域
局部变量: 在某个函数或块内部声明的变量称为局部变量。它们只能被函数或该代码块内部的语句使用。局部变量在函数外部是不可知的。
全局变量是定义在函数外部,通常是在程序的顶部。全局变量在整个程序生命周期内都是有效的,在任意的函数内部能访问全局变量。全局变量可以被任何函数访问。也就是说,全局变量在声明后整个程序中都是可用的。
在程序中,局部变量和全局变量的名称可以相同,但是 在函数内,如果两个名字相同,会使用局部变量 ,全局变量不会被使用。
C 内存管理
定义一个指针,必须 使其指向某个存在的内存空间的地址,才能使用 ,否则使用野指针会造成段错误,内存分配与释放函数如下:
void free(void *addr); 该函数释放 addr 所指向的内存块,释放的是动态分配的内存空间。
void *malloc(int size); 在堆区分配一块指定大小为 size 的内存空间,用来存放数据,不会被初始化。
常用函数
下面是头文件 string.h 中定义函数,掌握以下常用的函数:
void *memcpy(void *dest,const void *src,size_t n): 从 src 复制 n 个字符到 dest 。void *memset(void *str,int c,size_t n)复制字符 c (一个无符号字符)到参数 str 所指向的字符串的前 n 个字符 。char *strcat(char *dest,const char *src): 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。char *strncat(char *dest,const char *src,size_t n): 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾,直到 n 字符长度为止。char *strchr(const char *str,int c):在参数 str 所指向的字符串中搜索第一次出现字符 c (一个无符号字符)的位置。-
int strcmp(const char *str1,const char *str2): 把 str1 所指向的字符串 和 str2 所指向的字符串进行比较。 -
char strcpy(char *dest,const char *str): 把 src 所指向的字符串复制到 dest -
size_t strlen(const char *str): 计算字符串 str 的长度,直到空结束字符,但不包括空结束字符