1.结构体struct
1.1 结构体的基本知识
#include <stdio.h>
struct point{
int x;
int y;
}p1, p2, p3;
struct point pt;
struct point pt2 = {300, 400};
struct point pt3 = {.x = 500};
struct rect {
struct point pt1;
struct point pt2;
};
struct rect screen;
int main()
{
printf("pt2.x = %d, pt2.y = %d\n", pt2.x, pt2.y);
printf("pt3.x = %d, pt3.y = %d\n", pt3.x, pt3.y);
double dist, sqrt();
dist = sqrt((double)pt2.x*pt2.x + (double)pt2.y*pt2.y);
printf("dist = %lf \n", dist);
printf("screen.pt2.x = %d \n", screen.pt2.x);
return 0;
}
huashidazhongbeitushuguan5deiMac:wufile duzhe$ vim struct.c
huashidazhongbeitushuguan5deiMac:wufile duzhe$ gcc struct.c
huashidazhongbeitushuguan5deiMac:wufile duzhe$ ./a.out
pt2.x = 300, pt2.y = 400
pt3.x = 500, pt3.y = 0
dist = 500.000000
screen.pt2.x = 0
huashidazhongbeitushuguan5deiMac:wufile duzhe$
1.2 结构体与函数
- 传递结构体的每个成员变量;
- 传递整个机构体;
- 传递指向结构体的指针;
#include <stdio.h>
struct point{int x; int y;};
struct rect {
struct point pt1;
struct point pt2;
};
struct rect screen;
struct point midlle;
struct point makepoint(int, int);
int main()
{
#define XMAX 300
#define YMAX 400
screen.pt1 = makepoint(0, 0);
screen.pt2 = makepoint(XMAX, YMAX);
struct point origin = {30}, *pp;
origin.y = 40;
//origin = {.x = 30, .y = 40}; //error
//origin = {30, 40}; //error
pp = &origin;
printf("origin: .x,.y is (%d, %d)\n", origin.x, origin.y);
printf("origin: (*pp).x is (%d, %d)\n", (*pp).x, (*pp).y);
printf("origin: pp->x is (%d, %d)\n\n", pp->x, pp->y);
return 0;
}
struct point makepoint(int x, int y)
{
struct point temp;
temp.x = x;
temp.y = y;
return temp;
}
/*
struct point addpoint(struct point p1, struct point p2)
{
p1.x += p2.x;
p1.y += p2.y;
return p1;
}
int pt_in_rect(struct point p, struct rect r)
{
return p.x >= r.pt1.x && p.x <= r.pt2.x
&& p.y >= r.pt1.y && p.y <= r.pt2.y;
}
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
// 矩形规范化
struct rect canon_rect(struct rect r)
{
struct rect temp;
temp.pt1.x = min(r.pt1.x, r.pt2.x);
temp.pt1.y = min(r.pt1.y, r.pt2.y);
temp.pt2.x = max(r.pt1.x, r.pt2.x);
temp.pt2.y = max(r.pt1.y, r.pt2.y);
return temp;
}
*/
struct rect r, *rp = &r;
//下面四个等价的
r.pt1.x;
rp->pt1.x;
(r.pt1).x;
(rp->pt1).x;
//anonymous struct
struct {int len; char * str; }*p, pn[]={{10,"ah",},20,"ABC", 30,"123",};
p = &pn; //struct3.c:7:3: warning: incompatible pointer types assigning to 'struct (anonymous struct at struct3.c:6:1) *' from 'struct (anonymous struct at struct3.c:6:1) (*)[3]' [-Wincompatible-pointer-types]
p = pn;
//下面两个等价的
++p->len; //11
++(p->len); //12
//指向下个对象
(++p)->len; //20
(p++)->len; //20
(p)->len; //30
//字符串的操作
p = pn;
*p->str 同 *(p->str) // just a char. %c: a
*p->str++ 同 *s++ // %c: a ,->h
//(*p->str)++ 对象++,导致段错误
(*p->str)+1 //i
*p->str + 2 //j
*p++->str //%c: h 先取str值,后指向下个对象
*p->str //%c: A
p->str //%s: ABC
++(p->str)//%s: BC
1.3 结构体数组
struct key{
char *word;
int count;
}keytab[NKEYS];
struct key keytab2[MKEYS];
struct key{
char *word;
int count;
}keytab[]={"AUTO", 0, "char", 2, {"cha", 3,},};
1.4 自引用结构体
struct tnode{
char *word;
int count;
struct tnode *left;
struct tnode *right;
};
2.枚举变量enum
例子1
#include <stdio.h>
int main()
{
enum boolean{NO, YES}b;
enum boolean bb = YES;
printf("enum NO: %d\n", NO);
printf("boolean b: %d \n",b);
printf("boolena b = %d, bb = %d \n",b = NO, ++bb);
printf("sizeof(b): %lu, sizeof(enum boolean): %lu \n", sizeof(b), sizeof(enum boolean));
return 0;
}
huashidazhongbeitushuguan5deiMac:wufile duzhe$ vim enum.c
huashidazhongbeitushuguan5deiMac:wufile duzhe$ gcc enum.c
huashidazhongbeitushuguan5deiMac:wufile duzhe$ ./a.out
enum NO: 0
boolean b: 1790791734
boolena b = 0, bb = 2
sizeof(b): 4, sizeof(enum boolean): 4
huashidazhongbeitushuguan5deiMac:wufile duzhe$
例子2
// 不同枚举中的名字必须互不相同(有区分大小写),同一枚举不同名字的值可以相同
enum escapes{
BELL = '\a',
BELL2= '\a',
BACKSPACE = '\b',
TAB = '\t',
tab = '\t',
NEWLINE = '\n',
VTAB = '\v',
RETURN = '\r',
};
例子3
// 比#define有优势就是常量值就自动生成的,如:FEB = 2, MAR = 3 ...
enum months{JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV ,DEC };
3.联合体union
例子1
#include <stdio.h>
//共享同一内存,大小取决于最大成员
union {
int a;
char c;
}u = {10}; //初始化第一个成员,而且只能初始化一个
int main()
{
printf("1 sizeof(u): %lu\n", sizeof(u));
printf("%d, %c\n", u.a, u.c);
u.c = 'a';
printf("2 sizeof(u): %lu\n", sizeof(u));
printf("%d, %c\n", u.a, u.c);
return 0;
}
huashidazhongbeitushuguan5deiMac:wufile duzhe$ vim union.c
huashidazhongbeitushuguan5deiMac:wufile duzhe$ ./a.out
1 sizeof(u): 4
10,
2 sizeof(u): 4
97, a
好处:不确定类型时,或者兼容多种类型。
union u_tag{
int ival;
float fval;
char *sval;
}u;
if(utype == INT){
printf("%d\n", u.ival);
}else if(utype == FLOAT){
printf("%f\n", u.fval);
}else if(utype == STRING){
printf("%s\n", u.sval);
}else{
printf("bad type %d in utype\n", utype);
}
嵌套在结构体
struct {
char *name;
int flags;
int utype;
union{
int ival;
float fval;
char *sval;
}u;
}symtab[NSYM];
//引用成员ival
symtab[i].u.ival;
//引用sval第一个字符
*symtab[i].u.sval;
symtab[i].u.sval[0];
例子2
#include <stdio.h>
union {
int a;
float b;
char c;
}u = {10};
int main()
{
printf("1 sizeof(u): %lu\n", sizeof(u));
printf("%d, %f, %c\n", u.a, u.b, u.c);
u.b = 3.5f;
printf("2 sizeof(u): %lu\n", sizeof(u));
printf("%d, %f, %c\n", u.a, u.b, u.c);
return 0;
}
huashidazhongbeitushuguan5deiMac:wufile duzhe$ gcc union.c
huashidazhongbeitushuguan5deiMac:wufile duzhe$ ./a.out
1 sizeof(u): 4
10, 0.000000,
2 sizeof(u): 4
1080033280, 3.500000,
huashidazhongbeitushuguan5deiMac:wufile duzhe$
例子2-2
printf("1 sizeof(u): %lu\n", sizeof(u));
printf("%d, %f, %c\n", u.a, u.b, u.c);
u.b = 3.5f;
printf("2 sizeof(u): %lu\n", sizeof(u));
printf("%d, %f, %c\n", u.a, u.b, u.c);
u.c = 'a';
printf("3 sizeof(u): %lu\n", sizeof(u));
printf("%d, %f, %c\n", u.a, u.b, u.c);
huashidazhongbeitushuguan5deiMac:wufile duzhe$ vim union.c
huashidazhongbeitushuguan5deiMac:wufile duzhe$ gcc union.c
huashidazhongbeitushuguan5deiMac:wufile duzhe$ ./a.out
1 sizeof(u): 4
10, 0.000000,
2 sizeof(u): 4
1080033280, 3.500000,
3 sizeof(u): 4
1080033377, 3.500023, a
例子2-3
printf("1 sizeof(u): %lu\n", sizeof(u));
printf("%d, %f, %c\n", u.a, u.b, u.c);
u.c = 'a';
printf("3 sizeof(u): %lu\n", sizeof(u));
printf("%d, %f, %c\n", u.a, u.b, u.c);
huashidazhongbeitushuguan5deiMac:wufile duzhe$ vim union.c
huashidazhongbeitushuguan5deiMac:wufile duzhe$ gcc union.c
huashidazhongbeitushuguan5deiMac:wufile duzhe$ ./a.out
1 sizeof(u): 4
10, 0.000000,
2 sizeof(u): 4
10, 0.000000,
3 sizeof(u): 4
97, 0.000000, a
huashidazhongbeitushuguan5deiMac:wufile duzhe$
4.位字段
4.1 一般的方法定义屏蔽吗
//宏定义
#define KEYWORD 01
#define EXTERNAL 02
#define STATIC 04
//枚举变量
enum{KEYWORD = 01, EXTERNAL = 02, STATIC = 04};
flags |= EXTERNAL | STATIC;
flags &= ~(EXTERNAL | STATIC);
if((flags & (EXTERNAL|STATIC) ) == 0)...
4.2 用位字段来定义屏蔽吗
unsigned int 最大是4字节*8位 = 32位
,sizeof是总的字节数,且为4的倍数(0,4,8,16…).
#include <stdio.h>
//定义了3个一位宽度的字段
struct{ //33 = 32 + 1 (bit)= 4 up byte = 8 type.
unsigned int is_keyword : 1;
unsigned int is_extern : 1;
unsigned int is_static : 1;
unsigned int err : 8;
unsigned int add :16;
//unsigned int err2 :64; //bit.c:10:18: error: width of bit-field 'err2' (64 bits) exceeds width of its type (32 bits)
int :1; //无名字段
int :4;
int :0;
int :1;
}flags, *p = &flags;//字段不是数组,没有地址,不能用&引用,但结构体有地址可以用&引用。
int main()
{
printf("sizeof(flags): %lu\n", sizeof(flags));
printf("%d, %d\n", flags.is_extern, flags.is_static);
flags.is_extern = flags.is_static = 0;
printf("%d, %d\n", flags.is_extern, flags.is_static);
flags.is_extern = flags.is_static = 1;
printf("%d, %d\n", flags.is_extern, flags.is_static);
flags.is_extern = flags.is_static = 2;
printf("%d, %d\n", flags.is_extern, flags.is_static);
flags.is_extern = flags.is_static = 3;
printf("%d, %d\n", flags.is_extern, flags.is_static);
if(flags.is_extern == 0 && flags.is_static == 0);//...;
flags.add = 65525;
flags.err = 255;
printf("sizeof(flags): %lu\n", sizeof(flags));
return 0;
}
huashidazhongbeitushuguan5deiMac:wufile duzhe$ vim bit.c
huashidazhongbeitushuguan5deiMac:wufile duzhe$ gcc bit.c
bit.c:25:43: warning: implicit truncation from 'int' to bitfield changes value from 2 to 0 [-Wbitfield-constant-conversion]
flags.is_extern = flags.is_static = 2;
^ ~
bit.c:27:43: warning: implicit truncation from 'int' to bitfield changes value from 3 to 1 [-Wbitfield-constant-conversion]
flags.is_extern = flags.is_static = 3;
^ ~
bit.c:30:50: warning: if statement has empty body [-Wempty-body]
if(flags.is_extern == 0 && flags.is_static == 0);//...;
^
bit.c:30:50: note: put the semicolon on a separate line to silence this warning
3 warnings generated.
huashidazhongbeitushuguan5deiMac:wufile duzhe$ ./a.out
sizeof(flags): 8
0, 0
0, 0
1, 1
0, 0
1, 1
sizeof(flags): 8
huashidazhongbeitushuguan5deiMac:wufile duzhe$
5.自定义类型typedef
- 可移植性
- 容易理解
typedef int Length;
Length len, maxlen;
Lenght *length[];
typedef char* String;
String p, lineptr[MAXLINES], alloc(int);
int strcmp(String, String);
p = (String) malloc(1024);
typedef struct tnode *Treeptr;
typedef struct tnode{
char *word;
int count;
Treeptr *left;
Treeptr *right;
}Treenode;
Treeptr talloc(void)
{
return (Treeptr)malloc(sizeof(Treenode));
}
// PFI是一个指向函数的指针
typedef int (*PFI)(char*, char*);
PFI strcmp, strcpy;
6.字节对齐
以最长(系统一次读的长度)为基本单位。
struct A{
int a;//4/
char b;//1
short c;//2
//1/
}a;
sizeof(a) = sizeof(struct A) = 8;
struct B{
char a;//4
int b;//4/
short c;//4
}b;
sizeof(b) = sizeof(struct B) = 12;
32位系统一次4字节,long long 8位读两次。sizeof是以%d: int 返回。
{char 4, LL 4+4, int 4} = 16
{char 4, int 4, short4} = 12
{LL 4+4, char 4, int 4} = 16
{LL 4+4, char 4 short } = 12
64位系统一次8字节,没long时,一次读4字节。sizeof是以%lu: long unsigned int 返回。LL和L都是8个字节。
//一次读8字节
{ LL 8 , char 8 int } = 16
{char 8, LL 8 , int 8 } = 24
//一次读4字节
{char 4,int 4, short 4} = 12
{char 4 short , int 4 } = 8
pragma pach(x) 按x个字节对齐
#pragma pach(2)
struct c{char 2; int 2+2; short 2;} = 8
#pragma pach(1)
struct c{char 1; int 4; short 2;} = 7
Wu_Being博客声明:本人博客欢迎转载,请标明博客原文和原链接!谢谢!
《结构体struct、枚举enum、联合体union、位字段、自定义类型typedef、字节对齐》: http://blog.csdn.net/u014134180/article/details/78335328
如果你看完这篇博文,觉得对你有帮助,并且愿意付赞助费,那么我会更有动力写下去。