每日三百行代码 第六天

  1. C 结构体
  2. 位域
  3. C 共用体
  4. C typedef

C结构体


//C数组允许定义可存储相同类型数据项的变量
//结构是C编程中另一种用户自定义的可用的数据类型
//它允许你存储不同类型的数据项。

//定义结构
struct name{
       //name 结构体标签 
	int i;      //标准的变量定义 
	float a;
	double c;
	char b;
	int m[10];
	....
}zname;
//结构变量,定义在结构的末尾,最后一个分号之前
//可以指定一个或多个结构变量 


struct name{
   
	int i;
	double a;
	char c;
}; 
struct name t1,t2[10],*t3; 

//结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针
//通常这种指针的应用是为了实现一些更高级的数据结构 如:链表和树等。

//此结构体包含其他结构体
struct COMPLEX{
   
	char string[100];
	struct SIMPLE a;
}; 

//此结构体包含了指向自己类型的指针
struct NODE{
   
	char string[100];
	struct NODE *next_node;
}; 
//结构体变量的初始化 
struct books{
   
	char name[100];
	char author[100];
	int cost;
} book={
   "goodstudy","eternity","100"}; 
//为了访问结构成员,我们使用成员访问运算符(.)
#include <stdio.h>
#include <string.h>
 
struct Books
{
   
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};

int main(){
   
	struct Books book;
	strcpy(book.title,"goodstudy");
	strcpy(book.author,"eternity");
	strcpy(book.subject,"abc");
	book.book_id=123456;
	
	printf( "Book title : %s\n", book.title);
    printf( "Book author : %s\n", book.author);
    printf( "Book subject : %s\n", book.subject);
    printf( "Book book_id : %d\n", book.book_id);
    return 0;
} 

//指向结构的指针
 
//定义指向结构的指针,方式与定义指向其他类型变量的指针相似
struct Books *struct_pointer;

//在上述定义的指针变量中存储结构变量的地址
//为了查找结构变量的地址,把&运算符放在结构名称的前面
struct_pointer = &book;

//为了使用指向该数据结构的成员,使用->运算符
struct_pointer->title;

#include<stdio.h>
#include<string.h>

struct Books{
   
	char title[100];
	char author[100];
	char subject[100];
	int book_id;
	
};
 
void printBook(struct Books *book){
   
	printf("Book title: %s\n",book->title);
	printf("Book author: %s\n",book->author);
	printf("Book subject: %s\n",book->subject);
	printf("Book book_id: %d\n",book->book_id);
}

int main(){
   
	struct Books Book1;//声明 
	
	strcpy(Book1.title,"goodstudy");
	strcpy(Book1.author,"eternity");
	strcpy(Book1.subject,"abc");
	Book1.book_id=123456;
	
	printBook(&Book1);
	//通过传Book1的地址来输出Book1的信息 
	
	return 0; 
}

位域


有些信息在存储时,并不需要占用一个完整的字节
而只需要占几个或一个二进制位
如在存放一个开关量时,只有01两种状态,用一位二进位即可
为了节省存储空间,并使处理简便,C语言又提供了一种数据结构
称为"位域""位段" 

所谓"位域"是把一个字节中的二进位划分为几个不同的区域
并说明每个区域的位数
每个域有一个域名,允许在程序中按域名进行操作
这样就可以把几个不同的对象用一个字节的二进制位域来表示

典例:
//用1位二进位存放一个开关量时,只有0和1两种状态
//读取外部文件格式--可以读取非标准的文件格式

//位域的定义和位域变量的说明
struct bs{
   
	int a:8;//a占8位 
	int b:2;//b占2位 
	int c:6;//c占6位 
}data; 

//一个位域存储在同一个字节中,如一个字节所剩空间不够存放另一个位域时
//则会从下一单元起开始存放该位域
//也可以有意使某位域从下一单元开始
struct bs{
   
	unsigned a:4;
	unsigned  :4;//空域 //int后四位填0表示不使用 
	unsigned b:4;//从下一个单元开始存放,占4位 
}; 
 
//由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度
//也就是说不能超过8位的二进位
//如果最大长度大于计算机的整数字长
//一些编译器可能会允许域的内存重叠
//另一些编译器可能会把大大于一个域的部分存储在下一字节中

