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

例如,在下面的源程序中“""”之内的“你”、“好”、“,”、“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.

时间: 2024-09-13 05:22:33

C语言中的BYTE和char深入解析_C 语言的相关文章

C语言中const,volatile,restrict的用法总结_C 语言

1. const 变量声明中带有关键词const,意味着不能通过赋值,增量或减量来修改该变量的值,这是显而易见的一点.指针使用const则要稍微复杂点,因为不得不把让指针本身成为const和指针指向的值成为const区别开来.下面的声明表示pf指向的值必须是不变的 constfloat *pf:而pf则是可变的,它可以指向另外一个const或非const值:相反,下面的声明说明pf是不能改变的,而pf所指向的值则是可以改变的: float* const pf: 最后,当然可以有既不能改变指针的值

简单比较C语言中的execl()函数与execlp()函数_C 语言

C语言execl()函数:执行文件函数头文件: #include <unistd.h> 定义函数: int execl(const char * path, const char * arg, ...); 函数说明:execl()用来执行参数path 字符串所代表的文件路径, 接下来的参数代表执行该文件时传递过去的argv(0), argv[1], ..., 最后一个参数必须用空指针(NULL)作结束. 返回值:如果执行成功则函数不会返回, 执行失败则直接返回-1, 失败原因存于errno 中

C语言中sscanf()函数的字符串格式化用法_C 语言

介绍      sscanf()为C语言标准库函数,用于从指定字符串中读入与指定格式相符的数据.函数原型声明在stdio.h头文件中: int sscanf(const char *str, const char *format, ...);      该函数根据参数format(格式化字符串)来转换参数str指向的字符串,转换后的结果存于对应的可变参数内.其返回值为按照指定格式转换符成功读入且赋值的可变参数数目(若发生匹配错误而部分成功,该数目会小于指定的参数数目,甚至为0).若首次成功转换或

详细对比C语言中的chmod()函数和fchmod()函数_C 语言

C语言chmod()函数:修改文件权限头文件: #include <sys/types.h> #include <sys/stat.h> 定义函数: int chmod(const char * path, mode_t mode); 函数说明:chmod()会依参数mode 权限来更改参数path 指定文件的权限. 参数 mode 有下列数种组合: 1.S_ISUID 04000 文件的 (set user-id on execution)位 2.S_ISGID 02000 文件

简单介绍C语言中的umask()函数和truncate()函数_C 语言

C语言umask()函数:设置建立新文件时的权限遮罩头文件: #include <sys/types.h> #include <sys/stat.h> 定义函数: mode_t umask(mode_t mask); 函数说明:umask()会将系统umask值设成参数mask&0777后的值, 然后将先前的umask值返回.在使用open()建立新文件时, 该参数mode 并非真正建立文件的权限, 而是(mode&~umask)的权限值. 例如: 在建立文件时指定

详解C语言中的fopen()函数和fdopen()函数_C 语言

C语言fopen()函数:打开一个文件并返回文件指针头文件: #include <stdio.h> fopen()是一个常用的函数,用来以指定的方式打开文件,其原型为:   FILE * fopen(const char * path, const char * mode); [参数]path为包含了路径的文件名,mode为文件打开方式. mode有以下几种方式: 在POSIX 系统,包含Linux 下都会忽略 b 字符.由fopen()所建立的新文件会具有S_IRUSR|S_IWUSR|S_

详解C语言中的getgrgid()函数和getgrnam()函数_C 语言

C语言getgrgid()函数:从组文件中取得指定gid的数据 头文件: #include <grp.h> #include <sys/types.h> 定义函数: strcut group * getgrgid(gid_t gid); 函数说明:getgrgid()用来依参数gid 指定的组识别码逐一搜索组文件, 找到时便将该组的数据以group 结构返回. 返回值:返回 group 结构数据, 如果返回NULL 则表示已无数据, 或有错误发生. 范例 /* 取得gid=3 的组

简要对比C语言中的truncate()函数与ftruncate()函数_C 语言

C语言truncate()函数:改变文件大小头文件: #include <unistd.h> 定义函数: int truncate(const char * path, off_t length); 函数说明:truncate()会将参数path 指定的文件大小改为参数length 指定的大小. 如果原来的文件大小比参数length 大, 则超过的部分会被删去. 返回值:执行成功则返回0, 失败返回-1, 错误原因存于errno. 错误代码: 1.EACCESS 参数path 所指定的文件无法

C语言中的sscanf()函数使用详解_C 语言

sscanf() - 从一个字符串中读进与指定格式相符的数据. 函数原型: Int sscanf( string str, string fmt, mixed var1, mixed var2 ... ); int scanf( const char *format [,argument]... ); 说明: sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源. 其中的format可以是一个或多个 {%[*] [width] [{h |