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编辑  收藏  举报

导航