C语言学习(五)

一、结构体

结构体定义由关键字 struct 和结构体名组成,结构体名可以根据需要自行定义。

struct tag {
    member-list
    member-list
    member-list  
    ...
} SnaxName1,SnaxName2 ;

tag是结构体标签,SnaxName是结构体变量名称,两者只可省略一个,SnaxName 可直接当变量使用。

1.结构体大小的计算

结构体内会要求内存对齐,具体要求如下:

  • 第一个成员的首地址为0.

  • 每个成员的首地址是自身大小的整数倍

  • 结构体的总大小,为其成员中所含最大类型的整数倍。

例如:

struct S1
{
  char a;   //1+3
  int  b;    //4
  short c;    //2+2
}s1;
//S1的大小为12字节,为4的倍数
struct S2
{
  char d[7]; //7+1
  double a;	//8
  short  b;	//2+2
  char* c;//32位系统,指针4字节  4 
}s2;
//S2的大小为24,为8的倍数

2、共用体

union是一个重要的复合数据类型,允许在相同的内存位置存储不同类型的数据。与struct不同,共用体中的所有成员共享同一块内存,这意味着在某一时刻,只有一个成员有效。访问方式与结构体相似。

union [union tag]
{
   member definition;
   member definition;
   ...
   member definition;
} [one or more union variables];

一个variables中的所有member 共享同一块内存,不同的variables不共享一块内存。

3.位域

位域(Bit-Field)是一种特殊的结构体成员,它允许你定义一个特定数量的位来存储数据,从而有效地节省内存空间。位域不能跨字节

struct
{
  unsigned int widthValidated : 1;
  unsigned int heightValidated : 1;
} status;
//结构体在有参情况下,占用最小为最大成员变量类型所占字节大小
//unsigned int 占4字节,但只取了1位,第一个补齐空闲位占1字节,由于结构体需要为4的倍数,第二个补齐空闲位占3字节。

struct area
{
      char a:6;   //向int对齐,扩展为32位
      char b:3;
      int c:20;
};

//a占1字节 c起始地址需要为4的倍数,所以b占1+2字节。总字节应为4最大成员的变量类型(int)字节的倍数,所有C占4字节。总占8字节。 

4.typedef

typedef 关键字,您可以使用它来为类型取一个新的名字。例如:

typedef unsigned char BYTE;
typedef unsigned char byte;

typedef struct Books
{
  char  title[50];
  char  author[50];
  char  subject[100];
  int   book_id;
} Book;
声明成员时,

Book 相当于 struct Books,声明成员时,可使用Book xx; 创建。

typedef vs #define

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

二、文件操作

C 语言把所有的设备都当作文件。所以设备(比如显示器)被处理的方式与文件相同。

1.打开文件

使用 fopen( ) 函数来创建一个新的文件或者打开一个已有的文件,这个调用会初始化类型 FILE 的一个对象,类型 FILE 包含了所有用来控制流的必要的信息。

FILE *fopen( const char *filename, const char *mode );

filename 是字符串,用来命名文件,访问模式 mode 的值可以是下列值中的一个:

模式描述
r打开一个已有的文本文件,允许读取文件。
w打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。如果文件存在,则该文件会被截断为零长度,重新写入。
a打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,程序会在已有的文件内容中追加内容。
r+打开一个文本文件,允许读写文件。
w+打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。
a+打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。

2.关闭文件

使用 fclose( ) 函数关闭文件。

int fclose( FILE *fp );

如果成功关闭文件,fclose( ) 函数返回零,如果关闭文件时发生错误,函数返回 EOF。这个函数实际上,会清空缓冲区中的数据,关闭文件,并释放用于该文件的所有内存。EOF 是一个定义在头文件 stdio.h 中的常量。

3.写入文件

写入文件可以使用以下三个函数:

int fputc( int c, FILE *fp );//写入单个字符
int fputs( const char *s, FILE *fp );//写入字符串
int fprintf(FILE *fp,const char *format, ...)//写入字符串

4.读取文件

读取文件使用以下三个函数:

int fgetc( FILE * fp );//写入单个字符
char *fgets( char *buf, int n, FILE *fp );//写入字符串
int fscanf(FILE *fp, const char *format, ...) //写入字符串

  fgets()fp 所指向的输入流中读取 n - 1 个字符。它会把读取的字符串复制到缓冲区 buf,并在最后追加一个 null 字符来终止字符串,函数返回值为读取到的字符。

  如果fgets()在读取最后一个字符之前就遇到一个换行符 '\n'或文件的末尾 EOF,则只会返回读取到的字符。

  fscanf()遇到第一个空格和换行符时,停止读取。

读取文件后,指针会移动,再次读取时不会从起始位置读取。

预宏定义

ANSI C 定义了许多宏。在编程中您可以使用这些宏,但是不能直接修改这些预定义的宏。

描述
__DATE__当前日期,一个以 “MMM DD YYYY” 格式表示的字符常量。
__TIME__当前时间,一个以 “HH:MM:SS” 格式表示的字符常量。
__FILE__这会包含当前文件名,一个字符串常量。
__LINE__这会包含当前行号,一个十进制常量。
__STDC__当编译器以 ANSI 标准编译时,则定义

头文件

有两种引用方式

#include <file> //这种形式用于引用系统头文件。
#include "file" //这种形式用于引用用户头文件。

三、内存管理

内存是通过指针变量来管理的。指针是一个变量,它存储了一个内存地址,这个内存地址可以指向任何数据类型的变量,包括整数、浮点数、字符和数组等。

序号函数和描述
1void *calloc(int num, int size);
在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0。所以它的结果是分配了 num*size 个字节长度的内存空间,并且每个字节的值都是 0。
2void free(void *address);
该函数释放 address 所指向的内存块,释放的是动态分配的内存空间。
3void *malloc(int num);
区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。
4void *realloc(void *address, int newsize);
该函数重新分配内存,把内存扩展到 newsize
5void *alloc(size_t size);
中分配一块内存,无法释放,和malloc不同的是,alloc并不会显式初始化内存,并且它可能是库或自定义函数。
  • 28
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值