C笔记
1.goto label; goto和label只能在同一个函数中!
2.打印log:
#define log_printf(s,...) printf("RVC: %s():%d: " s, __func__, __LINE__, ##__VA_ARGS__)
3.setjmp和longjmp
非局部跳转语句:setjmp和longjmp函数。非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳
过若干调用帧,返回到当前函数调用路径上的某一个函数中。
Int setjmp(jmp_buf env); //返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值
Void longjmp(jmp_buf env,int val);
在希望返回到的位置调用setjmp,此位置在main函数中,因为直接调用该函数,所以其返回值为0. setjmp参数evn的类型是一个特殊
的类型jmp_buf.在使用longjmp跳转到setjmp中时,程序主动地退出了!相当于抛出一个异常退出!其实这两个函数可以模拟C++中的异常函数:
setjmp与longjmp结合使用时,它们必须有严格的先后执行顺序,也即先调用setjmp函数,之后再调用longjmp函数,以恢复到先
前被保存的“程序执行点”。否则,如果在setjmp调用之前,执行longjmp函数,将导致程序的执行流变的不可预测,很容易导致程序
崩溃而退出.
4.container_of的第三个参数必须是具有实体的!
//struct max9288_priv *priv = container_of(client, struct max9288_priv, client); /*error: struct max9288_priv应该有client实体才行,而不是指针!!!*/
struct max9288_priv *priv = container_of(sd, struct max9288_priv, subdev);
若第三个参数是指针怎么使用呢,下面写两个其变体
(1) 取消其类型检查,然后取number的地址后使用强制类型转换
(2) 改动一下类型转换那里检查的类型
例子:
#include <stdio.h> #define offsetof(TYPE, MEMBER) ((unsigned long ) &((TYPE *)0)->MEMBER) #if 0 //original #define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) * __mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); }) #endif //去掉类型检查 #define container_of(ptr, type, member) ({ (type *)((char *)ptr - offsetof(type, member)); }) //更改类型 #define container_of_ptr(ptr, type, member) ({ \ const typeof(((type *)0)->member) __mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); }) struct stu { char *name; int id; int class; int *parents; int grade; }; int g_parents = 1122; void main() { struct stu stu1; stu1.name = "XueBaochai"; stu1.id = 10; stu1.class = 9; stu1.parents = &g_parents; stu1.grade = 149; int *par = (int *)&stu1.parents; struct stu *pstu1 = container_of_ptr(par, struct stu, parents); struct stu *pstu2 = container_of(par, struct stu, parents); printf("pstu1->name = %s\n", pstu1->name); printf("pstu2->name = %s\n", pstu2->name); } /* # gcc container_of_test.c -o pp # ./pp pstu1->name = XueBaochai pstu2->name = XueBaochai */
5.printf("=======2========%s\n"); 会Segmentation fault (core dumped), 因为%s没有指定地址。可变参数函数对参数检查不严格,所以编译不会报错但运行有错!
6.glib---字符串处理函数
https://blog.csdn.net/hpu11/article/details/62063353
7.可变参数函数解析
#include "stdio.h" #include "stdarg.h" void gst_caps_new_full_valist (int arg, va_list var_args) { while (arg) { printf("arg=%d\n", arg); arg = va_arg(var_args, int); /*meet first non-int exit!!!*/ } } int gst_caps_new_full(int arg1, ...) { va_list var_args; va_start (var_args, arg1); gst_caps_new_full_valist(arg1, var_args); va_end (var_args); } int main() { gst_caps_new_full(1,2,3,4,5,6,7,1.25,8,9,0); } 运行结果: [root@hello c_test]# ./pp arg=1 arg=2 arg=3 arg=4 arg=5 arg=6 arg=7
4.#define to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver) 还可以是变量的子成员
5.头文件直接展开做为数组元素
static struct us_unusual_dev us_unusual_dev_list[] = { include "unusual_devs.h" { } /* Terminating entry */ };
6. 编译运行宏
__LINE__ 在源代码中插入当前源代码行号
__FILE__ 在源代码中插入当前源代码文件名
__DATE__ 在源代码中插入当前编译日期〔注意和当前系统日期区别开来〕
__TIME__ 在源代码中插入当前编译时间〔注意和当前系统时间区别开来〕
__STDC__ 当要求程序严格遵循ANSIC标准时该标识符被赋值为1。
7. 怎样判断一个字符是数字、字母或其它类别的符号
在头文件ctype.h中定义了一批函数,它们可用来判断一个字符属于哪一类别。下面列出了这些函数:
--------------------------------------------------------------------------------------- 函数 字符类别 返回非零值的字符 --------------------------------------------------------------------------------------- isdigit() 十进制数 0--9 isxdigit() 十六进制数 0--9,a—f,或A--F isalnum() 字母数字符号 0--9,a--Z,或A--Z isalpha() 字母 a—z或A--Z islower() 小写字母 a—z isupper() 大写字母 A--Z isspace() 空白符 空格符,水平制表符,垂直制表符,换行符,换页符,或回车符 isgraph() 非空白字符 任何打印出来不是空白的字符(ASCII码从21到7E) isprint() 可打印字符 所有非空白字符,加上空格符 ispunct() 标点符 除字母数字符号以外的所有非空白字符 iscntrl() 控制字符 除可打印字符外的所有字符(ASCII码从00到1F,加上7F) isascii(测试字符是否为ASCII 码字符) toascii(将整型数转换成合法的ASCII 码字符) tolower(将大写字母转换成小写字母) toupper(将小写字母转换成大写字母) isalnum(检查参数c是否为英文字母或阿拉伯数字)
注:内核中也有这些函数
8.结构体中的匿名成员可以直接访问
#include <stdio.h> struct audit_field { int type; union { int gid; struct { char lsm_str; struct { int inner; }; }; }; int op; }; struct audit_data { int type; union { int gid; struct { char lsm_str; struct { int inner; }is; }os; }u; int op; }; void main() { struct audit_field audit; audit.inner = 2; struct audit_data data; data.u.os.is.inner = 3; printf("audit.inner=%d\n", audit.inner); printf("data.u.os.is.inner=%d\n", data.u.os.is.inner); }
9.使用getenv()函数获取指定的系统环境变量,这些环境变量是可以使用env工具查看到的,也是可以通过echo $XX打印出来的。
#include <stdlib.h> #include <stdio.h> void main() { const char *name = "PATH"; char *value = getenv(name); printf("%s=%s\n", name, value); }
10.获取程序用户ID
uid_t是定义在头文件sys/types.h中,getuid()函数返回一个调用程序的真实用户ID,一般来说,这个函数都是会调用成功的。当使用root身份执行范例程序时uid is 0.
#include<stdio.h> #include<stdlib.h> #include <sys/types.h> #include <pwd.h> #include <stdio.h> #include <unistd.h> void main() { printf("UID is: %d\n", getuid()); printf("EUID is: %d\n", geteuid()); }
参考:http://blog.csdn.net/wykwdy007/article/details/6535322 有例子。
uid_t是定义在头文件sys/types.h中,getuid()函数返回一个调用程序的真实用户ID,一般来说,这个函数都是会调用成功的。当使用root身份执行范例程序时uid is 0.
#include<stdio.h>#include<stdlib.h>#include <sys/types.h>#include <pwd.h>#include <stdio.h>#include <unistd.h>
void main(){printf("UID is: %d\n", getuid());printf("EUID is: %d\n", geteuid());}
posted on 2017-11-10 22:53 Hello-World3 阅读(234) 评论(0) 编辑 收藏 举报