Tips
- C语言区分大小写
- C编译器忽略空格
- 所有的 C 语言程序都需要包含 main() 函数,代码从 main() 函数开始执行。
C11
C11(也被称为C1X)指ISO标准ISO/IEC 9899:2011,是当前最新的C语言标准。
在它之前的C语言标准为C99。
C环境
- 文本编辑器 (例:vi/vim)
输入程序,编辑器创建的文件——源文件。
C程序源文件扩展名 “.c” - C编译器 (例:GNU的C/C++编译器)
源代码编译成最终的可执行程序。
工作流程:源程序(source code)→预处理器(preprocessor)→编译器(compiler)→汇编程序(assembler)→目标程序(object code)→连接器(链接器,Linker)→可执行程序(executables)
C程序包含内容
- 预处理器指令
- 函数
- 变量
- 语句 & 表达式
- 注释
预处理
include
#include "my.h"
stdio.h表示系统文件库, 也可以声明其它的。
.h表示头文件,因为这些文件都是放在程序各文件的开头。
#include 告诉预处理器将指定头文件的内容插入到预处理器命令的相应位,导入头文件的预编译指令。
<> 表示系统自带的库,也可以写成" " 表示用户自定义的库。
<>直接到系统指定的目录下查找该文件;
" "先在当前目录查找有无该头文件,有则包含该目录下的头文件,没有则到系统指定的目录下找该头文件。
防止重复include:
- #pragma once
某些老的编译器不支持 - #ifndef XXX
#define XXX
#endif
出现宏名重复,即字符串中有与宏名相同的字符串
#undef FILE_SIZE
#define FILE_SIZE 42 //取消原定义,重新定义。
#ifndef MESSAGE
#define MESSAGE "You wish!"
#endif //没有定义MESSAGE,则进行定义
预定义宏
- __DATE__ : 日期
- __TIME__ : 时间
- __FILE__ : 当前文件名
- __LINE__: 代码当前行号
- __STDC__:当编译器以 ANSI 标准编译时,则定义为 1。
注释方式
- //单行注释
- /* 单行注释 */
- /*
多行注释
多行注释
多行注释
*/
数据类型
- 基本类型:整数类型、浮点类型
- 枚举类型
- void类型
表明没有可用的值、无类型
void表示函数没有返回值,
而用int或其他,则函数需要有返回值如:
int egg()
{
return 0;
}
- 派生类型:指针类型、数组类型、结构类型、共用体类型、函数类型
整数类型
类型 | 大小 | 值范围 |
---|---|---|
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 |
signed表示有符号的,即+/-;
unsigned表示无符号。
具体字节大小查询:
printf("int 存储大小 : %lu \n", sizeof(int));
浮点类型
类型 | 存储大小 | 值范围 | 精度 |
---|---|---|---|
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 位小数 |
枚举
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
}; //分别 = 1 2 3 4 5 6 7
enum DAY
{
MON, TUE=3, WED, THU, FRI, SAT, SUN
}; //分别 = 0 3 4 5 6 7 8
枚举变量定义
enum DAY
{
MON, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;
enum DAY
{
MON, TUE, WED, THU, FRI, SAT, SUN
} day;
enum
{
MON, TUE, WED, THU, FRI, SAT, SUN
} day;
常量
定义常量
#define THIS 10;
const int ABCDE = 10;
存储类
auto
只能用在函数内,即 auto 只能修饰局部变量。register
static
extern
运算符
位运算符(二进制)
- & 与
- | 或
- ^ 异或
相同为0,不同为1 - ~ 取反
- << 二进制左移
假设A=60,A<<2得到240
60二进制:0011,1100
左移2位后的二进制:1111,0000(即十进制240) - >> 二进制右移
A=60,A>>2得到15
60:0011,1100
右移2位后的二进制:0000,1111(即十进制15)
循环
循环控制语句
- break:终止循环或switch语句。
- continue:立即停止本次循环,开始下一次循环。
- goto:转移到被标记的语句。
作用域
- 局部变量
函数内部使用 - 全局变量
整个程序的生命周期
- 如果全局变量和局部变量名字相同, 优先使用局部变量。
- 全局变量自动初始化。
数组
初始化数组
int a[5] = {5, 2,4, 7, 50}; //一维数组
int a[3][4] = {
{0, 1, 2, 3} , /* 初始化0行 */
{4, 5, 6, 7} , /* 初始化1行 */
{8, 9, 10, 11} /* 初始化2行 */
};
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
多维数组
int x[3][4] //二维数组
指针
输出变量地址:
printf("a变量的地址: %p\n", &a );
指针是变量,值为另一个变量的内存地址,即十六进制数。
整数型、浮点型等指针,指针类型都一样,而指向的数据类型不同。
int main ()
{
int a = 20;
int *ip;
ip = &a; //指针指向数组为:int b[5]; ip = b;
printf("变量地址: %p\n", &a ); //bffd8b3c
printf("指针存储地址: %p\n", ip ); //bffd8b3c
printf("指针访问值: %d\n", *ip ); // 20
return 0;
}
空指针:
int *ip = NULL; //此时地址是0x0
指针的指针:
int a;
int *ptr;
int **pptr;
a = 8;
ptr = &var;
pptr = &ptr;
字符串
char a[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
char a[] = "hello";
结构体
typedef struct abcd
{
}__attribute__((packed)) abcd;
__attribute__((packed))的作用:取消字节对齐,减少占用空间,让内存紧凑存储。
共用体
union Data
{
int i;
float f;
char str[20];
} data;
共用体成员访问运算符(.)
位域
位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。
typedef
typedef struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} Book;
输入输出
输入
scanf() 函数用于从标准输入(键盘)读取并格式化;
scanf("%s %d", str, &i); //char前无&,int前有&
getchar()
gets()
输出
printf() 函数发送格式化输出到标准输出(屏幕)。
- %d 格式化输出整数
- %f 格式化输出浮点型数据
- %s 字符串
- %c 字符
putchar()
puts()
文件读写
打开并写入文件
#include
int main()
{
FILE *fp = NULL;
fp = fopen("/tmp/test.txt", "w+");
fprintf(fp, "This is testing for fprintf...\n");
fputs("This is testing for fputs...\n", fp);
fclose(fp);
}
访问模式 | 备注 |
---|---|
r | 打开一个已有的文本文件,允许读取文件。 |
w | 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为零长度,重新写入。 |
a | 打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。 |
r+ | 打开一个文本文件,允许读写文件。 |
w+ | 打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。 |
a+ | 打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。 |
强制类型转换
int sum = 17, count = 5;
double mean;
mean = (double) sum / count;
可变参数
即函数输入数量不固定
利用stdarg.h 中的va_list、va_start、va_arg、va_end
内存管理
内存分配管理函数:在
void *calloc(int num, int size);
在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0。它的结果是分配了 num*size 个字节长度的内存空间,并且每个字节的值都是0。void free(void *address);
该函数释放 address 所指向的内存块,释放的是动态分配的内存空间。void *malloc(int num);
在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。void *realloc(void *address, int newsize);
该函数重新分配内存,把内存扩展到 newsize。
内存分配示例:
description = (char *)malloc( 200 * sizeof(char) );
calloc(200, sizeof(char));
description = (char *) realloc( description, 100 * sizeof(char) ); // 重新分配内存
free(description); // 释放内存
命令行参数
48页