C语言中的BYTE和char深入解析

例如,在下面的源程序中“""”之内的“你”、“好”、“,”、“C”、“!”、“\n”就属于程序要处理的字符。


代码如下:

#include <stdio.h>
int main(void)
{
      printf("你好,C!\n");  
      return 0;
}

该源程序中的其他字符则属于书写源程序的字符,这其中也可能包含并没有明显显示出来的字符,例如空格字符(space character)、水平制表符(horizontal tab)、垂直制表符(vertical tab)和换页符(form feed)。

从某种意义上来说,编辑/编译器是一种接受字符输入,输出可执行文件的软件,由它产生可执行文件经过加载成为内存中的程序,这个程序通常也不可避免地要处理字符。

编辑/编译器与它生产出的应用程序并不一定运行在同一个环境中,这就意味着两者可能要各自处理不同的字符集合。

编辑/编译器所要处理的字符就是书写C语言源程序所用的字符,这种字符的集合叫源字符集(sourcecharacter set)。而应用程序要处理的字符所构成的集合叫执行字符集(execution character set)。

对于多数C语言学习者来说,由于编辑/编译环境与应用程序运行环境是重合的,可能意识不到源字符集与执行字符集之间的区别。

•源字符集(source character set)
源字符集中的字符就是编写C语言源程序的字符,也就是C语言要求编辑/编译器所运行的环境所提供的字符。这套字符由这几部分组成:基本字符集(basic character set)、表示换行的字符(new-line character)和扩展字符(extended characters)。

基本字符集(basic character set)包括:

A B C D E F G H I J K L M

N O P Q R S T U V W X Y Z

a b c d e f g h i j k l m

n o p q r s t u v w x y z

0 1 2 3 4 5 6 7 8 9

! " # % & ' ( ) * + , - . / :

; < = > ? [ \ ] ^ _ { | } ~

空格(space character)

控制符:horizontal tab, vertical tab, form feed

一共是95个。这就是C语言对编辑/编译器运行环境的最基本的要求,言外之意就是只要编辑/编译器所运行环境提供这95个字符就可以编写C语言程序了。事实上C语言源程序也“主要”地由这95个字符组成。

此外,C语言还要求在编辑/编译器运行的环境中,0~9这十个字符的编号(编码)必须是连续的。

