int p; //这是一个普通的整型变量
int *p; //首先从P 处开始,先与*结合,所以说明P 是一个指针,然后再与int 结合,说明指针所指向的内容的类型为int 型.所以P是一个返回整型数据的指针
int p[3]; //首先从P 处开始,先与[]结合,说明P 是一个数组,然后与int 结合,说明数组里的元素是整型的,所以P 是一个由整型数据组成的数组 -------整型数组
int *p[3]; //首先从P 处开始,先与[]结合,因为其优先级比*高,所以P 是一个数组,然后再与*结合,说明数组里的元素是指针类型,然后再与int 结合,说明指针所指向的内容的类型是整型的,所以P 是一个由返回整型数据的指针所组成的数组 ---指针数组
int (*p)[3]; //首先从P 处开始,先与*结合,说明P 是一个指针然后再与[]结合(与"()"这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以P 是一个指向由整型数据组成的数组的指针----数组指针
int **p; //首先从P 开始,先与*结合,说是P 是一个指针,然后再与*结合,说明指针所指向的元素是指针,然后再与int 结合,说明该指针所指向的元素是整型数据.由于二级指针以及更高级的指针极少用在复杂的类型中,所以后面更复杂的类型我们就不考虑多级指针了,最多只考虑一级指针.
int p(int); //从P 处起,先与()结合,说明P 是一个函数,然后进入()里分析,说明该函数有一个整型变量的参数,然后再与外面的int 结合,说明函数的返回值是一个整型数据
Int (*p)(int); //从P 处开始,先与指针结合,说明P 是一个指针,然后与()结合,说明指针指向的是一个函数,然后再与()里的int 结合,说明函数有一个int 型的参数,再与最外层的int 结合,说明函数的返回类型是整型,所以P 是一个指向有一个整型参数且返回类型为整型的函数的指针 -------------p函数指针 本质是指针变量
而 int * p(int) 指針函数 p本质是一个函数。函数返回类型是某一类型的指针
int *(*p(int))[3]; //从P 开始,先与()结合,说明P 是一个函数,然后进入()里面,与int 结合,说明函数有一个整型变量参数,然后再与外面的*结合,说明函数返回的是一个指针,,然后到最外面一层,先与[]结合,说明返回的指针指向的是一个数组,然后再与*结合,说明数组里的元素是指针,然后再与int 结合,说明指针指向的内容是整型数据.所以P 是一个参数为一个整数据且返回一个指向由整型指针变量组成的数组的指针变量的函数
以上去掉p就是p 的类型
在来点复杂的
void (*(*f[])())()
分析如下
f[]数组,数组包含类型是指针,指针指向的内容是函数,返回类型是指针,指向函数名,函数返回类型是void
最后分析rild中使用 hardware/ril/rild/rild.c
const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
const RIL_RadioFunctions *funcs;
static struct RIL_Env s_rilEnv = {
RIL_onRequestComplete,
RIL_onUnsolicitedResponse,
RIL_requestTimedCallback,
RIL_onRequestAck
};
typedef struct {
int version; /* set to RIL_VERSION */
RIL_RequestFunc onRequest;
RIL_RadioStateRequest onStateRequest;
RIL_Supports supports;
RIL_Cancel onCancel;
RIL_GetVersion getVersion;
} RIL_RadioFunctions;
void *dlHandle = dlopen(rilLibPath, RTLD_NOW);
rilInit =(const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))
dlsym(dlHandle, "RIL_Init");
funcs = rilInit(&s_rilEnv, argc, rilArgv);
包含头文件: #include <dlfcn.h>
dlopen
功能:打开一个动态链接库
函数定义: void * dlopen( const char * pathname, int mode ); void *则为“无类型指针”,void *可以指向任何类型的数据
函数描述: 在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。
mode:分为这两种
RTLD_LAZY 暂缓决定,等有需要时再解出符号
RTLD_NOW 立即决定,返回前解除所有未决定的符号。
RTLD_LOCAL
RTLD_GLOBAL 允许导出符号
RTLD_GROUP
RTLD_WORLD
返回值:
打开错误返回NULL
成功,返回库引用
编译时候要加入 -ldl (指定dl库)
dlsym
功能:根据动态链接库操作句柄与符号,返回符号对应的地址。
函数定义:void*dlsym(void* handle,const char* symbol)
函数描述:dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。
handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数或全局变量的名称。
dlclose
dlclose()用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
rilInit 函数返回类型是指向结构体RIL_RadioFunctions,dlsym 返回类型转化为指向rilInit指针,"RIL_Init"代表的rilLibPath动态库的函数名称,所以返回RIL_Init 函数引用
hardware/ril/reference-ril/reference-ril.c
const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{
//......
while ( -1 != (opt = getopt(argc, argv, "p:d:s:c:"))) {
switch (opt) {
case 'p':break;
case 'd':break;
case 's':break;
case 'c':break;
default:return NULL;
}
}
//..........
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
return &s_callbacks;
}
getopt 获取命令行参数 -p -d -s -c 参数后面的值(间隔space)单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg
umask
#include <sys/stat.h>
umask函数为进程设置文件模式创建屏蔽字,并返回以前的值
umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
函数原型 mode_t umask(mode_t cmask);
cmask是由下表列出的9个常量中的若干个按位“或”构成的
S_IRUSR 用户读
S_IWUSR 用户写
S_IXUSR 用户执行
S_IRGRP 组读
S_IWGRP 组写
S_IXGRP 组执行
S_IROTH 其他读
S_IWOTH 其他写
S_IXOTH 其他执行
C类型转换
任意类型(整型、长整型、浮点型等)的数字转换为字符串
1. itoa():将整型值转换为字符串
2. ltoa():将长整型值转换为字符串
3. ultoa():将无符号长整型值转换为字符串
4. gcvt():将浮点型数转换为字符串,取四舍五入
5. ecvt():将双精度浮点型值转换为字符串,转换结果中不包含十进制小数点
6. fcvt():指定位数为转换精度,其余同ecvt()
字符串转换为任意类型(整型、长整型、浮点型等)。
1. atof():将字符串转换为双精度浮点型值 ascii
2. atoi():将字符串转换为整型值
3. atol():将字符串转换为长整型值
4. strtod():将字符串转换为双精度浮点型值,并报告不能被转换的所有剩余数字
5. strtol():将字符串转换为长整值,并报告不能被转换的所有剩余数字
6. strtoul():将字符串转换为无符号长整型值,并报告不能被转换的所有剩余数字
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
pthread_attr_init
如果设置线程属性,必须在pthread_create 之前使用pthread_attr_init.
pthread_attr_t 结构体包含 是否绑定,是否分离,堆栈地址,堆栈大小,优先级信息
默认属性是 非绑定 非分离 默认1M大小堆栈 优先级和进程一样
轻进程概念,理解为内核进程,位于用户层和系统层之间,系统对线程资源的分配通过轻进程实现,如果设置绑定在轻进程,那个线程响应度高。
设置绑定状态的函数 pthread_attr_setscope
绑定:PTHREAD_SCOPE_SYSTEM
非绑定 PTHREAD_SCOPE_PROCESS
线程的分离状态,用来决定如何结束自己
设置参数的函数 pthread_attr_setdetachstate
非分离状态使用pthread_join 处理,才能释放资源,分离状态的线程,运行结束,自动释放
非分离:PTHREAD_CREATE_JOINABLE
分离:PTHREAD_CREATE_DETACHED
如果设置线程分离状态,线程运行太快,在pthread_attr_init 之后,但是在pthread_create之前结束,那么此时创建线程,会得到错误线程号,需要避免,最简单的方法 执行pthread_cond_timewait 使得线程慢点跑,一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。
pthread_cond_wait和pthread_cond_broadcast
int pthread_cond_broadcast(pthread_cond_t *cond)
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
pthread_cond_t 函数将要等待的信号
pthread_mutex_t 一个互斥锁,用于对信号量进行保护,防止多个线程同时对其进行操作
pthread_cond_broadcast 就是广播 信号
不懂看实例 https://blog.csdn.net/wangzhiyu1980/article/details/44227913
typedef 使用
typedef 已存在类型 新类型名称
typedef int size;
typedef unsigned int WORD;
size i = -4;
WORD word = 4
typdef 数组和指针
char str[10]; //定义 长度为10的字符数组
typedef char str[10];
//使用
str str1; //str 字符数组首地址
typedef char * pstr;
pstr p ;//指针
typedef 和函数 (ril 中使用的)
typedef void (*work_function_t)(void* arg);
work_function_t func;//代表指向这个类型的函数指针
函数指针 参数是无类型指针(可以强制转化为任意类型的指针,任何类型的指针都可以直接赋值给它,无需进行强制类型转换)
typedef 和 define的区别:
define 处理在预编译
typedef 在执行过程中
define 只是进行简单的字符串替换
typedef 是类似 定义
static 和java 的有区别
C 语言 static
static 初始化 变量,默认值0,但是作用域 本文件
修饰 函数 ,限定在本文件使用,默认是extern
C++的 static
修饰 变量和c 差不多
但是修饰函数不同, 实现的时候可以不用写static,只能访问静态成员,不需要实例就可以使用