基础
关键字
typeof
int a = 5;
typeof(int *) var = &a;
数据类型变量
char 1
unsigned char 1
signed char 1
int 4
unsigned int 4
short 2
unsigned short 2
long 4/8
unsigned long 4/8
long long 8
float 4
double 8
long double 16
void fuction(void);
void *ptr = malloc(12);
85 /* 十进制 */
0213 /* 八进制 */
0x4b /* 十六进制 */
30 /* 整数 */
30u /* 无符号整数 */
30l /* 长整数 */
30ul /* 无符号长整数 */
//定义常量
#defined a 100
const int a = 100;
存储类
auto
register
static
extern
volatile
变量自动auto 函数自动auto
auto int a; == int a;
register int a; //每次取值从内存去 编译器不要优化
static int a; //静态变量 生命周期全局
static void fun(); //限制函数名称作用域再本文件别的文件不能引用 避免命名空间污染
extern int a; //变量a引用
extern void fun(); //引用别的文件的函数
volatile 防止编译器优化掉操作变量的语句
数组
//一维数组
int array[4] = {1, 2, 3, 4}
int array[] = {1, 2, 3, 4};
int a = array[0]
//二维数组
int array[3][4] = {
{0, 1, 2, 3} , /* 初始化索引号为 0 的行 */
{4, 5, 6, 7} , /* 初始化索引号为 1 的行 */
{8, 9, 10, 11} /* 初始化索引号为 2 的行 */
};
int val = array[2][3];
int people[30] = {[0 ... 29] = 1};
//数组传参
1.
void fun(int *array)
{
}
2.
void fun(int array[4])
{
}
3.
void fun(int array[])
{
}
常用1和3
//传递二维数组
int array[4][3] = {0};
void fun(int array[][3])
void fun(int (* p)[3]); //数组指针 指向数组
fun(array);
数组相同于指针
一维数组
int array[5];
*(array + 1) == *(&array[0] + sizeof(array)) //*(&array[0] + 5)
二维数组
int array[4][5];
*(array + 1) == *(&array[0] + sizeof(array)) //*(&array[0] + 20)
三维
int array[3][4][5];
*(array + 1) == *(&array[0] + sizeof(array)) //*(&array[0] + 60)
//指针+1内存增加指针指向数据类型长度
//函数返回数组
int * fun()
{
static int array[10];
return array;
}
//指向数组指针
int array[4] = {1, 2, 3, 4}
int *ptr = array;
int array[4][4]
int *ptr = array;
int (*p)[4] = array;
枚举
enum DAY {
MON = 1,
TUE
};
enum season {spring, summer=3, autumn, winter};
没有指定值的枚举元素,其值为前一元素加 1。也就说 spring 的值为 0,summer 的值为 3,autumn 的值为 4,winter 的值为 5
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
指针
int *p; //一级指针
int **p; //二级指针
int (*p)[4]; //数组指针 就是 指针指向数组 数组存储大小是4个单元
int *p[4]; //指针数组 4个指向int的指针 int a = 10; p[0] = &a;
int (*p)(int, int); //函数指针 指向函数
int fun(int a, int b);
p = fun;
p(1, 2);//执行
typedef int (*fun_ptr)(int, int);
fun_ptr p = fun; //别名定义
字符串
数组最后一个字节存储 '\0'
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
char str[] = "hello" //自动添加 '\0'
结构体
//定义
1.
struct Books {
char title[10];
char author[10];
} book;
2.
struct Books book;
3.
typedef struct {
char title[10];
char author[10];
} Books;
Books book;
//初始化
Books book = {"c", "my"};
Books book = {.title = "c", .author = "my"}; //C风格
Books book = {title : "c", author : "my"}; //C++风格
结构体大小
1,每个结构体成员的起始地址为该成员大小的整数倍,即int型成员的其实地址只能为0、4、8等
2,结构体的大小为其中最大成员大小的整数倍
共用体
共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。您可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式
union Data
{
int i;
float f;
char str[20];
};
int main( )
{
union Data data;
printf( "Memory size occupied by data : %d\n", sizeof(data));
return 0;
}
//20
//大小为最大成员大小
big-endian和little-endian格式。在小端模式中,低位字节放在低地址,高位字节放在高地址;在大端模式中,低位字节放在高地址,高位字节放在低地址。
//大小端测试
#include<stdio.h>
union var{
char c;
int i;
};
int main(){
union var data;
data.c = 0x04;
printf("%x\n",data.i);
if(data.i == 0x04) {
printf("小端");
} else {
printf("大端");
}
}
REVERSED
#if defined(REVERSED)
std::cout<< ("大端");
#else
std::cout<<("小端");
#endif
变参数函数
double average(int num,...)
{
va_list valist;
double sum = 0.0;
int i;
/* 为 num 个参数初始化 valist */
va_start(valist, num);
/* 访问所有赋给 valist 的参数 */
for (i = 0; i < num; i++)
{
sum += va_arg(valist, int);
}
/* 清理为 valist 保留的内存 */
va_end(valist);
return sum/num;
}
int main()
{
printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
}
预处理器
字符串常量化运算符(#)和标记粘贴运算符(##)
#define Conn(x, y) x##y //连接字符
#define ToString(x) #x //转化为字符串
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
int main(void)
{
message_for(Carole, Debra);
return 0;
}
参数宏 #define square(x) ((x) * (x))
#define eprintf(format, ...) fprintf(stderr, format, ##__VA_ARGS__)
#ifdef DEF == #if define(DEF)
#else
#endif
#ifndef DEF
#endif
指令 描述
#define 定义宏
#include 包含一个源代码文件
#undef 取消已定义的宏
#ifdef 如果宏已经定义,则返回真
#ifndef 如果宏没有定义,则返回真
#if 如果给定条件为真,则编译下面代码
#else #if 的替代方案
#elif 如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码
#endif 结束一个 #if……#else 条件编译块
#error 当遇到标准错误时,输出错误消息
#pragma 使用标准化方法,向编译器发布特殊的命令到编译器中
内存管理
void *calloc(int num, int size); //分配并初始化为 size
void free(void * address); //释放内存
void *malloc(int num) //分配内存
void *realloc(void *address, int newsize); //扩展大小
位域
struct bs
{
unsigned a:4;
unsigned :0;
unsigned b:4;
unsigned c:4;
}
0填充对其
整个结构体的总大小为最宽基本类型成员大小的整数倍
位域变量类型:int unsigned int signed int
字节对齐方式
#pragma pack(1)//单字节对齐
typedef struct{
uint32 ID;
uint32 Num;
uint32 Type;
uint32 lat;
uint32 lng;
uint32 alt;
uint32 speed;
}Waypoint;//Payload_Data
#pragma pack(pop)
大小端
//方法1
int a = 1;
if(*(char *)(&a) == 1) {
//小端
} else {
//大端
}
//方法2
union Endian
{
int a;
char b;
}
Endian endian;
endian.a = 1;
if(endian.b == 1) {
//小端
} else {
//大段
}
extern C
#ifdef __cplusplus //告诉编译器,这部分代码按C语言的格式进行编译,而不是C++的
extern "C"{
#endif
/*…*/
#ifdef __cplusplus
}
#endif
库函数
stdio.h
int printf(const char *format, ...)
%d 有符号10进制 正数不带符号位
%o 无符号8进制
%x,X 无符号16进制
%u 无符号十进制
%f 浮点数
%e,E 指数形式浮点数
%c 单个字符
%s 字符串
%p 指针
%lu 32位无符号
%llu 64位无符号
%+d 显示+/-
%-d 左对齐
%02X 填充 0 宽度2 默认填充空格
%-05X 左对齐
%#x 显示0x
%#f 显示一个小数
%*s, len, str 参数指定长度
%.2f 两位小数
%lf 双精度浮点数
%hd 短整型 short
类似:
int fprintf(FILE *stream, const char *format, ...) //则返回写入的字符总数
int sprintf(char *str, const char *format, ...)
int scanf(const char *format, ...)
int sscanf(const char *str, const char *format, ...)
math.h
double exp(double x) e的x次幂
double ceil(double x) 大于等于x最小整数
double fabs(double x) x绝对值
double floor(double x) 小于等于x最大整数
signal.h
void sighandler(int);
signal(SIGINT, sighandler); //注册信号
ret = raise(SIGINT); //发射信号
stdlib.h
double atof(const char *str)
int atoi(const char *str)
long int atol(const char *str)
double strtod(const char *str, char **endptr)
str -- 要转换为双精度浮点数的字符串。
endptr -- 对类型为 char* 的对象的引用,其值由函数设置为 str 中数值后的下一个字符。
long int strtol(const char *str, char **endptr, int base)
unsigned long int strtoul(const char *str, char **endptr, int base)
int system(const char *string)
//二分查找
void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *))
//排序
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
int abs(int x)
int rand(void) 0 - RAND_MAX 之间随机数
string.h
int memcmp(const void *str1, const void *str2, size_t n)
void *memcpy(void *dest, const void *src, size_t n)
void *memset(void *str, int c, size_t n)
char *strcat(char *dest, const char *src)
int strcmp(const char *str1, const char *str2)
char *strcpy(char *dest, const char *src)
size_t strlen(const char *str)
char *strrchr(const char *str, int c)
在参数 str 所指向的字符串中搜索最后一次出现字符 c(一个无符号字符)的位置。
char *strstr(const char *haystack, const char *needle)
time.h
time_t time(time_t *timer)
计算当前日历时间,并把它编码成 time_t 格式。
char *ctime(const time_t *timer)
返回一个表示当地时间的字符串,当地时间是基于参数 timer。
struct tm *localtime(const time_t *timer)
timer 的值被分解为 tm 结构,并用本地时区表示。
size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr)
根据 format 中定义的格式化规则,格式化结构 timeptr 表示的时间,并把它存储在 str 中。
time_t rawtime;
struct tm *info;
char buffer[80];
time( &rawtime );
info = localtime( &rawtime );
strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", info);
printf("格式化的日期 & 时间 : |%s|\n", buffer );
数据结构和算法
数据结构
算法
冒泡排序
void bubble_sort(int array[], int len)
{
len = len - 1; //len - 1次排序就够了
for(int i = 0; i < len; i++) {
for(int j = 0; j < len - i; j++) { //最大的值冒泡到最后
if(array[j] > array[j + 1]) {
array[i] = array[i] ^ array[j];
array[j] = array[i] ^ array[j];
array[i] = array[i] ^ array[j];
}
}
}
}
static void bubble_sort(int arr[], int len)
{
while(len-- > 0) {
for(int j = 0; j < len; j++) {
if(arr[j] > arr[j + 1]) {
arr[j] = arr[j] ^ arr[j + 1];
arr[j + 1] = arr[j] ^ arr[j + 1];
arr[j] = arr[j] ^ arr[j + 1];
}
}
}
}
int main()
{
int array[] = {22, 45, 56, 12, 35, 45, 7, 90};
int len = sizeof(array) / sizeof(int);
bubble_sort(array, len);
for(int i = 0; i < len; i++) {
printf("%d ", array[i]);
}
return 0;
}
选择排序
static void selectSort(register int arr[], int len)
{
for(int i = 0; i < len - 1; i++) {
for(int j = i; j < len; j++) { //找出最小值
if(arr[j] < arr[i]) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
}
}
int main() {
int arrTest[] = {3, 1, 4, 2, 7, 1, 3, 5, 3, 2, 7, 3};
selectSort(arrTest, sizeof(arrTest) / 4);
for(int i = 0; i < sizeof(arrTest) / 4; i++) {
printf("%d ", arrTest[i]);
}
return 0;
}
插入排序
static void insertSort(int arr[], int len)
{
for(int i = 1; i < len; i++) {
int temp = arr[i], j = i;
//查找比 arr[i] 小的 跳出循环 或者没有找到说明最小 插入到最前面
for(j = i; j > 0 && arr[j - 1] > temp; j--) {
arr[j] = arr[j - 1];
}
arr[j] = temp;
}
}
int main() {
int arrTest[] = {3, 1, 4, 2, 7, 1, 3, 5, 3, 2, 7, 3};
insertSort(arrTest, sizeof(arrTest) / 4);
for(int i = 0; i < sizeof(arrTest) / 4; i++) {
printf("%d ", arrTest[i]);
}
return 0;
}
归并排序
void merge_sort_recursive(int arr[], int reg[], int start, int end) {
if (start >= end)
return;
int len = end - start, mid = (len >> 1) + start;
int start1 = start, end1 = mid;
int start2 = mid + 1, end2 = end;
merge_sort_recursive(arr, reg, start1, end1);
merge_sort_recursive(arr, reg, start2, end2);
int k = start;
//从小到大复制两个 排序数组, 每个数组已经从小到大排序完成了
while (start1 <= end1 && start2 <= end2)
reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
while (start1 <= end1)
reg[k++] = arr[start1++];
while (start2 <= end2)
reg[k++] = arr[start2++];
//全部复制
for (k = start; k <= end; k++)
arr[k] = reg[k];
}
void mergeSort(int arr[], const int len) {
int reg[len];
merge_sort_recursive(arr, reg, 0, len - 1);
}
int main() {
int arrTest[] = {3, 1, 4, 2, 7, 8, 9, 2, 1, 23, 11, 3, 5, 3, 2, 7, 3};
mergeSort(arrTest, (sizeof(arrTest) / 4));
for(int i = 0; i < sizeof(arrTest) / 4; i++) {
printf("%d ", arrTest[i]);
}
return 0;
}
快速排序
//快速排序
void quick_sort_recursive(int arr[], int start, int end) {
if (start >= end)
return;
int mid = arr[start];
int left = start, right = end;
while (left < right) {
// 从右向左找第一个小于mid的数
while (arr[right] >= mid && left < right)
right--;
if(left < right) {
arr[left++] = arr[right];
}
// 从左向右找第一个大于等于mid的数
while (arr[left] < mid && left < right)
left++;
if(left < right) {
arr[right--] = arr[left];
}
}
arr[left] = mid;
quick_sort_recursive(arr, start, left - 1);
quick_sort_recursive(arr, left + 1, end);
}
void quick_sort(int arr[], int len) {
quick_sort_recursive(arr, 0, len - 1);
}
int main() {
int arrTest[] = {3, 1, 4, 2, 7, 8, 9, 2, 1, 23, 11, 3, 5, 3, 2, 7, 3};
quick_sort(arrTest, 0, (sizeof(arrTest) / 4) - 1);
for(int i = 0; i < sizeof(arrTest) / 4; i++) {
printf("%d ", arrTest[i]);
}
return 0;
}