c语言基础(一)

c语言基础(一)

开个头:嘿嘿,最近终于有的闲,好好整理一下码农的工具箱,收拢一下一些基础知识吧,go go go ............

——————————————————————————————————

                                                     目录

1、结构体字节对齐

2、大端小端

3、结构体相关的一些有意思的宏

4、函数指针的使用

——————————————————————————————————

1、结构体字节对齐

1)系统相关

                char        short        int        long        long long        float        double

32位         1             2              4           4              8                      4              8  

64位         1             2              4           8              8                      4              8


2)如何指定字节对齐

#pragmapack(2)//编译器命令,按照2个字节对齐

..................................................

..................................................

#pragmapack()//取消指定对齐,恢复缺省的对齐

3)空结构体

sizeof(空结构)   gcc为0  g++为1

4)编译选项

-fpack-struct

5)位域

struct

{

unsigned char ucJust      :4; 

unsigned char ucKidding:3;

unsigned char ucTest      :3;

unsigned char ucBit        :4;

}SB;

sizeof(SB)为 2

2、大端小端

大端:数的低位存在高地址中,高位存在低地址中 (大-低高高低);

小端:数的低位存在低地址中,高位存在高地址中 (小-低低高高);

网络字节序:大端

1)如何判断机器是大端还是小端?

int   IsThisABigEndianCookie()
{
       short	sCookie = 0x1234;
       char   *pCookie = (char *)(&sCookie);
       if(*pCookie ==  0x12)
       {
    		return 1;
       }
       else 
       {
              return 0;
       }
       return -1;
}

2)ip地址点分十进制的输出

int main(int argc, char* argv[])
{
    	int a = 0x12345678;
    	unsigned char *p = (unsigned char *)&a;
    	char buf[20]={0};
	sprintf(buf, sizeof(buf), "%d.%d.%d.%d", p[3], p[2], p[1], p[0]);
	//snprintf(buf, sizeof(buf), "%d.%d.%d.%d", a >> 24,  (a >> 16) & 0xff, (a >> 8) & 0xff, a & 0xff);
    	printf(“%s\n”,str);
    	return 0;
}
大端输出:120.86.52.18
小端输出:18.52.86.120

3)位域的大小端问题

union {
    struct  
    {
        unsigned char a1:2;
        unsigned char a2:3;
        unsigned char a3:3;
    }x;
    unsigned char b;
}d;
int main(int argc, char* argv[])
{
    d.b = 100;
    printf("%d %d %d\n", d.x.a1, d.x.a2, d.x.a3);
    return 0;
}

小端输出: 0  1  3

大端输出: 3  1  0

4)位域结构体的一般定义形式

struct {
#ifdef BIG_ENDIAN
       inta:1;
       intb:2;
       intc:3;
       intd:4;
#else
       intd:4;
       intc:3;
       intb:2;
       inta:1;
#endif   
} B;

3、结构体相关的一些有意思的宏

1)根据结构体的某一成员地址获取结构体的地址

step1:根据结构体成员地址获取该成员的offset

step2:根据上述的offset获取结构体的地址

#define OFFSET_OF(TYPE, MEM)  ((long) &((TYPE *)0)->MEM)

#define MEM_TO_TYPE(pMEM, TYPE, MEM)   (TYPE *)((long)pMEM - OFFSET_OF(TYPE, MEM))

应用场景:vxworks里使用这种方式设计了可以适用于任何数据结构的单双链表

4、函数指针的使用

typedef int (*FUNCPTR)();

1)使用场景-类Strategy模式

        举个例子吧,如队列的实现策略有“先入先出队列”,“优先级队列”等,如果每一种队列都对外提供一组操作接口,那上层如果要更改调用策略的话,就要把所有接口名都改了,为了达到松耦合,我们设计一组统一的操作接口,接口实际调用了具体类型的处理函数,由上层在使用时指定队列类型(动态绑定),然后调用,如果上层要更改策略,则把队列类型改了就行,用结构体打包一组接口(函数指针类型),把该打包的地址提供给外围使用。

//打包接口的类型
typedef struct qClass
 {
    (FUNCPTR)qCreate;
    (FUNCPTR)qInit;
    (FUNCPTR)qDelete;
    (FUNCPTR)qInsertRtn;
    (FUNCPTR)qPut;
    (FUNCPTR)qGet;
    (FUNCPTR)qRemove;
}Q_CLASS;

//具体的实现类型-fifo队列
LOCAL Q_CLASS qFifoClass =
{
    (FUNCPTR)qFifoCreate,
    (FUNCPTR)qFifoInit,
    (FUNCPTR)qFifoDelete,
    (FUNCPTR)qFifoNullRtn,
    (FUNCPTR)qFifoPut,
    (FUNCPTR)qFifoGet,
    (FUNCPTR)qFifoRemove
};
/* globals */
Q_CLASS_ID qFifoClassId = &qFifoClass;


//具体的实现类型-pri队列
LOCAL Q_CLASS qPriDeltaClass =
{
    (FUNCPTR)qPriCreate,
    (FUNCPTR)qPriInit,
    (FUNCPTR)qPriDelete,
    (FUNCPTR)qPriTerminate,
    (FUNCPTR)qPriPut,
    (FUNCPTR)qPriGet,
    (FUNCPTR)qPriRemove
};
/* globals */
Q_CLASS_ID qPriClassId = &qPriClass;

2)使用场景-回调

如libc里面qsort定义

void qsort(void *base,int nelem,int width,int (*fcmp)(const void *,const void *));





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值