C中的一点小东西

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”)

猜你喜欢

转载自blog.csdn.net/ppss177/article/details/130138277