计算数组的大小
sizeof(数组名)
获得这个数组占用内存的总长度。二维数组是全部元素占用的总长度。
长度 = sizeof(数组名) / sizeof(数组类型)
元素个数 = 总的占用字节大小 / 每个元素占用的字节大小
64位指针占用8字节,8×8=64,内存寻址。
计算一维数组长度
例子1:
1 | char *sc4[] ={"hello","world","Welcome","C"}; |
输出:
1 | arr total byte = 32 |
例子2:
1 | int n[8] = {1,2,3,4,5}; |
输出:
1 | arr total byte = 32 |
计算二维数组长度
例子1:
1 | char* arr2[2][3]; |
输出:
1 | total byte = 48 |
例子2:
定义一个结构体:
1 | typedef struct People_s { |
1 | People arr3[3][9]; |
输出:
1 | total byte = 432 |
valgrind 检查内存泄漏
valgrind --leak-check=full --track-origin=yes ./test
C的字符串数组
第一种情况,每一个都是指针
1 | char **arr = NULL; |
第二种情况,确定字符串的个数,但每个字符串长度不确定
1 | char *print2[10]; |
第三种情况,字符串的个数和字符串的长度已经确定
1 | char print[2][10] = {"Hello", "World"}; |
Makefile相关
C的false和true
在C中,只有0是false,大于0和小于0, 其余都为true
NULL的定义:
1 | #define NULL ((void *)0) |
true/false的定义:
1 | #define true 1 |
使用例子
1 | void checkcond(int32_t cond){ |
易混淆点:strcmp("Hello","Hello")
相等返回0,所以
常见写法
1 | // char *str |
取非之后才是比较相等的
C语言大小端工具转化
1 | // 大小端字节转换 |
C list
内核提供的list
简单的头文件
[linux_list.h]
需要一个哑结点作为整个链表的头部
1 |
|
申请一段连续的内存,这一段连续的内存可以使用list进行跳转
好处:只用申请一次内存,避免重复申请和释放
坏处:不可扩展,只能固定大小
注意
- 必须使用
list_for_each_safe
才能在循环里面删除。如果想要使用list_for_each
删除元素,需要找到之后再删除
1 | book_list_t *deleteItem = NULL; |
列表删除只是将索引关系删除,并不会对自定义数据做任何变更。只会处理
list
里面的next和prev。初始化列表的head,将前向指针和后向指针
定义一个万能指针类型ptr
typedef void *ptr;
1 | typedef void *ptr; |
输出:
1 | Hello World |
函数的注册与回调
函数的注册与回调,在多线程或某个函数中,完成相应的事件处理之后能够进行通知。
就像生命周期的钩子一样,开始,结束都会通知并可以处理。理解万能指针之后就会发现指针真是万能的,可以放参数、结构体、函数。
1 |
|
使用C语言实现一个环形缓冲区
RingBuffer.h
1 |
|
RingBuffer.h
1 |
|
use demo
1 |
|
C-Meessage-Queue使用Demo
1 |
|
信号与事件
linux系统下一共有64个信号,可以通过发送或者捕获特定的信号完成特定的动作,在ctl+c之后完成资源的释放等。
1 |
|
获得系统开机时间
1 |
|
c语言得UTC时间戳
1 | time_t utc_time; |
未定义的行为引发的问题:memcpy能不能用作移动数据的函数,不能。
比如想要将data数据往前移动2个字节memcpy(data, data+2, data_size -2)
这样会出现什么问题?有些编译器是支持的,但是有些编译器是将data的值清空之后再赋值。这个是未定义的行为。
关于函数引用问题
两个.c文件里面的函数里面可以相互引用吗?可以。
a.c
1 | int add(int x, int y ) { |
b.c
1 | int add(int x, int y); |
声明和定义的具体区别。
读写锁
为了并发读不受影响,使用读写锁进行共享变量的处理。
1 | int pthread_rwlock_init(pthread_rwlock_t *rwlock); |