Just a little smile ^ ^

yoyo_zeng

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

结构, union, enum, typedef

 

struct structname

{

         int i; //除了static,其余不可在定义struct时赋值.

         char buf[32];

         double f;

} ;  //定义struct structname

structname a; //定义变量 a

structname a = {0, “123”, 1.2}; //初始化

a.i = 10;

支持初始化指定项目(C99)

structname a = {.i = 1};

 

不同平台的寻址方式不同,有的可能同偶地址开始读取, 编译器会将struct对齐, 以成员函数size的最大位对齐.

对于

struct structname

{

         int i;

         char buf[32];

} a; //sizeof(a) = 36; 4位对齐

 

struct structname

{

         double f;

} b; //sizeof(b) = 8;  8位对齐

 

struct structname

{

         int i;

         char buf[32];

         double f;

} c; //sizeof(c) = 48; 8位对齐

 

#progma pack (2) 可以指定对齐位数, 此时最终对齐值为自身对齐值和指定对齐值中的较低的那个.

对于空结构体,size == 1因为必须保证结构体的每一个实例在内存中都有独一无二的地址.
结构体的静态成员不对结构体的大小产生影响,因为静态变量的存储位置与结构体的实例地址无关.

 

struct structname

{

} a, *pstr; //定义struct和变量 a

 

和数组不同,一个结构的名字不是该结构的地址,必须使用&运算符.

memset(&a, 0, sizeof(structname));

 

struct 允许赋值,数组不可.

structname b;

a = b;

 

伸缩型数组成员(C99)

struct structname

{

         int i;

         double arr[]; //未分配任何内存,必须至少有一个其他成员,必须是最后//的一个数组成员.

} *p;

p = (structname *)malloc(sizeof(structname) + sizeof(double) * 5);

 

union

在同一存储空间里(但不同时)存储不同类型数据的数据类型,同一时间只能存储一个成员值,

union unionname

{

         int i;

         double f;

         char c

} a;

a.i = 10;

 

支持初始化指定项目(C99)

union a = {.i = 1};

union允许赋值,数组不可.

union b;

a = b;

 

enum

enum enumname

{

         one, //0

         two = 3, //注意,以逗号隔开

         three //4,注意没有逗号

} a;

a  = two;

 

typedef

typedef struct structname

{

         int i;

}nickname;

nickname a;

typedef char (* func())[5]; //typedef函数类型,无参数,返回值为指向char []的指针.

typedef char [5] *(* func)(); //typedef函数指针,无参数,返回值为指向char []的指针.

 

void func(char buf[]);

int main(int argc, _TCHAR* argv[])

{

         typedef void (* pfunc)(char buf[]);

         typedef void fun(char buf[]);

         pfunc  p = func;

         fun *a= func;

         return 0;

}

void func(char buf[])

{

}

 

C预处理器和C

 

编译器用一个空格字符代替每一个注释

int/*===*/a; //等同于 int a;

系统会删除反斜线和换行符的组合,但是编译其会有缩进,所以要注意喔.

 

预处理指令

#define

#define X 1

#define fun(n) n*n //func(4+2);最后结果为144+2*4+2

预处理器不进行计算,只是进行文字替换操作,实际计算过程是在编译阶段.

#运算符

#define PRINT(n) printf(#n" = %d\n", n); //#n可以吧参数转换为相应的字符串

#define PRINT1(n) printf("n = %d\n", n); //#n可以吧参数转换为相应的字符串

int main(int argc, _TCHAR* argv[])

{

         int x = 2;

PRINT1(2); //n = 2

         PRINT(x); //x = 2

         PRINT(2); //2 = 2

         return 0;

}

 

##运算符

#define X(n) x##n

#define PRINT(n) printf("x"#n"=%d\n", x##n);

int main(int argc, _TCHAR* argv[])

{

         int X(1) = 2; //等同于x1 = 2;

         PRINT(1); //x1 = 2

         return 0;

}

 

可变宏 __VA_ATGS__

#define X(n) x##n

#define PR(X,...) printf("hi, "#X": " _ _VA_ATGS_ _) //…必须放在最后

int main(int argc, _TCHAR* argv[])

{

         int X(1) = 2;

         PR(1, "x1 = %d", x1); //输出:hi, 1: x1 = 2

         return 0;

}

 

#define MYC

#ifdef MYC //或者 #ifndef MYC

...

#else

...

#endif

 

#define MYC

#if defined(MYC) //同上面的代码意义相同,#if后面跟常量整数表达式,如果表达式为非0,则表达式为真

...

#elif defined(YOURC)

...

#else

...

#endif

 

#pragma来启动修改对编译器的设置

#pragma C99 on

 

内联函数inline,编译器没有预留给它的单独带麻快,所以无法获得内联函数的地址(如果获得地址,编译器会产生非内联函数),编译时候优化内联函数,所以内联函数的定义和调用必须在同一文件中,故在头文件中定义内联函数,具有内部链接,所以编译不会产生问题.

 

int atexit(void (* pfunc)(void));

注册函数,在exit执行时,注册函数会执行.函数按先进后出顺序执行.

 

可变参数:stdarg.h

int i = 2;

char c = 'A';

char buf[32] = "abc";

func("%d%c%s", i, c, buf);

 

void func(char *format, ...); //…必须为最后一个参数

va_list ap//存放参数

va_start(ap, format); //ap初始化为参数列表,参数是从开始的.

int i = va_arg(ap, int); //n次调用va_arg,返回参数列表的第n个参数.va_arg不提供退回之前参数的方法,可用va_copy(apcopy, ap)先保存参数列表.

va_end(ap); //释放动态分配的用于存放参数的内存

posted on 2011-09-29 15:38  yoyo_zeng  阅读(209)  评论(0编辑  收藏  举报