//位域可以是无名位域,这时它只用来作填充或调整位置
//无名的位域是不能使用的

#include<stdio.h>

int main(){
   
	struct bs{
   
		unsigned a:1;
		unsigned b:3;
		unsigned c:4;
	}bit,*pbit;
	bit.a=1;
	bit.b=7;
	bit.c=15;
	printf("%d %d %d\n",bit.a,bit.b,bit.c);
	pbit=&bit;//把位域变量bit的地址送给指针变量*pbit
	pbit->a=0;//用指针的方式给位域a重新赋值
	pbit->b&=3;
	//使用了复合的位运算符"&=",相当于:pbit->b=pbit->b&3
	//位域b中原有值为7,与3作按位与运算的结果为3
	//111&011=011,十进制值为3
	pbit->c|=1;
	//使用了复合的位运算符"|=",相当于:pbit->c=pbit->c|1
	//1111|0001=1111,十进制值为15
	printf("%d %d %d\n",pbit->a,pbit->b,pbit->c);
	return 0; 
} 

C 共用体

//共用体是一种特殊的数据类型,允许你在相同的内存位置存储不同的数据类型
//你可以定义一个带有多成员的共用体
//但是任何时候只能有一个成员带有值
//共用体提供了一种使用相同的内存位置的有效方法

//定义共用体

union  Book{
   
	int i;
	float f;
	char str[100]; 
}data;
//表示一个变量(相同的内存位置)可以存储多个多种类型的数据
//可以根据需要在一个共用体内使用任何内置的或者用户自定义的数据类型
//共用体占用的内存应足够存储共用体中最大的成员 
//如:
#include<stdio.h>
#include<string.h>

union Data{
   
	int i;
	float f;
	char str[100];
}; 

int main(){
   
	union Data data;
	printf("Memory size occupied by data: %d\n",sizeof(data));
	return 0;
}

//访问共同体成员
//使用成员访问运算符(.)

#include<stdio.h>
#include<string.h>

union Data{
   
	int i;
	float f;
	char str[100];
}; 

int main(){
   
	union Data data;
	data.i=10;
	data.f=100.25;
	strcpy(data.str,"eternity");
	
	printf("%d %f %s\n",data.i,data.f,data.str);
	return 0;
}
//i和f的值有损坏,因为最后赋给变量的值占用了内存位置
//str能完好输出


#include <stdio.h>
#include <string.h>
 
union Data
{
   
   int i;
   float f;
   char  str[20];
};
 
int main( )
{
   
   union Data data;        
 
   data.i = 10;
   printf( "data.i : %d\n", data.i);
   
   data.f = 100.25;
   printf( "data.f : %f\n", data.f);
   
   strcpy( data.str, "eternity");
   printf( "data.str : %s\n", data.str);
 
   return 0;
}
//所有成员都能完好输出,因为同一时间只用到一个成员
 

C typedef


//可以使用typedef来为一个类型取一个新名字
typedef unsigned char ASD;
ASD b1,b2;
//ASD为unsigned char 的缩写

//可以对结构体使用typedef来定义一个新的数据类型名字
//然后使用这个新的数据类型来直接定义结构变量 
#include <stdio.h>
#include <string.h>
 
typedef struct Books
{
   
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
}Book;

int main(){
   
	Book book;
	strcpy(book.title,"goodstudy");
	strcpy(book.author,"eternity");
	strcpy(book.subject,"abc");
	book.book_id=123456;
	
	printf( "Book title : %s\n", book.title);
    printf( "Book author : %s\n", book.author);
    printf( "Book subject : %s\n", book.subject);
    printf( "Book book_id : %d\n", book.book_id);
    return 0;
} 

//#define 是C指令,用于为各种数据类型定义别名

//typedef 仅限于为类型定义符号名称
//#define 不仅可以为类型定义别名,也能为数值定义别名
 
//typedef是由编译器执行解释的,#define语句是由预编译器进行处理的

//#define的简单用法
#include<stdio.h>

#define TRUE 1
#define FALSE 0

int main(){
   
	printf("%d %d\n",TRUE,FALSE);
	return 0;
}