C语言结构、联合、位操作、位域和枚举

1、结构

1.1 定义结构和结构类型的变量

(1)
struct card
{
char *face;
char *suit;
};
struct card aCard,deck[52],*cardPtr;
(2)
struct card
{
char *face;
char *suit;
}aCard,deck[52],*cardPtr;
(3)
struct
{
char *face;
char *suit;
}aCard,deck[52],*cardPtr;
(4)
typedef struct
{
char *face;
char *suit;
}Card;
Card aCard,deck[52],*cardPtr;

(1)
struct EdgeNode //边表结点
{
EdgeType weight; //用于存储权值,对于非网图可以不需要
struct EdgeNode *next; //链域,指向下一个邻接点
};
typedef struct EdgeNode EdgeNode;
(2)
typedef struct EdgeNode/* 边表结点  */
{
EdgeType weight;/* 用于存储权值,对于非网图可以不需要 */
struct EdgeNode *next; /* 链域,指向下一个邻接点 */
} EdgeNode;

typedef struct EdgeNode //边表结点
{
EdgeType weight; //用于存储权值,对于非网图可以不需要
struct EdgeNode *next; //链域,指向下一个邻接点
} EdgeNode;

typedef struct VertexNode //顶点表结点
{
VertexType data; //顶点域,存储顶点信息
EdgeNode *firstedge; //边表头指针

typedef struct
{
int numNodes, numEdges; //图中当前顶点数和边数
//上面的代码非来自本博，仅用来举例说明

1.2 结构的内存对齐问题

struct E
{
char c;
int i;
}e1,e2;

1.3 结构的初始化

1.4 访问结构成员

1.5 在函数中使用结构

1.6 一个结构的例子

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

struct card
{
const char *face;
const char *suit;
};
typedef struct card Card;

void fillDeck(Card * const wDeck,const char *wFace[],const char *wSuit[]);
void shuffle(Card *const wDeck);
void deal(const Card * const wDeck);

int main()
{
//定义数组存储纸牌
Card deck[52];
//牌面数组
const char *face[]={"Ace","Deuce","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Jack","Queen","King"};
//花色

//设置随机数发生器的种子
srand(time(NULL));
fillDeck(deck,face,suit);
//shuffle the card
shuffle(deck);
//distribute
deal(deck);
return 0;
}
void fillDeck(Card * const wDeck,const char *wFace[],const char *wSuit[])
{
int i;
for (i=0;i<=51;i++)
{
wDeck[i].face=wFace[i%13];
wDeck[i].suit=wSuit[i%4];
}
}
void shuffle(Card *const wDeck)
{
int i;
int j;
Card temp;
//随机选出一张放在第i个位置
for (i=0;i<=51;i++)
{
j=rand()%52;
temp=wDeck[i];
wDeck[i]=wDeck[j];
wDeck[j]=temp;
}
}
void deal(const Card *const wDeck)
{
int i;
for (i=0;i<=51;i++)
printf("%5s of %-8s%c",wDeck[i].face,wDeck[i].suit,(i+1)%3?'\t':'\n');
}

2、联合(union)

2.1 定义和初始化

union number
{
int x;
double y;
};

2.2 联合的例子

#include <stdio.h>
union number
{
char c;
unsigned int i;
};
int main()
{
union number value;

value.c='A';
printf("%s:\nchar:%c\nunsigned int:%d\n","Put a value int the char member",value.c,value.i);

value.i=97;
printf("%s:\nchar:%c\nunsigned int:%d\n","Put a value int the unsigned int member",value.c,value.i);

value.c='A';
printf("%s:\nchar:%c\nunsigned int:%d\n","Put a value int the char member",value.c,value.i);
return 0;
}

2.3 联合的使用

2.3.1 增加代码的可读性

struct  Matrix
{
union
{
struct
{
float  _f11, _f12, _f21, _f22;
};
float  f[2][2];
}_matrix;
};
struct  Matrix m;

2.3.2 union和强制类型转换

#define TRUE 1
#define FALSE 0
#define BOOL int
//不用union
BOOL  isBigEndian()
{
unsigned int  i = 1;   /* i = 0x00000001*/
char  c = *(char  *)&i; /* 注意不能写成 char c = (char)i; */
return  (int )c != i;
}
//用union
BOOL  isBigEndian()
{
union
{
unsigned int  i;
char  c;
}test;
test.i = 2;
return  test.c != 2;
}
3、位运算

3.1 C语言提供了的位运算符

&|^ 对两个操作数按位进行与、或、异或操作
<<左移 将第一个操作数的各位向左移动第二个操作数所指定的位数；在右边用0来填充空位，向左移动到边界之外的1将丢失。
>>右移 将第一个操作数的各位向右移动第二个操作数所指定的位数；填充左边的方法依赖于计算机。对于unsigned整数执行右移将使得左边的空位用0代替，移动到右边界之外的1将丢失。如果右边的操作数是负值，或者右边的操作数大于存储左边操作数的位数，则移位的结果是不确定的。
~取反 将操作数按位取反
3.2 一个例子：以二进制的形式输出无符号整数

#include <stdio.h>
void displayBits(unsigned value);
int main()
{
unsigned x;
printf("Enter an unsigned integer:\n");
scanf("%u",&x);
displayBits(x);
return 0;
}
void displayBits(unsigned value)
{
unsigned c;
printf("%10u= ",value);
for (c=1;c<=32;c++)
{
value<<=1;//左移一位
if(c%4==0)
{
putchar(' ');
if(c%8==0)
putchar(' ');
}
}
putchar('\n');
}

4、位域

4.1 位域的声明

struct bitCard
{
unsigned face : 4;
unsigned suit : 2;
unsigned color : 1;
};

struct example
{
unsigned a : 13;
unsigned   : 19;
unsigned b : 4;
};

struct example
{
unsigned a : 13;
unsigned   : 0;
unsigned b : 4;
};

4.2 使用位域的好处和缺点

4.3 例子

#include<stdio.h>
struct bitCard
{
unsigned face : 4;
unsigned suit : 2;
unsigned color: 1;//1 bit
};
typedef struct bitCard Card;
void fillDeck(Card *const wDeck);
void deal(const Card * const wDeck);

int main()
{
Card deck[52];
fillDeck(deck);
deal(deck);
return 0;
}
void fillDeck(Card *const wDeck)
{
int i;
for (i=0;i<=51;i++)
{
wDeck[i].face=i%13;
wDeck[i].suit=i/13;
wDeck[i].color=i/16;
}
}
void deal(const Card * const wDeck)
{
int i;
for (i=0;i<=51;i++)
printf("Card:%2d Suit:%2d Color:%2d%s",wDeck[i].face,wDeck[i].suit,wDeck[i].color,(i+1)%3?" | ":"\n");
printf("\n");
}

5、枚举

C语言提供的最后一个用户自定义类型称为枚举。由关键字enum声明的枚举是用标识符表示的一组整数常量。实际上，这些枚举常量是可以自动设置值的符号常量。枚举中的值从0开始，每次增加1(除非特别指定)。

5.1 枚举声明

5.2 例子

#include <stdio.h>
//声明一个枚举类型
enum months {JAN=1,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC};
int main()
{
//定义一个枚举变量
enum months month;
const char *monthName[]={"*Error*","January","February","March","April",
"May","June","July","August","September","October","November","December"};
for (month=JAN;month<=DEC;month=(enum months)(1+(int)month))
{
printf("%2d %10s%c",month,monthName[month],month%2?'\t':'\n');
}
return 0;
}

• 本文已收录于以下专栏：

C语言中利用共用体、结构体、位域实现位操作

• a651588
• 2015年03月16日 11:39
• 1308

c语言位域操作—_结构体内冒号:的使用

• zhjmyx
• 2016年12月19日 13:41
• 807

C语言的结构体、联合和枚举

• lemonrabbit1987
• 2015年08月20日 09:47
• 909

联合体、位段巧妙用法

• xiaoliu0518
• 2014年06月17日 17:39
• 1907

[C语言]菜鸟的一些理解-结构体，共用体，枚举，位域

• u011741688
• 2013年10月10日 23:13
• 1478

UNION和位域的使用

• qq_21000273
• 2015年12月03日 11:01
• 1357

【C语言】位域的定义和使用

• xxxxxx91116
• 2013年07月02日 13:45
• 18140

C位域与大小端字节序 间关系

C位域 大端 小端 字节序
• feng2008ao
• 2016年05月22日 21:12
• 2844

C语言结构体，联合体，枚举体的内存大小计算方法

• u014453898
• 2016年12月17日 11:10
• 843

位域与union结构

位域　　有些信息在存储时，并不需要占用一个完整的字节， 而只需占几个或一个二进制位。例如在存放一个开关量时，只有0和1 两种状态， 用一位二进位即可。为了节省存储空间，并使处理简便，C语言又提供了一...
• xiven
• 2009年07月13日 10:25
• 5528

举报原因： 您举报文章：C语言结构、联合、位操作、位域和枚举 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)