C语言 复习指南
数据类型
在C语言中,数据类型是用来声明不同类型的变量或函数的一套系统。变量的类型决定了变量存储占用的空间以及如何解释存储的位模式。
类型名称 | 类型解释 |
---|---|
基本类型 | 即算术类型,包括两种类型:整数类型和浮点类型 |
枚举类型 | 也是算术类型,被用来定义在程序中只能赋予其一定的离散整数值的变量 |
void类型 | 类型说明符,表示没有可用的值 |
派生类型 | 包括指针类型、数组类型、结构类型、共用体类型和函数类型 |
图解C语言类型如下:
1.整数类型(64bit System)
类型 | 存储大小 | 值范围 |
---|---|---|
char | 1字节 | 与 signed char 或 unsigned char 相同 |
short | 2字节 | -2^15 到 2^15-1 |
int | 4字节 | -2^31 到 2^31-1 |
long | 4字节 | -2^31 到 2^31-1 |
unsigned char | 1字节 | 0 到 2^8-1 |
unsigned short | 2字节 | 0 到 2^16-1 |
unsigned int | 4字节 | 0 到 2^32-1 |
unsigned long | 4字节 | 0 到 2^32-1 |
signed char | 1字节 | -128 到 127 |
2.浮点类型
类型 | 存储大小 | 值范围 | 精度 |
---|---|---|---|
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位小数 |
3.结构类型
C数组允许定义可存储相同类型数据项的变量,结构是C中可以由用户自定义的可用数据类型,允许用户存储不同类型的数据项。
定义结构体
struct s_tag{
int id;
char name[20];
} member;
s_tag是结构体标签
int id;、char name[20]是标准的变量定义
member是结构体变量,可以利用一个结构定义多个结构体变量。
一般情况下,结构体标签、标准变量定义、结构体变量这三部分最少要出现两个。
结构体的使用
//这个结构体并没有标明其标签,但是声明了结构体变量s1
struct
{
int a;
char b;
double c;
} s1;
//结构体的标签被命名为SIMPLE,没有声明结构体变量
struct SIMPLE
{
int a;
char b;
double c;
};
//用SIMPLE标签的结构体,另外声明了结构体变量t1、t2、t3
struct SIMPLE t1, t2[20], *t3;
//也可以用typedef创建新类型
typedef struct
{
int a;
char b;
double c;
} Simple2;
//现在可以用Simple2作为新类型声明新的结构体变量
Simple2 u1, u2[20], *u3;
注意体会上述代码中的typedef声明新类型Simple2与SIMPLE标签的区别,可以把Simple2理解为类似int、double这种级别的类型。
需要掌握的是如何利用结构体标签或者新结构体变量类型来声明结构体变量
结构体的成员可以包含其他的结构体,也可以包含指向自己结构体类型的指针,通常这种指针的应用是为了实现一些更高级的数据结构如链表和树
//此结构体的声明包含了其他的结构体
struct COMPLEX
{
char string[100];
struct SIMPLE a;//这里利用结构体标签声明了新的结构体变量
};
//此结构体的声明包含了指向自己类型的指针
struct NODE
{
char string[100];
struct NODE *next_node;//利用结构体标签声明新的结构体变量指针
};
当两个结构体相互包含的时候,需要先对其中一个结构体进行不完整声明。
struct B; //对结构体B进行不完整声明
//结构体A中包含指向结构体B的指针
struct A
{
struct B *partner;
//other members;
};
//结构体B中包含指向结构体A的指针,在A声明完后,B也随之进行声明
struct B
{
struct A *partner;
//other members;
};
上述不完整声明很好理解,若没有对B的不完整声明,那么在结构体A中声明指向结构体B指针的时候将会出错,因为根本没有B这个结构体。
结构体变量的初始化: 和其他的变量一样,对结构体变量初始化可以在定义的时候指定初始值。
结构作为函数参数:与其他的参数没什么不同,函数参数表中一般都是使用“参数类型 参数名”对参数进行声明的,那么结构体作为函数参数实际上就是在参数表中声明一个结构体的事情。示例如下:
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
void printBook( struct Books book )
{
printf( "Book title : %s\n", book.title);
printf( "Book author : %s\n", book.author);
printf( "Book subject : %s\n", book.subject);
printf( "Book book_id : %d\n", book.book_id);
}
指向结构的指针:与普通的指针变量声明没什么不同,记得正确使用结构体标签和结构体类型声明即可,示例如下:
struct Books *struct_pointer;
struct_pointer = &Book1;
struct_pointer->title;//结构体指针访问结构成员的方式“->”
位域
有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有 0 和 1 两种状态,用 1 位二进位即可。为了节省存储空间,并使处理简便,C 语言又提供了一种数据结构,称为"位域"或"位段"。
所谓"位域"是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。
典型的实例:
- 用 1 位二进位存放一个开关量时,只有 0 和 1 两种状态。
- 读取外部文件格式——可以读取非标准的文件格式。例如:9 位的整数。
4.共用体
共用体是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型,因此共用体变量所占的内存长度等于最长成员的长度。
- 只有定义了共用体变量才能够引用它,但是应当注意,不能引用共用体变量,只能引用共用体变量的成员。
- 共用体变量的同一内存段可以用来存放几种不同类型的成员,但是在一瞬间只能存放其中的一个成员,而不是同时存放几个。
- 可以对共用体变量初始化,但是初始化表中只能有一个常量。
- 共用体变量中起作用的是最后一次被赋值的成员。
- 共用体变量的地址和它的成员地址都是同一地址。
- 不能对共用体变量名赋值,也不能企图引用变量名来得到值。
定义共用体
union Data
{
int i;
float f;
char str[20];
} data;
Data是共用体标签(是可选的)
int i;、float f是标准变量的定义
data是共用体变量(可以指定多个共用体变量)
上述的Data类型的变量可以存储一个整数或者一个浮点数。
共用体的使用
#include <stdio.h>
#include <string.h>
union Data
{
int i;
float f;
char str[20];
};
int main( )
{
union Data data;
data.i = 10;
data.f = 220.5;
strcpy( data.str, "C Programming");
printf( "data.i : %d\n", data.i);
printf( "data.f : %f\n", data.f);
printf( "data.str : %s\n", data.str);
return 0;
}
上述代码被编译执行时,会产生如下结果
可以看到i与f的成员值有损坏,这是因为最后赋值给变量的值占用了内存未知,这也是最后str成员能够正常输出的原因。
下方的代码是使用共用体的主要目的
#include <stdio.h>
#include <string.h>
union Data
{
int i;
float f;
char str[20];
};
int main( )
{
union Data data;
data.i = 10;
printf( "data.i : %d\n", data.i);
data.f = 220.5;
printf( "data.f : %f\n", data.f);
strcpy( data.str, "C Programming");
printf( "data.str : %s\n", data.str);
return 0;
}
上述代码被编译执行时,产生如下结果:
data.i : 10
data.f : 220.500000
data.str : C Programming
5.指针类型
指针概念图
图中的Pointer是指针变量、var_runoob是int类型的变量,可以看到指针自身的值是指向var_runoob地址的。图中地址均用16进制进行表示
指针代码解释
#include<stdio.h>
int main(void){
int var_runoob=10;
int *pointer;
pointer=&var_runoob;
printf("var_runoob 变量的地址:%p\n",&var_runoob);
printf("var_runoob 变量的值:%d\n",var_runoob);
printf("pointer 指针指向的变量地址:%p\n",pointer);
printf("pointer 指针自身的地址:%p\n",&pointer);
printf("pointer 指针自身的值:%p\n",*&pointer);
printf("pointer 指针指向的变量的值:%d\n",*pointer);
printf("var_runoob 变量的地址(十进制):%d\n",&var_runoob);
return 0;
}
总结如下:
- 1.指针的声明方式为int *pointer,声明int类型的指针变量;
- 2.指针的定义方式为pointer=&var_runoob,将变量的地址赋值给指针;
- 3.输出p:这是指针自身的值,也是指针所指向变量的地址;
- 4.输出&p:这是指针自身的地址,与指向变量的地址没有任何关系;
- 5.输出p:这是指针所指向变量的int值;
与&两个符号的作用是相反的,给你一个变量的地址,那么在此地址前加即可得到这个变量的值;给你一个变量名,在此变量名前加上&即可得到这个变量的地址(上面的图片中提到了与&的作用)。
6.枚举类型
枚举是C中的一种基本数据类型,它可以让数据更简洁,更易读。
枚举的定义
enum DAY { Mon=1, Tue, Wed, Thu, Fri, Sat, Sun };
- DAY是枚举名
- Mon、Tue、Wed等是枚举元素
- 第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。
- 若把第一个枚举成员的值定义为1,那么第二个就为2,以此类推。
- 可以在定义枚举的时候改变枚举元素的值,如果改Wed为7,那么Wed后续的就为8、9等。
枚举的使用
上述已经声明了枚举类型,接下来定义枚举变量。
//先定义枚举类型,再定义枚举变量
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;
//定义枚举类型的同时定义枚举变量
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
//省略枚举名称,直接定义枚举变量
enum
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
枚举使用的示例:
#include <stdio.h>
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
int main()
{
enum DAY day;
day = WED;
printf("%d",day);
return 0;
}
输出结果为:3
C语言中的枚举类型是被当作int或者unsigned int来处理的,所以按照C语言的规范是没有办法遍历枚举类型。但是对于一些特殊的枚举类型是可以进行有条件的遍历的。
#include <stdio.h>
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
int main()
{
// 遍历枚举元素
for (day = MON; day <= SUN; day++) {
printf("枚举元素:%d \n", day);
}
}
但是对于一些非连续的枚举,便无法遍历
typedef关键字
C提供了typedef关键字,可以用它来为类型取一个新的名字
typedef unsigned char BYTE;
BYTE b1,b2;
typedef struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} Book;
Book book_one;
typedef和#define
#define是C指令,用于为各种数据类型定义别名,与typedef类似,但是它们也有以下几点不同:
- 1.typedef仅限于为类型定义符号名称,#define不仅可以为类型定义别名,也可以为数值定义别名,比如可以定义1为ONE。
- 2.typedef由编译器执行解释的,#define由与编译器进行处理
//#define最简单的用法
#define TRUE 1
#define FALSE 0
int main( )
{
printf( "TRUE 的值: %d\n", TRUE);
printf( "FALSE 的值: %d\n", FALSE);
return 0;
}
上述代码的执行结果如下
- TRUE 的值: 1
- FALSE 的值: 0
C字符串
字符串的声明与创建
char site[7] = {'R', 'U', 'N', 'O', 'O', 'B', '\0'};
char site[] = "RUNOOB";
C语言中的字符串操作函数
序号 | 函数 | 目的 |
---|---|---|
1 | strcpy(s1,s2) | 复制字符串s2到字符串s1 |
2 | strcat(s1,s2) | 连接字符串s2到字符串s1的末尾 |
3 | strlen(s1) | 返回字符串s1的长度 |
4 | strcmp(s1,s2) | 如果s1和s2是相同的,则返回0,如果s1<s2则返回小于0(-1),如果s1>s2则返回大于0(1) |
5 | strchr(s1,ch) | 返回一个指针,指向字符串s1中字符ch的第一次出现的位置 |
6 | strstr(s1,s2) | 返回一个指针,指向字符串s1中字符串s2的第一次出现位置 |