网站建设需求调研通知,wordpress用户注册邮件,忻州做网站公司,药房网站模板之前C语言遗漏的一些。
数据在内存中的存储
原码、反码、补码
整数的2进制表⽰⽅法有三种#xff0c;即 原码、反码和补码
正整数的原、反、补码都相同。
负整数的三种表⽰⽅法各不相同。 原码#xff1a;直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。 反码即 原码、反码和补码
正整数的原、反、补码都相同。
负整数的三种表⽰⽅法各不相同。 原码直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。 反码将原码的符号位不变其他位依次按位取反就可以得到反码。 补码反码1就得到补码。 对于整形来说数据存放内存中其实存放的是补码。
⼤⼩端字节序和字节序判断 我们发现a是倒着存储的这是为什么 其实超过⼀个字节的数据在内存中存储的时候就有存储顺序的问题按照不同的存储顺序我们分 为⼤端字节序存储和⼩端字节序存储下⾯是具体的概念 ⼤端存储模式是指数据的低位字节内容保存在内存的⾼地址处⽽数据的⾼位字节内容保存 在内存的低地址处。 ⼩端存储模式是指数据的低位字节内容保存在内存的低地址处⽽数据的⾼位字节内容保存 在内存的⾼地址处。 为什么要有大小端呢
这是因为在计算机系统中我们是以字节为单位的每个地址单元都对应着⼀个字节⼀个字节为8 bit 位但是在C语⾔中除了8 bit 的 char 之外还有16 bit 的 short 型32 bit 的 long 型要看 具体的编译器另外对于位数⼤于8位的处理器例如16位或者32位的处理器由于寄存器宽度⼤ 于⼀个字节那么必然存在着⼀个如何将多个字节安排的问题。因此就导致了⼤端存储模式和⼩端存 储模式。 例如⼀个 16bit 的 short 型 x 在内存中的地址为 0x0010 x 的值为 0x1122 那么 0x11 为⾼字节 0x22 为低字节。对于⼤端模式就将 0x11 放在低地址中即 0x0010 中 0x22 放在⾼地址中即 0x0011 中。⼩端模式刚好相反。我们常⽤的 X86 结构是⼩端模式⽽ KEIL C51 则为⼤端模式。很多的ARMDSP都为⼩端模式。有些ARM处理器还可以由硬件来选择是 ⼤端模式还是⼩端模式。
判断大小端的两个程序
//代码1
#include stdio.h
int check_sys()
{int i 1;return (*(char *)i);
}
int main()
{int ret check_sys();if(ret 1){printf(⼩端\n);}else{printf(⼤端\n);}return 0;
}
//代码2
int check_sys()
{union{int i;char c;}un;un.i 1;return un.c;
} 浮点数在内存中的存储
常⻅的浮点数3.14159、1E10等浮点数家族包括 float、double、long double 类型。 浮点数表⽰的范围 float.h 中定义
当然对于浮点数的表示规则比较多比较繁琐这里就不解释了。
文件操作
为什么用文件文件是何文件分类 如果没有⽂件我们写的程序的数据是存储在电脑的内存中如果程序退出内存回收数据就丢失 了等再次运⾏程序是看不到上次程序的数据的如果要将数据进⾏持久化的保存我们可以使⽤ ⽂件。 磁盘上的⽂件是⽂件。 但是在程序设计中我们⼀般谈的⽂件有两种程序⽂件、数据⽂件从⽂件功能的⻆度来分类 的。 程序⽂件 程序⽂件包括源程序⽂件后缀为.c,⽬标⽂件windows环境后缀为.obj,可执⾏程序windows 环境后缀为.exe。 数据⽂件 ⽂件的内容不⼀定是程序⽽是程序运⾏时读写的数据⽐如程序运⾏需要从中读取数据的⽂件或 者输出内容的⽂件。 其实有时候我们会把信息输出到磁盘上当需要的时候再从磁盘上把数据读取到内存中使⽤这⾥处 理的就是磁盘上⽂件。 ⼀个⽂件要有⼀个唯⼀的⽂件标识以便⽤⼾识别和引⽤。 ⽂件名包含3部分⽂件路径⽂件名主⼲⽂件后缀 例如 c:\code\test.txt 为了⽅便起⻅⽂件标识常被称为⽂件名。 根据数据的组织形式数据⽂件被称为⽂本⽂件或者⼆进制⽂件。 数据在内存中以⼆进制的形式存储如果不加转换的输出到外存就是⼆进制⽂件。 如果要求在外存上以ASCII码的形式存储则需要在存储前转换。以ASCII字符的形式存储的⽂件就是⽂ 本⽂件。 ⼀个数据在内存中是怎么存储的呢 字符⼀律以ASCII形式存储数值型数据既可以⽤ASCII形式存储也可以使⽤⼆进制形式存储。 如有整数10000如果以ASCII码的形式输出到磁盘则磁盘中占⽤5个字节每个字符⼀个字节⽽ ⼆进制形式输出则在磁盘上只占4个字节 。 文件的打开和关闭
C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。 ⼀般情况下我们要想向流⾥写数据或者从流中读取数据都是要打开流然后操作 。 标准流那为什么我们从键盘输⼊数据向屏幕上输出数据并没有打开流呢 那是因为C语⾔程序在启动的时候默认打开了3个流 • stdin - 标准输⼊流在⼤多数的环境中从键盘输⼊scanf函数就是从标准输⼊流中读取数据。 • stdout - 标准输出流⼤多数的环境中输出⾄显⽰器界⾯printf函数就是将信息输出到标准输出 流中。 • stderr - 标准错误流⼤多数环境中输出到显⽰器界⾯。 这是默认打开了这三个流我们使⽤scanf、printf等函数就可以直接进⾏输⼊输出操作的。 stdin、stdout、stderr 三个流的类型是 FILE* 通常称为⽂件指针。 C语⾔中就是通过 FILE* 的⽂件指针来维护流的各种操作的。 文件指针 缓冲⽂件系统中关键的概念是“⽂件类型指针”简称“⽂件指针”。 每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区⽤来存放⽂件的相关信息如⽂件的名 字⽂件状态及⽂件当前的位置等。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系 统声明的取名FILE. 文件类型申明
struct _iobuf {char *_ptr;int _cnt;char *_base;int _flag;int _file;int _charbuf;int _bufsiz;char *_tmpfname;};
typedef struct _iobuf FILE; 不同的C编译器的FILE类型包含的内容不完全相同但是⼤同⼩异。 每当打开⼀个⽂件的时候系统会根据⽂件的情况⾃动创建⼀个FILE结构的变量并填充其中的信 息使⽤者不必关⼼细节。 ⼀般都是通过⼀个FILE的指针来维护这个FILE结构的变量这样使⽤起来更加⽅便。 下⾯我们可以创建⼀个FILE*的指针变量:
FILE* pf;//⽂件指针变量
定义pf是⼀个指向FILE类型数据的指针变量。可以使pf指向某个⽂件的⽂件信息区是⼀个结构体变 量。通过该⽂件信息区中的信息就能够访问该⽂件。也就是说通过⽂件指针变量能够间接找到与 它关联的⽂件。 ⽂件在读写之前应该先打开⽂件在使⽤结束之后应该关闭⽂件。 在编写程序的时候在打开⽂件的同时都会返回⼀个FILE*的指针变量指向该⽂件也相当于建⽴了 指针和⽂件的关系。 ANSIC 规定使⽤ fopen 函数来打开⽂件 fclose 来关闭⽂件。 //打开⽂件
FILE * fopen ( const char * filename, const char * mode );
//关闭⽂件
int fclose ( FILE * stream ); fopen文件打开模式 r代表read的简写代表可读可写w代表writeb代表bit二进制位t代表text r 打开只读文件该文件必须存在 r 打开可读可写的文件该文件必须存在(这里的写文件是指将之前的文件覆盖 rt 打开只读文本文件该文本必须存在 rt 读写打开一个文本文件允许读和写该文件必须存在(这里的写文件是指将之前的文件覆盖 rb 只读打开一个二进制文件该文本必须存在 rb 读写打开一个文本文件允许读和写该文件必须存在(这里的写文件是指将之前的文件覆盖 w 打开只写文件若文件存在则文件长度清零即文件内容会消失若文件不存在则建立该文件 w 打开可读写文件若文件存在则文件长度清零即文件内容会消失若文件不存在则建立该文件(这里的读文件同样需要使用rewind()函数) wt 打开只写文本文件若文件存在则文件长度清零即文件内容会消失若文件不存在则建立该文件 wt 打开可读写文本文件若文件存在则文件长度清零即文件内容会消失若文件不存在则建立该文件 wb 打开只写二进制文件若文件存在则文件长度清零即文件内容会消失若文件不存在则建立该文件 wb 打开可读写文件若文件存在则文件长度清零即文件内容会消失若文件不存在则建立该文件 a以附加的方式打开只写文件若文件不存在则建立文件存在则在文件尾部添加数据,即追加内容 a以附加的方式打开可读写文件不存在则建立文件存在则写入数据到文件尾(这里的读文件同样需要使用rewind()函数但是写文件不需要rewind()函数a是追加) at二进制数据的追加不存在则创建只能写。 at读写打开一个文本文件允许读或在文本末追加数据(这里的读文件同样需要使用rewind()函数但是写文件不需要rewind()函数a是追加) ab二进制数据的追加不存在则创建只能写。 ab读写打开一个二进制文件不存在则创建,允许读或在文本末追加数据(这里的读文件同样需要使用rewind()函数但是写文件不需要rewind()函数a是追加) /* fopen fclose example */
#include stdio.h
int main ()
{FILE * pFile;//打开⽂件pFile fopen (myfile.txt,w);//⽂件操作if (pFile!NULL){fputs (fopen example,pFile);//关闭⽂件fclose (pFile);}return 0;
} 顺序函数读写函数 函数名 功能 适⽤于 fgetc 字符输⼊函数 所有输⼊流 fputc 字符输出函数 所有输出流 fgets ⽂本⾏输⼊函数 所有输⼊流 fputs ⽂本⾏输出函数 所有输出流 fscanf 格式化输⼊函数 所有输⼊流 fprintf 格式化输出函数 所有输出流 fread ⼆进制输⼊ ⽂件 fwrite ⼆进制输出 ⽂件 文件的随机读写 fseek 根据⽂件指针的位置和偏移量来定位⽂件指针。
ftell 返回⽂件指针相对于起始位置的偏移量
rewind 让⽂件指针的位置回到⽂件的起始位置
编译和链接
翻译环境和运⾏环境 在ANSI C的任何⼀种实现中存在两个不同的环境。 第1种是翻译环境在这个环境中源代码被转换为可执⾏的机器指令。 第2种是执⾏环境它⽤于实际执⾏代码。 那翻译环境是怎么将源代码转换为可执⾏的机器指令的呢这⾥我们就得展开开讲解⼀下翻译环境所 做的事情。 其实翻译环境是由编译和链接两个⼤的过程组成的⽽编译⼜可以分解成预处理有些书也叫预编 译、编译、汇编三个过程。 ⼀个C语⾔的项⽬中可能有多个 .c ⽂件⼀起构建那多个 .c ⽂件如何⽣成可执⾏程序呢 • 多个.c⽂件单独经过编译出编译处理⽣产对应的⽬标⽂件。 • 注在Windows环境下的⽬标⽂件的后缀是 .obj Linux环境下⽬标⽂件的后缀是 .o • 多个⽬标⽂件和链接库⼀起经过链接器处理⽣成最终的可执⾏程序。 • 链接库是指运⾏时库(它是⽀持程序运⾏的基本函数集合)或者第三⽅库。 预处理
预定义符号
C语⾔设置了⼀些预定义符号可以直接使⽤预定义符号也是在预处理期间处理的。
__FILE__ //进⾏编译的源⽂件
__LINE__ //⽂件当前的⾏号
__DATE__ //⽂件被编译的⽇期
__TIME__ //⽂件被编译的时间
__STDC__ //如果编译器遵循ANSI C其值为1否则未定义
#define定义常量
#define MAX 1000
#define reg register //为 register这个关键字创建⼀个简短的名字
#define do_forever for(;;) //⽤更形象的符号来替换⼀种实现
#define CASE break;case //在写case语句的时候⾃动把 break写上。
// 如果定义的 stuff过⻓可以分成⼏⾏写除了最后⼀⾏外每⾏的后⾯都加⼀个反斜杠(续⾏符)。
#define DEBUG_PRINT printf(file:%s\tline:%d\t \date:%s\ttime:%s\n ,\__FILE__,__LINE__ , \__DATE__,__TIME__ )
#define定义宏
#define 机制包括了⼀个规定允许把参数替换到⽂本中这种实现通常称为宏macro或定义宏 define macro。 下⾯是宏的申明⽅式
#define name( parament-list ) stuff
其中的 parament-list 是⼀个由逗号隔开的符号表它们可能出现在stuff中。 注意 参数列表的左括号必须与name紧邻如果两者之间有任何空⽩存在参数列表就会被解释为stuff的 ⼀部分。 宏替换的规则
在程序中扩展#define定义符号和宏时需要涉及⼏个步骤。 1. 在调⽤宏时⾸先对参数进⾏检查看看是否包含任何由#define定义的符号。如果是它们⾸先 被替换。 2. 替换⽂本随后被插⼊到程序中原来⽂本的位置。对于宏参数名被他们的值所替换。 3. 最后再次对结果⽂件进⾏扫描看看它是否包含任何由#define定义的符号。如果是就重复上 述处理过程。 注意 1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏不能出现递归。 2. 当预处理器搜索#define定义的符号的时候字符串常量的内容并不被搜索。