遗憾的是,有些环境无法全部提供这95个字符。例如,据说有些国家的键盘上压根就没有“[”这个键。

由于存在这种情况,所以C语言也容许用所谓的三字符序列(trigraph)来表示那些环境不提供的字符。比如用“??<”表示“{”,用“??>”表示“}”。下面的代码尽管看起来有些怪异,然而依然是合法的C程序。


代码如下:

#include<stdio.h>
int main(void)
 ??<
      printf("你好,C!\n");  
      return 0;
 ??>

编译器也可以对基本字符集自行进行扩展,这就是所谓的扩展字符(extended characters)。前面代码中的“你”、“好”就属于扩展字符。这些扩展字符只能出现在标识符、字符常量、字符串字面量、头名(header name)、注释以及某些预处理单词(preprocessing token that is never converted to a token)中。代码的其他其他部分出现扩展字符则是一种未定义行为。

扩展字符的值是由具体的编译器定义的。源程序可以使用的所有字符的集合叫做扩展字符集(extended character set)。

•执行字符集
应用程序运行的环境中的字符集(the execution character set)也是一种扩展字符集(extended character set)。

其中也必须包括前面提到的源字符集中的那95个基本字符集,0~9这十个字符的编码也必须是连续的。

特别需要注意的是,C语言并没有要求执行环境中的基本字符集和编辑/编译环境中的基本字符集具有相同的编码方式,尽管这两个基本字符集的“符”是相同的。

执行环境中必须提供的字符还有alert,backspace,carriage return,new line以及一个各位都为0的字符(null character)。

执行环境中程序可以处理的其他字符也被叫做扩展字符(extended characters),这些扩展字符与基本字符集以及alert,backspace,carriage return,new line和null character共同构成了执行环境中的扩展字符集(extended character set),或称之为执行字符集(the execution character set)。

对于执行环境来说,扩展字符(extended characters)同样是由编译器自行定义的。

•C语言中的Byte
C语言中的Byte,如同int等类型类似,同样不是一个确定长度的位组。C语言只是要求Byte能放得下执行环境中和编辑/编译环境中基本字符集的编码。这样在某些编译器中C语言中的Byte是9位就不难理解了,这并不违背C语言的基本定义。

同样的道理,如果在编辑/编译环境中,基本字符集的编码是8位,而在运行环境中基本字符集的编码是16位的话,那么Byte的大小显然就必须至少为16位。

由此可见,在C语境中的Byte并非是平时普遍认为的octet(8位组)。

•C语言中的char数据类型
C语言中的char数据类型是一种整数类型(integer type),它的大小被定义为1个Byte。亦即

sizeof (char)  ≡ 1

若需要知道某个具体编译器的Byte究竟是多少位,可以查看编译器提供的limits.h。其中定义的符号常量CHAR_BIT就是char类型的位数,也就是Byte的位数。

补充:

C标准的矛盾?

"addressable unit of data large enough to hold any member of the basic character set of the execution environment" (clause 3.6 of the C standard)

可是在5.2.1-3中

The representation of each member of the source and execution basic character sets shall fit in a byte.

(0)

相关推荐

  • c语言字符数组与字符串的使用详解

    1.字符数组的定义与初始化字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素.char str[10]={ 'I',' ','a','m',' ','h','a','p','p','y'};即把10个字符分别赋给str[0]到str[9]10个元素如果花括号中提供的字符个数大于数组长度,则按语法错误处理:若小于数组长度,则只将这些字符数组中前面那些元素,其余的元素自动定为空字符(即 '\0' ). 2.字符数组与字符串在c语言中,将字符串作为字符数组来处理.(c++中不是)在实际应用

  • C#语言中字符类char的使用方法(总结)

    char类在C#中表示一个unicode字符,正是这些unicode字符构成了字符串.unicode字符是目前计算机中通用的字符编码,它为针对不同语言中的每个字符设定了统一的二进制编码,用于满足跨越语言.跨平台的文本转换.处理要求.char的定义非常简单,如下: char ch1='z': 但是,char只能定义一个unicode字符. 下面是char类常见的使用方法及说明 iscontrol   指示指定的unicode字符是否属于控制字符类别 isdigit  指示某个unicode字符是否

  • C语言中的字符(char)详细讲解

    1.字符型(char)简介 字符型(char)用于储存字符(character),如英文字母或标点. 严格来说,char 其实也是整数类型(integer type),因为 char 类型储存的实际上是整数,而不是字符. 计算机使用特定的整数编码来表示特定的字符. 2. 声明字符型变量 3. 字符常量与初始化 实例: 用 char 类型来专门表示一个字符,例如: char a='1'; char b='$'; char c='X'; char d=' '; // 空格也是一个字符 char e=

  • string与char*转换的使用详解

    复制代码 代码如下: //string --> const char string str2ch: str2ch.c_str(); //============================= //string --> char * //先转为 const char , 然后 转char * char TargetFile[strlen(TorrentFileNameDown.c_str())];    strcpy(TargetFile,TorrentFileNameDown.c_str(

  • C语言中的BYTE和char深入解析

    例如,在下面的源程序中""""之内的"你"."好".","."C"."!"."\n"就属于程序要处理的字符. 复制代码 代码如下: #include <stdio.h>int main(void){      printf("你好,C!\n");         return 0;} 该源程序中的其他字符则属于书写源

  • C语言中getchar的用法以及实例解析

    目录 getchar解析 一.getchar的返回类型及作用机制 二.根据一段代码初步了解 三.实例(“输入密码”)进一步了解 1.代码达不到理想效果 2.输入的密码中有空格 总结 getchar解析 一.getchar的返回类型及作用机制 getchar——读取字符的函数 int getchar(void) 返回类型为int,参数为void. 有人可能会有疑惑,getchar既然是读取字符的,为什么返回类型是int呢? 1.getchar其实返回的是字符的ASCII码值(整数). 2.getc

  • go语言中int和byte转换方式

    主机字节序 主机字节序模式有两种,大端数据模式和小端数据模式,在网络编程中应注意这两者的区别,以保证数据处理的正确性:例如网络的数据是以大端数据模式进行交互,而我们的主机大多数以小端模式处理,如果不转换,数据会混乱 参考 :一般来说,两个主机在网络通信需要经过如下转换过程:主机字节序 -> 网络字节序 -> 主机字节序 大端小端区别 大端模式:Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端 低地址 --------------------> 高地址 高

  • C语言中 int main(int argc,char *argv[])的两个参数详解

    C语言中 int main(int argc,char *argv[])的两个参数详解 argc是命令行总的参数个数: argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数.命令行后面跟的用户输入的参数. int main(int argc, char* argv[]) { int i; for (i = 0; i<argc; i++) cout<<argv[i]<<endl; cin>>i; return 0; } 执行时敲入 F:\MYDOCU

  • 详解C语言中Char型指针数组与字符数组的区别

    详解C语言中Char型指针数组与字符数组的区别 1.char 类型的指针数组:每个元素都指向一个字符串,指向可以改变 char *name[3] = { "abc", "def", "gbk" }; for(int i = 0 ; i < strlen(name); i ++){ printf("%s\n", *(name+i)); //printf("%s\n", name[i]); } //指向改

  • C语言中char*和char[]用法区别分析

    本文实例分析了C语言中char* 和 char []的区别.分享给大家供大家参考之用.具体分析如下: 一般来说,很多人会觉得这两个定义效果一样,其实差别很大.以下是个人的一些看法,有不正确的地方望指正. 本质上来说,char *s定义了一个char型的指针,它只知道所指向的内存单元,并不知道这个内存单元有多大,所以: 当char *s = "hello";后,不能使用s[0]='a':语句进行赋值.这是将提示内存不能为"written". 当用char s[]=&q

  • 详解C语言中的char数据类型及其与int类型的转换

    C语言中的char变量 char是C/C++整型数据中比较古怪的一个,其它的如int/long/short等不指定signed/unsigned时都默认是signed.虽然char在标准中是unsigned(因为char类型提出的初衷是用来表示ascii码,ascii码的范围是0~127),但实际情况中究竟是signed还是unsigned取决于编译器. 可通过下面程序判断编译器的默认char类型: void char_type() { char c=0xFF; if(c==-1) printf

  • 详解Go语言中for循环,break和continue的使用

    目录 基本语法 有始有终的条件循环 带条件的循环 无限循环 数组循环 使用计数器循环 利用range循环 Map循环 string的遍历 Break和Continue 基本语法 和C语言同源的语法格式,有始有终的循环,for init; condition; post { } 带条件的while循环,for condition { } 无限循环,for { } 有始有终的条件循环 sum := 0 for i := 0; i < 10; i++ { sum = sum + i } 注意:i变量在

  • 聊聊C语言中sizeof运算符的一个陷阱

    sizeof运算符通常用于获取变量或类型所占内存的大小(单位是字节) #include <stdio.h> struct D{ char a; int b; }; int main() { int a = 0; struct D d; printf("sizeof(a)=%ld\n", sizeof(a)); printf("sizeof(int)=%ld\n", sizeof(int)); printf("sizeof(d)=%ld\n&qu

  • C语言中printf()缓冲问题详解

    前言 缓冲区又称为缓存,它是内存空间的一部分.也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区. 缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区. 为什么要引入缓冲区 比如我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度. 又比如,

随机推荐