1.内存
代码区:编译后的程序指令,CPU可直接执行的机器码。字符串常量、字符常量、浮点数常量、枚举常量等。
数据区:全局变量、静态变量。
堆:动态申请的区域。
栈:函数参数、临时变量。
2.malloc free
int * p = NULL;
p = (int*) malloc(sizeof(int));//申请成功不为NULL,申请不成功为NULL。
free( p );
3.extern
extern只起申明作用,不定义,extern的变量或函数的定义在其他文件中。extern的函数或变量在头文件中被引用了,只会被编译一次。
.h中extern的变量或函数定义可以不在对应的.c文件中,但该对应的.c文件中也可以使用。
.h中声明的变量或函数定义需要在对应的.c文件中。
4.空类型指针
空类型指针可以转为其他类型的指针,其他类型的指针也可转为空类型的指针
int num = 10;
int *p = #
void *q = (void *) p;
int num = 10;
void *p = #
int *q = (int *) p;
5.空指针
int *p = NULL;
p = (int *) 5;//ok
int n = 5;
p = &n;//ok
通过地址赋值
typedef struct {
int x;
int y;
int z;
} vec_t;
vec_t *vec = NULL;
vec->x = 5;
vec->y = 6;
vec->z = 1;//error,vec是一个空指针,不能对一个空指针直接赋值;
6.一些整型
int8_t(8位有符号整型),
int16_t(16位有符号整型),
int32_t(32位有符号整型),
int64_t(64位有符号整型)
精度和范围不同,在不超出范围的情况下同一个数值在数值上是大小是相等的。
7.函数指针和指针函数
函数指针:void (*fun)(parm);//可作为函数参数实现回调功能
指针函数:void * fun(parm);//返回一个指针
回调:
s端:
typedef void (*fun_listener_t)(parm) ;
fun_listener_t s_listener = NULL;
void callback(fun_listener_t listener) {
s_listener = listener;
}
s_listener(parm);
c端:
fun_listener_t fun_listener(parm) {
//可根据parm做一些实际的事...
}
callback(fun_listener);
8.拼接字符串
sprintf 函数是将格式化的字符串拷贝到指定的字符数组中,如果待拼接的字符串长度超过了定义的字符数组长度,就会发生缓冲区溢出的问题,导致不可预测的结果,可能会破坏栈帧的完整性,甚至造成程序崩溃。当需要拼接的字符串长度超过了指定的字符数组长度时
snprintf 函数会自动截取字符串,并在字符串末尾添加一个空字符 ‘\0’
int snprintf(char *str, size_t size, const char *format, …);//第三个参数 format 是格式化字符串;后面的参数与格式化字符串中的格式说明符相对应。
int vsnprintf(char *str, size_t size, const char *format, va_list ap);//第三个参数 format 也是目标格式化字符串;第四个参数 ap 是一个 va_list 类型的可变参数列表,前面的参数与 format 字符串中的相应格式说明符对应
int num = 75253;
char str[64] = {
0};
sprintf(str, "this num is *%d", num);//this num is 75253;
for(int i=0; i<10; i++) {
sprintf(str + i, "%d", i);
}//str:0123456789
snprintf(str, 4, "%d", num);//752(占位符‘\0’);
9.define函数
level_error = 4;
#define LOG_ERROR(msg) log(level_error,msg)
void log(int levle, char* str) {
printf(str);
}
9.可变参数
#include <stdarg.h>
printf_string(int num, ...){
va_list str;//用于遍历可变参数的变量
va_start(str, num);//第一个参数传递va_list变量,第二个参数传递最后一个具体参数名称
for (int i = 0; i < num; i++) {
char* str = va_arg(ap, char*);//遍历参数列表,第一个参数传递va_list变量,第二个参数传递数据类型type
printf("%s\n", str);
}
va_end(str);//清理 va_list 以便程序可以从栈中正确地恢复可变参数之前的状态
}
printf_string(5,"hello","Bob","How","are","you");
宏定义:
#include <stdio.h>
#include <stdarg.h>
int log_print(const char *msg, ...) {
char buffer[256];
va_list args;
va_start(args, msg);
int len = snprintf(buffer, sizeof(buffer), format, args);
va_end(args);
printf("%s\n", buffer);
return len;
}
#define LOG(msg, args...) log_print(msg, ##args)//args...和##args为固定格式,变量名可变
int main() {
int value = 10;
char *str = "Hello";
LOG("Value: %d, String: %s", value, str);
return 0;
}
void log(const char *message, ...){
va_list ap;
va_start(ap, message);
char buf[128] = {
0}
vsnprintf(&buf, 128, message, ap);
va_end(ap);
}
#define FG_LOG(log_level, ...) \
do \
{
\
if (log_level >= s_curr_log_level) \
{
\
log(__VA_ARGS__); \
} \
} while (0)
#define LOG_INFO(...) FG_LOG(FG_LOG_LEVEL_INFO, __VA_ARGS__)
#define LOG_NOTIFY(...) FG_LOG(FG_LOG_LEVEL_NOTIFY, __VA_ARGS__)
#define LOG_WARN(...) FG_LOG(FG_LOG_LEVEL_WARN, __VA_ARGS__)
#define LOG_ERROR(...) FG_LOG(FG_LOG_LEVEL_ERROR, __VA_ARGS__)```
//调用
LOG_WARN("there is %d %s",5,“apples”);