attribute
1.由来:GNU C的特色机制,主要起到控制属性的目的,一般情况下放到函数声明之后,可以对函数属性、变量属性和类型属性之后。
2.例子
例子1:
extern int atexit (void(*__func)(void)) __THROW __nonnull((1));
这里你会说了,哪有attribute呢?我们接着往下看。
#define __THROW __attribute__ ((__nothrow__ __LEAF))
#define __nonnull(params) __attribute__((__nonull__ params))
这里两个宏定义,都是引用了__attribute__,它们都是在对atexit以及其参数进行限制。
这里的__THROW是添加了throw(),以此来优化函数调用;
这里nonnull标记指针参数,不允许其为NULL
例子2:
extern void exit(int) __attribute__((noreturn));
这里的参数noreturn告诉编译器,函数exit不会返回任何值。当函数需要返回值时,却没有返回值,一般情况下会报错,但是加上这个属性后,程序不会报错。
别的程序在调用有这种属性的函数时,即使最后没有返回值也不会报错。
例如一个程序运行出错了,于是调用了一个exit(),退出了程序,显示错误。这时,函数其实还没返回值,但是不显示错误,因为exit是noreturn的。
sizeof(struct)
查看结构体尺寸,这里面有一个处理过程,为提高CPU存储速度,VS对一些变量做了“对齐”处理,及变量的其实位置都应该是自己尺寸的整数倍。
例如:
struct Test_Struct
{
double A1;
char B1;
int C1;
};
sizeof(Test_Struct) = 16,而不是8+1+4=13
因为,0位存A1,8位存B1(因为char占用一位)
然而int是4位,9不是它的倍数,所有在9位不能存放C1,因该在12位存放C1。
8+1+3+4=16
函数指针
static void *recover_1 (void *param)
{
…………
}
有时候我们会看到这样的函数,recover_1是指针,这里大家就会问了,好好的一个函数为啥弄成指针???
一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是函数指针。
又因为
不存在“函数类型的变量”,但存在“指向函数的指针”
因为“指向函数的指针类型”也是指针类型,而指针类型又是属于对象类型
在函数调用中,输入的参数不能为函数,但是可以为指针,因此,将函数名定义为指针类型,可以实现函数作为参数的调用。
fun(recover_1,2)
互斥锁
互斥锁用来保证一段时间内只有一个线程执行加锁的代码,其他线程等待互斥锁解开后才可执行。
1)创建互斥锁线程标号
pthread_mutex_t mutex;
2)初始化并生成互斥锁
pthread_mutex_init (&mutex,NULL);
3)在只能单线程操作的地方加锁和解锁
//加锁
pthread_mutex_lock (&mutex);
//一段需要执行的代码
//解锁
pthread_mutex_unlock(&mutex);
4)为了避免线程对该函数一直占用,因此设定占用完此函数后需要等待一会,才可再次占用。
pthread_delay_np(&delay);