C语言总结由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“c语言总结”。
目录
1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 1.19 1.20 1.21 1.22 1.23 1.24 C基础知识.......................................................................................................1 函数与头文件..................................................................................................2 C预处理器.......................................................................................................3 将一个字符转换为long型.............................................................................4 strcpy函数.......................................................................................................4 aert用法.......................................................................................................5 itoa函数和atoi函数.......................................................................................6 strcmp函数实现.............................................................................................8 strcpy函数实现...............................................................................................9 memcpy函数实现.........................................................................................10 memcpy和memmove函数的实现.............................................................11 strcat函数实现..............................................................................................13 使用库函数atoi,将char *→int................................................................13 使用库函数itoa,将int→char *.................................................................14 不使用库函数,将int→char *....................................................................14 不使用库函数,将char *→int....................................................................15 求两个整数的最大公约数............................................................................16 Little_endian or Big_endian.........................................................................17 sizeof与strlen的区别..................................................................................19 实现String类的BIG_FOUR......................................................................19 struct和union的区别..................................................................................20 char字符变量与int整型数据.....................................................................22 字,字节,字符,比特.........................................................................................23 空格、空字符、字符数组结束符的区别....................................................25
1.1 C基础知识
位运算符 & 按位与
如果两个对应的二进制都为1,则该位结果值为1,否则为0
特殊用途:(1)清0(2)取一个数的特定位 | 按位或
如果两个对应的二进制中只要有一个为1,则结果为1,否则为0 ^ 按位异或
两个二进制同号,则结果为0,否则为1(1)与0相异或,保留原值(2)交换两个值,不用临时变量
将a,b交换 a = a ^ b;b = b ^ a;a = a ^ b;
~ 取反 > 右移
&& 与运算:表示如果y,z为真,则(y&&z)为真,返回一个布尔值1 || 或运算:表示如果y,z中有一个为真,则(y||z)为真,返回一个布尔值1
说明:位运算符除了~以外,均为二目运算符,即要求两侧各有一个运算量。运算量只能是整型或字符型的数据,不能为实型数据。
1.2 函数与头文件
#include using namespace std;函数:cout,endl
#include 函数:getchar, putchar, scanf, printf等
#include 函数:aert
#include 函数:itoa, atoi, atof, atol, strtod, strtol,system等
#include 函数:memcpy, strcpy, strcat,strlen等
#include 函数:abs等
1.3 C预处理器
C预处理器是一种简单的宏处理器。预处理器是由特殊的预处理器命令行控制的,它们是以#符号开头的源文件行。预处理器的一般操作:从源文件中删除所有的预处理器命令行,并在源文件中执行这些预处理器命令所指定的转换操作。
预处理器代码行的语法与C语言其他部分的语法是完全独立的,但经过预处理所产生的源代码必须在上下文环境中合法。常见的预处理器命令:
#define 定义一个预处理器宏 #undef 取消一个预处理器宏
#include 插入另一个源文件的文本 #if 测试一个常量表达式的值 #ifdef 测试如果一个宏已被定义 #ifndef 测试如果一个宏没有被定义 #else 测试失败后 #endif 终止条件文本
#line 提供用于编译器信息的行号
#elif 与else if相似
defined 判断一个宏是否被定义,已定义返回1,否则返回0,其与#if和#elif联用
# 将#后的宏标记转化为字符串
## 将两个相邻的宏标记连接成一个整体标记 #pragma 指定依赖编译器的信息
#error 用指定的信息产生一个编译时错误
常用的预定义的宏有:
__LINE__ 当前源程序行的行号,用十进制整数常量表示
__FILE__ 当前源文件的名称,用字符串常量表示
__DATE__ 编译时的日期,用“MM dd yyyy”形式的字符串常量表示
__TIME__ 编译时的时间,用“hh:mm:”形式的字符串常量表示
__STDC__ 当且只当编译器遵循ISO标准时,它的值是十进制常量1 __STDC__VERSION__ 如果编译器遵循C99,则这个宏的值是199901L,其他情况下,该宏没定义
__STDC__HOSTED__ 当前是宿主系统,该宏值为1,当前是独立系统,这个宏值为0
__STDC__IEC__559__ 如果浮点实现遵循IEC 60599标准,这个宏值为1,否则无定义
__STDC__IEC__559__COMPLEX__ 如果复数运算实现遵循IEC 60559标准,则该宏值为1,否则未定义
__STDC__ISO10646__ 定义为一个长整数常量
__LINE__和__FILE__在调试中的运用
上面这段代码通过#ifdef #else #endif三个条件编译指令,根据_DEBUG定义情况(该宏用于区分DEBUG版本和Release版本),决定了具体的TRACE_FILE_LINE_INFO宏函数的实现。使用者可以用如下方法使用
##标记符粘贴运算符
ANSI标准定义的标记符粘贴运算符##可以把宏定义中的两个标记符组合成一个标记符。
例如 #define combine(s1, s2)s1##s2 Combine(TOTAL,SALES)则为 TOTALSALES #define NAME(i)name ## i
NAME(1)=>name1
1.4 将一个字符转换为long型
char cMax;long lMax;cMax = getch();lMax = cMax & 0xF;1.5 strcpy函数
原型:extern char *strcpy(char *dest,char *src);用法:#include 功能:把src所指由NULL结束的字符串复制到dest所指的数组中。
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。返回指向dest的指针。给一个很经典版本的strcpy函数源码: char *strcpy(char *strDest, const char *strSrc);{
aert((strDest!=NULL)&&(strSrc!=NULL));
char *addre = strDest;
while((*strDest++ = * strSrc++)!=‘ ’)NULL;
return addre;} 1.6 aert用法
aert宏的原型定义在中,其作用是如果它的条件返回错误,则终止程序执行,原型定义: #include void aert(int expreion);aert的作用是现计算表达式expreion,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。请看下面的程序清单badptr.c: #include #include #include int main(void){
FILE *fp;
fp = fopen(“test.txt”, “w”);//以可写的方式打开一个文件,如果不存在就创建一个同名文件
aert(fp);//所以这里不会出错
fclose(fp);
fp = fopen(“noexitfile.txt”, “r”);//以只读的方式打开一个文件,如果不存在就打开文件失败
aert(fp);//所以这里出错
fclose(fp);//程序永远都执行不到这里来
return 0;} [root@localhost error_proce]# gcc badptr.c [root@localhost error_proce]#./a.out a.out: badptr.c:14: main: Aertion `fp' failed.已放弃
使用aert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。在调试结束后,可以通过在包含#include 的语句之前插入 #define NDEBUG 来禁用aert调用,示例代码如下: #include #define NDEBUG #include 用法总结与注意事项:
1)在函数开始处检验传入参数的合法性 如: int resetBufferSize(int nNewSize){ //功能:改变缓冲区大小, //参数:nNewSize 缓冲区新长度 //返回值:缓冲区当前长度
//说明:保持原信息内容不变
nNewSize= 0);aert(nNewSize
不好: aert(nOffset>=0 && nOffset+nSize= 0);aert(nOffset+nSize
i++;4)aert和后面的语句应空一行,以形成逻辑和视觉上的一致感 5)有的地方,aert不能代替条件过滤
1.7 itoa函数和atoi函数
函数名:atoi 功 能:把字符串转换成整型数 用 法:int atoi(const char *nptr);
函数说明: atoi()会扫描参数nptr字符串,检测到第一个数字或正负符号时开始做类型转换,之后检测到非数字或结束符 时停止转换,返回整型数。需要用到的头文件: #include 程序例: 1)
#include #include
int main(void){ int n;char *str = “12345.67”;n = atoi(str);printf(“string = %s integer = %dn”, str, n);return 0;} 执行结果
string = 12345.67 integer = 12345
函数名: itoa
备注:该函数的头文件是#include 功 能:把整数转换为字符串
用 法:char *itoa(int value, char *string, int radix);详细解释:itoa是英文integer to array(将int整型数转化为一个字符串,并将值保存在数组string中)的缩写。参数:
value: 待转化的整数。
radix: 是基数的意思,即先将value转化为radix进制的数,范围介于2-36,比如10表示10进制,16表示16进制。
* string: 保存转换后得到的字符串。返回值:
char * : 指向生成的字符串,同*string。atoi和itoa的示范代码如下:
#include #include void main(void){
char *s;int ix;
char buffer[20];
int i = 3445;
long l =-344115L;
unsigned long ul = 1234567890UL;
s = “-9885 pigs”;
/* Test of atoi */
ix = atoi(s);
printf(“atoi test: ASCII string: %sttinteger: %dn”, s, ix);
_itoa(i, buffer, 10);
printf(“String of integer %d(radix 10): %sn”, i, buffer);
_itoa(i, buffer, 16);
printf(“String of integer %d(radix 16): 0x%sn”, i, buffer);
_itoa(i, buffer, 2);
printf(“String of integer %d(radix 2): %sn”, i, buffer);
_ltoa(l, buffer, 16);
printf(“String of long int %ld(radix 16): 0x%sn”, l, buffer);
_ultoa(ul, buffer, 16);
printf(“String of unsigned long %lu(radix 16): 0x%sn”, ul,buffer);} 输出结果:
atoi test: ASCII string:-9885 pigs
integer:-9885 String of integer 3445(radix 10): 3445 String of integer 3445(radix 16): 0xd75 String of integer 3445(radix 2): 110101110101 String of long int-344115(radix 16): 0xfffabfcd String of unsigned long 1234567890(radix 16): 0x499602d2
1.8 strcmp函数实现
功 能: 串比较
用 法: int strcmp(char *str1, char *str2);
#include #include using namespace std;
int MyStrcmp(const char *str1,const char *str2)//错误 {
aert((str1!=NULL)&&(str2!=NULL));
for(;(*str1!=' ')&&(*str2!=' ');str1++,str2++)
{
if(*str1>*str2)
return 1;
else
return-1;
}
return 0;}
int my_strcmp(const char *str1,const char *str2)//正确 {
aert((str1!=NULL)&&(str2!=NULL));for(;(*str1!=' ')&&(*str2!=' ');str1++,str2++){
if(*str1>*str2)return 1;if(*str1
} } return-1;if((*str1==' ')&&(*str2!=' '))return-1;else if((*str1!=' ')&&(*str2==' '))return 1;return 0;else
int main(){
char *string1=“hanli”;
char *string2=“hanlihaha”;//-1 // char *string1=“”;// char *string2=“”;//0
cout
return 0;}
1.9 strcpy函数实现
原函数作用:拷贝一个字符串到另一个
#include #include using namespace std;
char *MyStrcpy(char *strDest, const char *strSrc)//程序员面试宝典P205 {
aert((strDest!=NULL)&&(strSrc!=NULL));
char *strDestCopy=strDest;
while((*strDest++=*strSrc++)!=' ')
NULL;
return strDestCopy;}
我的修改
char *MyStrcpy(char *strDest, const char *strSrc)//有错吗? {
aert((strDest!=NULL)&&(strSrc!=NULL));
char *strDestCopy=strDest;
while((*strDestCopy ++=*strSrc++)!=' ')
;
return strDest;}
int main(void){
char *str1=“abc”;
char str2[20];
cout
return 0;}
1.10 memcpy函数实现
功 能: 从源source中拷贝n个字节到目标destin中 #include #include using namespace std;
void *MyMemcpy(void *memDest, const void *memSrc, size_t size){
aert((memDest!=NULL)&&(memSrc!=NULL));
char *tempDest = static_cast(memDest);
const char *tempSrc = static_cast(memSrc);/*当目标地址比较大,且源地址和目标地址有部分空间重合时,需要从最大值读取,使目标地址最后能够存储源地址的所有数据*/
if((tempDest>tempSrc)&&(tempDest
{
for(size_t i=size-1;i!=-1;--i)
tempDest[i]=tempSrc[i];
} /*其它情况都可以按照从小到大读取*/
else
{
for(size_t i=0;i
tempDest[i]=tempSrc[i];
}
return memDest;}
int main(){
char strSrc[]=“12345”;
char strDest[20];
MyMemcpy(strDest,strSrc,4);
strDest[4]=' ';//以' '结束,勿漏!
cout
return 0;}
1.11 memcpy和memmove函数的实现
/*
* 函数名: memcpy
* 功
能: 从源source中拷贝n个字节到目标destin中
* 用
法: void *memcpy(void* destin, const void* source, size_t n);
* 说
明: 自己实现此库函数 */
#include
//#include //memcpy库函数头文件 #include
//getch头文件 #include //aert头文件
typedef unsigned char byte;//typedef unsigned int size_t;/* memcpy自定义函数 */ //src要保留
void* memcpy(void* dst,const void* src,size_t count){
char* pbTo =(char*)dst;
char* pbFrom =(char*)src;
aert(dst!= NULL && src!= NULL);//不能存在空指针
aert(pbTo >= pbFrom+count || pbFrom >= pbTo + count);//防止内存重叠
//aert(pbTo >= pbFrom+count&& pbTo= pbTo + count&& pbFrom
while(count--> 0)
{
*pbTo++ = *pbFrom++;
}
return dst;} /* memmove自定义函数 */ //src可以不保留
char *_memmove(char* dest, const char *src, size_t len){
aert(src!= 0 && src!= 0);
if(dest
{
char *p = dest;
for(size_t i = 0;i
*p++ = *src++;
}
else if(dest > src)
{
char *p = dest + len1;
for(size_t i = len-1;i >= 0;i--)
*p--= *src--;
}
return dest;}
void* memmove(void* dst,const void* src,size_t count){
char* pbTo =(char*)dst;
char* pbFrom =(char*)src;
aert(dst!= NULL && src!= NULL);//不能存在空指针
if(dst = pbFrom + count)//没有overlap的情况,直接拷贝
{
while(count--> 0)
{
*pbTo++ = *pbFrom++;
}
}
else
{
pbTo = pbTo + count-1;//overlap的情况,从高位地址向低位拷贝
pbFrom = pbFrom + count-1;
while(count--> 0)
{
*pbTo--= *pbFrom--;
}
}
return dst;} 1.12 strcat函数实现
功 能: 字符串拼接函数
#include #include using namespace std;
char* MyStrcat(char *strDest,const char *strSrc)//copy strStr to the end of strDest {
aert((strDest!=NULL)&&(strSrc!=NULL));
char *strDestCopy=strDest;
strDest=strDest+strlen(strDest);
while(*strSrc!=' ')
{
*strDest++=*strSrc++;
}
return strDestCopy;} int main(){
char string1[100]=“hanli”;
char *string2=“yuanlin”;
cout
return 0;}
1.13 使用库函数atoi,将char *→int #include //#include//not neceary!using namespace std;int main(){
int number;
char str[10]=“12345”;
number=atoi(str);//const char *str
cout
return 0;}
1.14 使用库函数itoa,将int→char * #include //#include//not neceary!using namespace std;int main(){
int number=12345;
char str[10];
itoa(number,str,10);//int value,char *str, int radix
cout
return 0;}
1.15 不使用库函数,将int→char * #include #include using namespace std;
void MyItoa(int value, char *str){
aert((value>=0)&&(str!=NULL));
char temp[10];
int i=0,j=0;
while(value)
{
temp[i++]=value%10 + '0';//整数加'0'就会隐性转化成char类型的数
value=value/10;
}
i--;
while(i>=0)
str[j++] = temp[i--];
str[j]=' ';//以' '结束,勿漏!}
int main(){
int number;
char str[10];
cout
cin>>number;
MyItoa(number,str);
cout
return 0;}
1.16 不使用库函数,将char *→int #include using namespace std;
int MyAtoi(const char *str){
int number=0;
const char *ptr=str;
if((*str=='+')||(*str=='-'))//如果第一位为符号位
str++;
while(*str!=' ')
{
if((*str'9'))//如果不是数字
break;
number=number*10+(*str-'0');//数字转换为字符
str++;
}
if(*ptr=='-')//如果有符号位,且为'-'
number=-number;
return number;}
int main(){
int number;
char str[10]=“12345”;
number=MyAtoi(str);
cout
return 0;}
1.17 求两个整数的最大公约数
#include #include using namespace std;
int GetGcd(unsigned long int a,unsigned long int b){
aert((a>0)&&(b>0));
unsigned long int temp;
while(a%b!= 0)
{
temp=a%b;
a=b;
b=temp;
}
return b;}
int main(){
unsigned long int x,y;
unsigned long int gcd;
cout
cin>>a>>b;
gcd=GetGcd(x,y);
cout
return 0;}
1.18 Little_endian or Big_endian //Little_endian: CPU对操作数的存储方式是低字节在低地址;(Intelx86)//Big_endian :CPU对操作数的存储方式是低字节在高地址; #include using namespace std;
int CheckCPU(){
union w
{
int a;
char b;
}c;
c.a=1;
return(c.b==1);//Little_endian(==1)}
int main(){
int temp;
temp=CheckCPU();
if(temp)
cout
else
cout
return 0;}
字节序(Endian),大端(Big-Endian),小端(Little-Endian)
在各种计算机体系结构中,对于字节、字等的存储机制有所不同,因而引发了计算机通信领域中一个很重要的问题,即通信双方交流的信息单元(比特、字节、字、双字等等)应该以什么样的顺序进行传送。如果不达成一致的规则,通信双方将无法进行正确的编/译码从而导致通信失败。目前在各种体系的计算机中通常采用的字节存储机制主要有两种:
big-edian和little-endian。字节顺序 Endian 现代的计算机系统一般采用字节(Octet, 8 bit Byte)作为逻辑寻址单位。当物理单位的长度大于1个字节时,就要区分字节顺序(Byte Order, or Endianne)。常见的字节顺序有两种:Big Endian(High-byte first)和Little Endian(Low-byte first),这就是表2.1中的BE和LE。Intel X86平台采用Little Endian,而PowerPC处理器则采用了Big Endian。举例来说,整型数字$1234ABCD存储的时候就会有两种方式:
大端Big-Endian 低地址存放最高有效位(MSB),既高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
计算机体系结构中一种描述多字节存储顺序的术语,在这种机制中最高有效位(MSB)存放在最低端的地址上。采用这种机制的处理器有IBM3700系列、PDP-
10、Mortolora微处理器系列和绝大多数的RISC处理器。小端Little-Endian
低地址存放最低有效位(LSB),既低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
计算机体系结构中一种描述多字节存储顺序的术语,在这种机制中最不重要字节(LSB)存放在最低端的地址上。采用这种机制的处理器有PDP-
11、VAX、Intel系列微处理器和一些网络通信设备。该术语除了描述多字节存储顺序外还常常用来描述一个字节中各个比特的排放次序。
中端 Middle-Endian 除了big-endian和little-endian之外的多字节存储顺序就是middle-endian,比如以4个字节为例:象以3-4-1-2或者2-1-4-3这样的顺序存储的就是middle-endian。这种存储顺序偶尔会在一些小型机体系中的十进制数的压缩格式中出现。
网络字节序 Network Order TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序。
主机序 Host Orader 它遵循Little-Endian规则。所以当两台主机之间要通过TCP/IP协议进行通信的时候就需要调用相应的函数进行主机序(Little-Endian)和网络序(Big-Endian)的转换。
C++怎样判别大端小端 使用宏的方法: const int endian = 1;#define is_bigendian()((*(char*)&endian)== 0)#define is_littlendbian()((*(char*)&endian)== 1)方法二: bool IsLittleEndian(){ union
{
long val;char Char[sizeof(long)];}u;//1-小端(Intel);0-大端(Motor)u.val = 1;
if(u.Char[0] == 1){ //小端 return true;}
else if(u.Char[sizeof(long)-1] == 1){ // 大端
return false;
}
throw(“Unknown!”);}
小知识
Java使用的是Big-Endian。
1.19 sizeof与strlen的区别
(1)sizeof是运算符,strlen是函数
(2)sizeof可以用类型做参数;strlen只能用char *做参数,且必须是以' '结尾(3)sizeof大多在编译时已计算出结果;strlen的结果要在运行的时候才能计算出来
即:sizeof是计算范围有多大;strlen是计算' '之前有多少
1.20 实现String类的BIG_FOUR //构造函数
String::String(const char *str){
if(str==NULL)
{
m_data=new char[1];
*m_data=' ';
}
else
{
int length=strlen(str);
m_data=new char[length+1];
strcpy(m_data,str);
} } //析构函数
String::~String(void){
dalete [] m_data;} //拷贝构造函数
String::String(const String &other){
int length=strlen(other.m_data);
m_data=new char[length+1];
ctrcpy(m_data,other.m_data);} //赋值函数
String &String::operator=(const String&other){
if(this!=&other)
{
char *temp=new char[strlen(other.m_data)+1];
str(temp,other.m_data);
delete [] m_data;
m_data=temp;
}
return *this;}
1.21 struct和union的区别
首先看看union,在c++中,union可能没有多大用处,在c语言中,可能我们要借助其完成很多巧妙的设计,下面是其一个完整的定义:
union UTest {
double dlOne;
char chOne;
byte bArray[4];};好了,看到上面的定义,很像struct的定义,但是对于union来说,有几点是值得注意的:不能直接对其进行初始化;某个时候只能使用其中的一个元素;最后一点也是最重要的一点就是内存共享,分配给union内存的Size是其中Size最大的那个元素的Size。说到这里,既然union最重要的是内存共享,那么我们做如下定义:union UTest tEle;然后赋值:tEle.dlOne = 2.0f;现在是dlOne可用,下一步:tEle.chOne = 'A';到这里dlOne失去了其意义,chOne变得可用。
然后,我们再来看看Struct,在struct中每一个元素都是分配内存的,而且都是有单独意义的,也就是说对一个变量的赋值并不影响其它变量的取值。到这里,各位应该明白这两者之间的区别了吧,事实上我个人认为,它们最主要的区别是在内存的分配和使用上。知道这一点,一切也就不难理解了。
最后,在使用union的时候,可能有时候我们会来用其来对字节流进行分解和重组,这样使用的时候一定要注意各种内存对数据的存储,比如Intel是按高高低低的原则存储的,有些则是相反的。因此,这点因该值得注意,否则得到的可能和预期的结果不一样。
举例:使用union结构输出主机字节序 int main(void){
union
{
short s;
char c[sizeof(shor)];
}un;
un.s = 0x0102;
printf(“%s:”, CPU_VENDOR_OS);
if(2==sizeof(short))
{
if(1==un.c[0]&& 2==un.c[1])
{
printf(“big-endiann”);
}
else if(2==un.c[0] && 1==un.c[1])
{
printf(“little-endiann”);
}
else
{
printf(“unknownn”);
}
}
else
{
printf(“sizeof(short)= %dn”, sizeof(short));
}
return 0;}
1.22 char字符变量与int整型数据
字符型变量用来存放字符变量,请注意只能放一个字符,将一个字符常量放在字符变量中,实际上并不是把该字符本身放在内存单元中去,而是将该字符对应的ASCII码放在存储单元中,即在内存中,字符数据是以ASCII码存储,存储形式就与整数的存储形式类似。ASCII码表如下示:
ASCII码表
由图可知,字符数据类型只能存储一个字节,即0~255之间的内的整数。有些系统将字符变量中的最高位做为符号位,也就是将字符处理成带符号的整数,即signed char型,它的取值范围为-128~127。如果使用ASCII码为0~127间的字符,由于字节最高位为0,因此用%d输出时是一个正整数,如果使用ASCII码为128~255间的字符,由于字节最高位为1,因此用%d输出时是一个负整数。
char a = 256;int b = a;printf(“%dn”,b);char c = 130;//输出结果为0 printf(“%dn”,c);//输出结果为-126
1.23 字,字节,字符,比特
1bit = 1b = 1比特 = 二进制的一位 1Byte = 1B = 1字节 = 8b 1英文字母占用1个字节 1个汉字占用2个字节 c和c++语言中 char = 8b = 1B int = 32b = 4B float = 32b = 4B double = 64b = 8B 原码转补码:取反再加1 补码转原码:减1再取反
“比特”(Bit)
一个比特只能拥有一个值,不是0就是1,所以如果我给你一个值0,你可以说它就是一个比特,如果我给你两个(00),你就可以说它们是两个比特了。
现在,如果你将八个0或者1组合在一起,例如0110 1010(在中间加一个空格是为了看起来清晰明了),你就可以说它们是八个比特或者说一个字节。好,这就对了,八比特就等于一字节,而不管它们都是全是0、全是1或者是由若干0和若干1混合而成。将这些字节加起来,到了1024个字节的时候,就获得了一个千字(Kbyte)了,为什么是1024而不是1000呢?这是由二进制的进位方式造成的,如果你学过数学,你就会知道上述结果是正确的。
容易混淆的概念 字
在计算机中,一串数码作为一个整体来处理或运算的,称为一个计算机字,简称字。字通常分为若干个字节(每个字节一般是8位)。在存储器中,通常每个单元存储一个字,因此每个字都是可以寻址的。字的长度用位数来表示。
在计算机的运算器、控制器中,通常都是以字为单位进行传送的。字出现在不同的地址其含义是不相同。例如,送往控制器去的字是指令,而送往运算器去的字就是一个数。
字长
计算机的每个字所包含的位数称为字长。根据计算机的不同,字长有固定的和可变的两种。固定字长,即字长度不论什么情况都是固定不变的;可变字长,则在一定范围内,其长度是可变的。
计算的字长是指它一次可处理的二进制数字的数目。计算机处理数据的速率,自然和它一次能加工的位数以及进行运算的快慢有关。如果一台计算机的字长是另一台计算机的两倍,即使两台计算机的速度相同,在相同的时间内,前者能做的工作是后者的两倍。一般地,大型计算机的字长为32―64位,小型计算机为12―32位,而微型计算机为4一16位。字长是衡量计算机性能的一个重要因素。
字节
字节是指一小组相邻的二进制数码。通常是8位作为一个字节。它是构成信息的一个小单位,并作为一个整体来参加操作,比字小,是构成字的单位。
在微型计算机中,通常用多少字节来表示存储器的存储容量。
字符,字节,字符串
理解编码的关键,是要把字符的概念和字节的概念理解准确。这两个概念容易混淆,我们在此做一下区分:
概念描述 举例
字符 人们使用的记号,抽象意义上的一个符号。'1', '中', 'a', '$', '¥', „„
字节 计算机中存储数据的单元,一个8位的二进制数,是一个很具体的存储空间。0x01, 0x45, 0xFA, „„
字符串
在内存中,如果“字符”是以ANSI编码形式存在的,一个字符可能使用一个字节或多个字节来表示,那么我们称这种字符串为 ANSI 字符串或者多字节字符串。如,“中文123”(占7字节)。
字符集和代码页
对于ANSI编码方式,存在不同的字符集(Charset)。同样的字节序列,在不同的字符集下表示的字符不一样。要正确解析一个ANSI字符串,还要选择正确的字符集,否则就可能导致所谓的乱码现象。不同语言版本的操作系统,都有一个默认的字符集。在不指定字符集的情况下,系统会使用此字符集来解析 ANSI 字符串。也就是说,如果我们在简体中文版的Windows下打开了一个由日文操作系统保存的 ANSI 文本文件(仅包含 ANSI 字符串的文本文件),我们看到的将是乱码。但是,如果我们使用Visual Studio之类的带编码选择的文本编辑器打开此文件,并且选择正确的字符集,我们将可以看到它的原貌。注意:简体中文字符集中的繁体字和繁体中文字符集中的繁体字,编码不一定相同(事实证明,似乎是完全不同)。
每个字符集都有一个唯一的编号,称为代码页(Code Page)。简体中文(GB2312)的代码页为936,而系统默认字符集的代码页为0,它表示根据系统的语言设置来选择一个合适的字符集。
UNICODE 字符串在内存中,如果“字符”是以在Unicode中的序号存在的,那么我们称这种字符串为Unicode字符串或者宽字节字符串。在Unicode中,每个字符都占两个字节。如,“中文123”(占10字节)。
Unicode和ANSI的区别就相当于输入法内的“全角”和“半角”的区别。
由于不同 ANSI 编码所规定的标准是不相同的(字符集不同),因此,对于一个给定的多字节字符串,我们必须知道它采用的是哪一种字符集则,才能够知道它包含了哪些“字符”。而对于 UNICODE 字符串来说,不管在什么环境下,它所代表的“字符”内容总是不变的。Unicode 有着统一的标准,它定义了世界上绝大多数的字符的编码,使得拉丁文、数字、简体中文、繁体中文、日文等都能以同一种编码方式保存。
ANSI字符串:(多字节字符)
在内存中,如果“字符”是以 ANSI 编码形式存在的,一个字符可能使用一个字节或多个字节来表示,那么我们称这种字符串为 ANSI 字符串或者多字节字符串。“中文123”(占7字节)
UNICODE字符串:(宽字符)
在内存中,如果“字符”是以在 UNICODE 中的序号存在的,那么我们称这种字符串为 UNICODE 字符串或者宽字节字符串。L“中文123”(占10字节)
由于不同 ANSI 编码所规定的标准是不相同的,因此,对于一个给定的多字节字符串,我们必须知道它采用的是哪一种编码规则,才能够知道它包含了哪些“字符”。而对于 UNICODE 字符串来说,不管在什么环境下,它所代表的“字符”内容总是不变的。
1.24 空格、空字符、字符数组结束符的区别
空格符号和空字符是不一样的,在ASCII里面,空格(space)符号的ASCII码是0x20,而空字符是0x0,2个是完全不一样的2个字符呵呵.空字符一般来描述一个字符串的结尾,其实是控制符的一种,但不能理解为没有字符,应该理解为代表什么都没有的字符.好比回车0x0A和换行0x0D虽然不显示,但是也是控制字符的一种.(这些字符以前是用于打印机的,所以很多都没有用了)
字符串的概念:在C语言中,字符串是指由若干个有效字符(其中包括字母、数字、转义字符、等)组成的系列,以' '作为字符串结束标志。' '是一个“空操作”字符,它不做任何操作,只是一个标志。' '的代码值为0,它不计入串的长度。
还有这里需要注意下在接受字符串的时候,如果用scanf来接收的话,字符串中不能含有空格,否则将以空格作为串的结束符。如果你键入得是harry potter 那么实际上scanf只能获取harry这个单词。所以要接收空格的话可以用gets()这个函数。
补充:C语言中字符串结束符' '就是0.》》' '就是8位的00000000,因为字符类型中并没有对应的这个字符,所以这么写。在数值类型里就代表数字0。补充:这个你要去学下基础的,数值类型存储时,最高位决定正负号,其他位都为0可不就是0了么? ' '是转译字符,意思是告诉程序,这不是字符0,我要的是数字0的2进制直接放进来,因为acsii码的0可不是00000000