大佬说C语言最核心的就是指针与内存管理
回顾之后发现C这种比较接近音硬件的语言会更多让人理解编译器的操作以及很多硬件的本质
所以我准备抽时间好好看看cJson(一个小而精的Jsonj解析开源项目),复习C语言基础而且注重指针
https://zhuanlan.zhihu.com/p/267442434 知乎这一篇解析真的很仔细!
C指针
-
type *var-name;
-
所有实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,对应指针的值的类型都是一样的,都是一个代表内存地址的长的十六进制数。
-
使用指针时会频繁进行以下几个操作:定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值
-
ptr++
在执行完上述的运算之后,ptr 将指向位置 1004
(因为 ptr 每增加一次,它都将指向下一个整数位置,即当前位置往后移 4 字节)
如果 ptr 指向一个地址为 1000 的字符,上面的运算会导致指针指向位置 1001,因为下一个字符位置是在 1001。
-
const int MAX = 3;
-
typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型
-
int (* p)(int, int) = & max; // &可以省略
-
回调函数
函数指针作为某个函数的参数
-
#include <stdlib.h> #include <stdio.h> // 回调函数 void populate_array(int *array, size_t arraySize, int (*getNextValue)(void)) { for (size_t i=0; i<arraySize; i++) array[i] = getNextValue(); } // 获取随机值 int getNextRandomValue(void) { return rand(); } int main(void) { int myarray[10]; /* getNextRandomValue 不能加括号,否则无法编译,因为加上括号之后相当于传入此参数时传入了 int , 而不是函数指针*/ populate_array(myarray, 10, getNextRandomValue); for(int i = 0; i < 10; i++) { printf("%d ", myarray[i]); } printf("\n"); return 0; }
-
声明一个返回指针的函数,如下所示:
int * myFunction()
-
srand((unsigned)time(NULL)) 生成随机数
srand函数是随机数发生器的初始化函数。原型:void srand(unsigned seed);
它初始化随机种子,会提供一个种子,这个种子会对应一个随机数,如果使用相同的种子后面的rand()函数会出现一样的随机数
不过为了防止随机数每次重复,常常使用系统时间来初始化,即使用 time函数来获得系统时间,它的返回值为从 00:00:00 GMT, January 1, 1970 到现在所持续的秒数
然后将time_t型数据转化为(unsigned)型再传给srand函数
直接传入一个空指针,因为你的程序中往往并不需要经过参数获得的数据。 -
C typedef
C 语言提供了 typedef 关键字,您可以使用它来为类型取一个新的名字。下面的实例为单字节数字定义了一个术语 BYTE:
typedef unsigned char BYTE;
-
typedef vs #define
#define 是 C 指令,用于为各种数据类型定义别名,与 typedef 类似,但是它们有以下几点不同:
- typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。
- typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的
-
标准输入 stdin 键盘 标准输出 stdout 屏幕 -
在 printf() 函数的引号中使用 “%d” (整型) 来匹配整型变量 testInteger 并输出到屏幕。
-
了定义结构,您必须使用 struct 语句。struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下
struct tag { member-list member-list member-list ... } variable-list ;
tag、member-list、variable-list 这 3 部分至少要出现 2 个
c struct Books Book1; /* 声明 Book1,类型为 Books */
-
结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针,而通常这种指针的应用是为了实现一些更高级的数据结构如链表和树等。
-
volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等
-
__cdecl 是C Declaration的缩写(declaration,声明)
-
/ 3.用于快速创建内容的宏 // #define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) #define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) #define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) #define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) #define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) #define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name,
-
malloc的全称是memory allocation (also allocate() )
C 库函数 void *malloc(size_t size) 分配所需的内存空间,并返回一个指向它的指针。
void *malloc(size_t size)
- size – 内存块的大小,以字节为单位。
#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { char *str; /* 最初的内存分配 */ str = (char *) malloc(15); strcpy(str, "runoob"); printf("String = %s, Address = %u\n", str, str); /* 重新分配内存 */ str = (char *) realloc(str, 25); strcat(str, ".com"); printf("String = %s, Address = %u\n", str, str); free(str); return(0); }
-
straup()
功能:将字符串拷贝到新建的位置处
注意:strdup()在内部调用了malloc()为变量分配内存,不需要使用返回的字符串时,需要用free()释放相应的内存空间,否则会造成内存泄漏。#include <stdio.h> #include <string.h> //for strdup() #include <stdlib.h> //for free() int main(void) { char *dup_str, *string = "I am won"; dup_str = strdup(string); printf("%s\n", dup_str); free(dup_str); return 0; }
函数strdup() 与 函数strcpy() 的区别
strdup可以直接把要复制的内容复制给没有初始化的指针,因为它会自动分配空间给目的指针,需要手动free()进行内存回收。
strcpy的目的指针一定是已经分配(足够)内存的指针 -
assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:
#include <assert.h> void assert( int expression );
assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。请看下面的程序清单badptr.c:
-
数组和对象的深层嵌套:cJSON不支持嵌套太深的数组和对象,因为这会导致堆栈溢出。为了防止这种CJSON_NESTING_LIMIT情况,默认情况下,cJSON将深度限制为1000,但是可以在编译时进行更改。
-
从某个结点开始,即可以向前遍历,也可以向后遍历,这是双向链表的优势
-
JSON格式中其 Key永远是字符串,Value 可以是满足JSON规则的任务基本类型/复杂嵌套类型。
-
preallocated 预分配的;
-
c语言中(int*)是什么意思:
- int*代表的是int型的bai指针 强制类型转换指针
-
memset是计算机中C/C++语言初始化函数。作用是将某一块内存中的内容全部设置为指定的值