define
define的基础用法: 将标识符定义为后面的常量
#define 标识符 常量 //最后没有分号
- C语言中以#开头的均为预处理命令,且以#开头的都是宏定义,用宏名表示一个常量,好处是"方便程序的修改"
#define NUM 5
位运算符
<< 二进制左移运算符,将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。如60(00111100) << 2 得到240
|或运算符
按二进制位进行或运算
- 输入输出规范
c语言中符合%#的意思是带格式输出
比如,%#x的意思是在输出前面加上0x,%#b的意思是在输出前面加上0b,c语言中的%#x意思是带格式0x的16进制输出。
进阶用法
- glob库函数的使用
如果glob返回的是非零值,则说明路径不存在
glob("path",0, NULL, &buf);// 从path获取配置文件并读取到buf中
#include <stdio.h>
#include <glob.h>
int main(int argc, const char *argv[])
{
glob_t buf;
int i;
i = glob("/Users/panlanlan/Documents/project/baidu/c/test_bvrouter/1",0, NULL, &buf);
printf("%d\n", i);
for(i=0; i < buf.gl_pathc; i++)
{
printf("buf.gl_pathv[%d]= %s \n", i, (buf.gl_pathv[i]));
}
globfree(&buf);
return 0;
}
- 获取当前路径
getcwd()函数的使用
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(void)
{
char *path = NULL;
path = getcwd(NULL,0);
puts(path);
free(path);
return 0;
}
- GCC diagnostic push的使用
test1函数就是被忽略的,main()函数只输出test2的结果
/************************************************************************/
//记录当前的诊断状态
#pragma GCC diagnostic push
//关闭警告,诊断忽略没有返回值
#pragma GCC diagnostic ignored "-Wreturn-type"
int test1(void)
{
return;
}
//恢复到之前的诊断状态
#pragma GCC diagnostic pop
/************************************************************************/
int test2(void)
{
return;
}
int main(int argc, char* argv[])
{
test1();
test2();
return 0;
}
- printf()和fprintf()的区别
fprintf是将字符输出到流(文件)的,printf是输出到标准设备(stdout)的。
int fprintf( FILE *stream, const char *format, [ argument ]...);
int printf( const char *format [, argument]... );
- strdup():复制字符串
参考 - chdir():改变当前的工作目录
参考 - container_of(ptr,type,member)的理解
container_of(ptr,type,member)指由结构体中元素member和member在结构体中的地址找到结构体的首地址
#define offset_of(type,member) ((int)&(((type *)0)->member))
#define container_of(ptr,type,member) ({ \
const typeof(((type*)0)->member) *__mptr = ptr; \
(type *)((char *)__mptr - offset_of(type,member)); \
})
struct mytest{
char i;
int j;
char *k;
};
int main(){
struct mytest temp;
struct mytest *p = &temp;
p->i = 100;
p->j = 10;
printf("&temp = %p\n",&temp);
printf("&temp.k = %p\n",&temp.k);
printf("&((struct mytest *)0)->k = %d\n",((int)&((struct mytest *)0)->k));
printf("&temp = %p \n",container_of(&temp.j,struct mytest,j));
printf("&temp = %p \n",container_of(&temp.k,struct mytest,k));
printf("======test=====\n");
printf("&temp = %p \n", &p->i);
printf("&temp = %p \n", &(p->i));
return 0;}
输出结果
&temp = 0x7ffee4018508 //结构体首地址
&temp.k = 0x7ffee4018510 // 结构体中元素k所在的地址,为了对齐字节,每个元素占4个字节
&((struct mytest *)0)->k = 8 //结构体中从首地址到k元素的长度
&temp = 0x7ffee4018508 //container_of(&temp.j,struct mytest,j)
&temp = 0x7ffee4018508 //container_of(&temp.k,struct mytest,k)
======test=====
&temp = 0x7ffee4018508
&temp = 0x7ffee4018508
还涉及一个运算符优先级的问题,顺手也做了小测试
&p->i
- &和->的优先级高低问题
通过上述测试,发现->优先级高于&
- 高阶用法
- 对于uint16_t,uint32_t,uint64_t的使用,在程序中加入typedef unsigned __int16 uint16_t;typedef unsigned __int32 uint32_t;typedef unsigned __int64 uint64_t;的输入输出形式:
https://blog.csdn.net/u010464679/article/details/45671705
malloc和free的使用
https://www.cxybb.com/article/weixin_43800761/107116376