c语言中,用构造c语言数据类型型做一场有英雄属性的简单战斗,每回合怪物合英雄打斗掉血,有技能最好

C语言当中位段的使用
编辑:www.fx114.net
本篇文章主要介绍了"C语言当中位段的使用",主要涉及到C语言当中位段的使用方面的内容,对于C语言当中位段的使用感兴趣的同学可以参考一下。
C语言当中位段的使用
位段以位为单位定义结构体(或共用体)中成员所占存储空间的长度。&含有位段的结构体类型称为位段结构。
位段结构也是一种结构体类型,只不过其中含有以位为单位定义存储长度的整数类型位段成员。采用位段结构既节省存储空间,又可方便操作。
位段结构中位段的定义格式为:&&&&&&&& unsigned &成员名&:&二进制位数&例如:struct bytedata{unsigned a:2;&& /*位段a,占2位*/&unsigned:6;& /*无名位段,占6位,但不能访问*/&unsigned:0;&&&& /*无名位段,占0位,表下一位段从下一字边界开始*/&unsigned b:10;& /*位段b,占10位*/&&&&&&&&&& /*成员i,从下一字边界开始*/}
位段数据的引用:同结构体成员中的数据引用一样,但应注意位段的最大取值范围不要超出二进制位数定的范围,否则超出部分会丢弃。例如:data.a=2;&& 但& data.a=10;就超出范围(a占2位,最大3)
关于位段数据,注意以下几点:
(1)一个位段必须存储在同一存储单元(即字)之中,不能跨两个单元。如果其单元空间不够,则剩余空间不用,从下一个单元起存放该位段。(2)可以通过定义长度为0的位段的方式使下一位段从下一存储单元开始。(3)可以定义无名位段。(4)位段的长度不能大于存储单元的长度。(5)位段无地址,不能对位段进行取地址运算。(6)位段可以以%d,%o,%x格式输出。(7)位段若出现在表达式中,将被系统自动转换成整数。
C语言中的结构是有实现位段的能力的,噢!你问它到底是什么形式是吧?这个问题呆会给你答案。让我们先看看位段的作用:位段是在字段的声明后面加一个冒号以及一个表示字段位长的整数来实现的。这种用法又被就叫作&深入逻辑元件的编程&,如果你对系统编程感兴趣,那么这篇文章你就不应该错过!  我把使用位段的几个理由告诉大家:1、它能把长度为奇数的数据包装在一起,从而节省存储的空间;2、它可以很方便地访问一个整型值的部分内容。  首先我要提醒大家注意几点:1、位段成员只有三种类型:int ,unsigned int 和signed int这三种(当然了,int型位段是不是可以取负数不是我说了算的,因为这是和你的编译器来决定的。位段,位段,它是用来表示字段位长(bit)的,它只有整型值,不会有7.2这种float类型的,如果你说有,那你就等于承认了有7.2个人这个概念,当然也没有char这个类型的);2、成员名后面的一个冒号和一个整数,这个整数指定该位段的位长(bit);3、许多编译器把位段成员的字长限制在一个int的长度范围之内;4、位段成员在内存的实现是从左到右还是从右到左是由编译器来决定的,但二者皆对。  下面我们就来看看,它到底是什么东西(我先假定大家的机器字长为32位):  Struct WORD  {unsigned int chara: 6:unsigned int font : 7;unsigned int maxsize : 19;  };  Struct WORD  这一段是从我编写的一个文字格式化软件摘下来的,它最多可以容纳64(既我说的unsigned int chara :6; 它总共是6位)个不同的字符值,可以处理128(既unsigned int font : 7 ;既2的7次方)种不同的字体,和2的19次方的单位长度的字。大家都可以看到maxsize是19位,它是无法被一个short int 类型的值所容纳的,我们又可以看到其余的成员的长度比char还小,这就让我们想起让他们共享32位机器字长,这就避免用一个32位的整数来表示maxsize的位段。怎么样?还要注意的是刚才的那一段代码在16位字长的机器上是无法实现的,为什么?提醒你一下,看看上面提醒的第3点,你会明白的!你是不是发现这个东西没有用啊?如果你点头了,那你就错了!这么伟大的创造怎么会没有用呢(你对系统编程不感兴趣,相信你会改变这么一个观点的)?磁盘控制器大家应该知道吧?软驱与它的通信我们来看看是怎么实现的下面是一个磁盘控制器的寄存器:│&5&│&5&│&9&│&8&│&1&│&1&∣&1&∣&1&∣&1&∣  上面位段从左到右依次代表的含义为:5位的命令,5位的扇区,9位的磁道,8位的错误代码,1位的HEAD LOADED,1位的写保护,1位的DISK SPINNING,1位的错误判断符,还有1位的READY位。它要怎么来实现呢?你先自己写写看:  struct DISK_FORMAT  {   unsigned int command : 5;     unsigned sector : 5;   unsigned track : 9 ;   unsigned err_code : 8;   unsigned ishead_loaded : 1;   unsigned iswrit_protect : 1;   unsigned isdisk_spinning : 1;   unsigned iserr_ocur : 1;   undigned isready :1 ;  };   注:代码中除了第一行使用了unsigned int 来声明位段后就省去了int ,这是可行的,详见ANCI C标准。  如果我们要对044c18bfH的地址进行访问的话,那就这样:  #define DISK ((struct DISK_FORMAT *)0x044c18bf)  DISK-&sector=fst_  DISK-&track=fst_  DISK-&command=WRITE;  当然那些都是要宏定义的哦!  我们用位段来实现这一目的是很方便的,其实这也可以用移位或屏蔽来实现,你尝试过就知道哪个更方便了!  我们今天的话题就到这儿,如果诸位还有疑问,可e-mail给我:;  特别声明哦:不要把以上内容用于不法行为,否则后果自负。另外本文不可用于任何谋取商业利益的举动,否则同上!
C编译器对结构空间缺省的分配  在C语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如数组、结构、联合等等)的数据单元。在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间;各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间,见表1:
                       表1:Win32下的自然对界条件例如,下面的结构各成员空间分配情况如图1:struct test {char x1;short x2;float x3;char x4;};                   图1:缺省结构空间分配  结构的第一个成员x1,其偏移地址为0,占据了第1个字节。第二个成员x2为short类型,其起始地址必须2字节对界,因此,编译器在x2和x1之间填充了一个空字节。结构的第三个成员x3和第四个成员x4恰好落在其自然对界地址上,在它们前面不需要额外的填充字节。在test结构中,成员x3要求4字节对界,是该结构所有成员中要求的最大对界单元,因而test结构的自然对界条件为4字节,编译器在成员x4后面填充了3个空字节。整个结构所占据空间为12字节。
结构中的位段  所谓位段是以位为单位定义长度的结构体类型中的成员。编译器对结构中位段的分配遵从下面几点原则:? 对于长度为0的位段,其下一个位段从下一个存储单元开始存放:如:struct T {unsigned char a : 1;unsigned char b : 2;unsigned : 0;unsigned c : 3;};  结构T的成员a和b在一个存储单元中,c则在另一个存储单元中。  ? 一个位段必须存储在同一存储单元中,不能跨两个单元:如:struct T {unsigned char a : 4;unsigned char b : 6;};  结构T的成员a在一个存储单元中,b则在另一个存储单元中。
更改C编译器的缺省分配策略  一般地,可以通过下面的两种方法改变缺省的对界条件:  ? 使用伪指令#pragma pack ([n])  ? 在编译时使用命令行参数#pragma pack ([n])伪指令允许你选择编译器为数据分配空间所采取的对界策略,见表2:
                  表2:更改缺省对界条件  在Microsfot Visual C++中,命令行参数/Zp[n]可以改变缺省对界条件;在Borland C++ Builder中,命令行参数-a[n]可以改变缺省对界条件。n的含义和#pragma pack中的n相同。  例如,在使用了#pragma pack (1)伪指令后,test结构各成员的空间分配情况如图2所示:                 图2:使用#pragma pack (1)后的结构空间分配
  我们在日常编程工作中,特别是对一些网络事务的处理,经常会同其他人有着各种各样的协议:如我传给你20字节的头,前4个字节表示&&等等。很多人都是通过指针偏移的方法来得到各种信息,这样做,不仅编程复杂,而且一旦协议有变化,程序修改起来也比较麻烦。在了解了编译器对结构空间的分配原则之后,我们完全可以利用这一特性定义自己的协议结构,通过访问结构的成员来获取各种信息。这样做,不仅简化了编程,而且即使协议发生变化,我们也只需修改协议结构的定义即可,其它程序无需修改,省时省力。下面以TCP协议首部为例,说明如何定义协议结构。  TCP协议首部如图3所示:                图3:TCP首部其协议结构定义如下:struct TCPHEADER {short SrcP // 16位源端口号short DstP // 16位目的端口号int SerialNo; // 32位序列号int AckNo; // 32位确认号unsigned char HaderLen : 4; // 4位首部长度unsigned char Reserved1 : 4; // 保留6位中的4位unsigned char Reserved2 : 2; // 保留6位中的2位unsigned char URG : 1;unsigned char ACK : 1;unsigned char PSH : 1;unsigned char RST : 1;unsigned char SYN : 1;unsigned char FIN : 1;short WindowS // 16位窗口大小short TcpChkS // 16位TCP检验和short UrgentP // 16位紧急指针};其协议结构还可以定义为如下的形式:struct TCPHEADER {short SrcP // 16位源端口号short DstP // 16位目的端口号int SerialNo; // 32位序列号int AckNo; // 32位确认号unsigned char HaderLen : 4; // 4位首部长度unsigned char : 0; // 保留6位中的4位unsigned char Reserved : 2; // 保留6位中的2位unsigned char URG : 1;unsigned char ACK : 1;unsigned char PSH : 1;unsigned char RST : 1;unsigned char SYN : 1;unsigned char FIN : 1;short WindowS // 16位窗口大小short TcpChkS // 16位TCP检验和short UrgentP // 16位紧急指针
本文来自CSDN博客,转载请标明出处:
1.什么是位段
在前面各章中, 我们已经讨论过字节概念了。在大多数的计算机系统中, 一个字节是由八个更小的, 称作为位的单位组成的。位是比字节更小的单位。位只有两个值, 1 或 0 。因此, 存储在计算机存储器中的一个字节可以看成由八个二进制数字形成的串。例如, 一个存放值 36 的字节是八个二进制数字的串: 可以表示成 。 存入值24 的字节可以表示成 。有时, 我们希望不仅对字节进行操作, 也要能对位进行操作。例如, 用布尔真或假条件表示的标志, 在计算机中可用位来表示。但是, 说明一个用作标志的普通变量至少要用一个字节---8 位, 而在某些计算机系统中则可能是 16 位。 如果我们想在一个很大的表中存储很多标志, 那么 "被浪费" 的内存空间是很可观的。在 C 语言中, 一种方法是用叫做位段的构造类型来定义一个压缩信息的结构。
什么是位段呢? 位段是 C 语言特有的数据结构, 它允许我们定义一个由位组成的段, 并可为它赋以一个名字。
2.位段的用法
我们已经了解什么是位段了, 现在我们继续讨论位段的使用方法。先看一个例子: 我们需要用到五个变量。 假定, 其中三个用作标志, 称为 f1, f2 和 f3。第四个称为 type, 取值范围为 1 至 12。 最后一个变量称为 index, 值的范围为 0 至 500。通常, 我们用下面的语句来说明这些变量: char f1,f2,f3;但是, 实际上标志 f1, f2, f3 分别只需要 1 位。变量 type 只需要 4 位, 而变量 index 只需要 9 位。 总共是 16位 ---- 2 个字节。我们用两个字节就够了。我们可这样来做: struct packed_struct{&&& unsigned int f1 :1; &&& unsigned int f2 :1; &&& unsigned int f3 :1; &&& unsigned int type :4;&&& unsigned int index :9;
};该例中, 我们定义了一个结构 packed_struct。该结构定义了五个成员
。第一个成员叫做 f1, 是 unsigned int 类型的。紧跟在该成员名之后的 :1 规定了它以 1 位存放。类似地, 标志 f2 和 f3 被定义为长度只有 1 位的。定义成员 type 占有 4 位。定义成员 index 占有 9 位。C 编译器自动地把上面的位段定义压缩在一起。位段的划分如图所示。packed_struct 总共使用了 16 位。这种方法的好处是, 定义成 packed_struct 类型的变量的位段, 可以如引用一般的结构成员一样方便地引用。同时, 使用了更少的内存单元数。我们已经定义了一个称作为 packed_struct 的包含着位段的结构。现在, 我们象下面那样定义一个称作为 packet_data 的变量: struct packed_struct packed_ 于是, 我们就可以用简单的语句, 把 packed_data 的 type 位段设置为 7: packed_data.type = 7; 类似地, 我们可以用下面的语句把这个位段的值设为 n: packed_data.type = 我们不必担心 n 的值太长, 以致不能放入 type 位段中, C 编译器会自动地仅取出 n 的低四位, 把它赋值给 packed_data.type。取出位段的值也自动地处理的, 因此语句 n = packed_data. 将从 packed_data 中取出 type 位段, 并把它的值赋给 n。在一般的表达式中可以使用位段, 此时, 位段自动地转换成整数。因此, 表达式 i = packed_data.index/5+1; 是完全有效的。在包含位段的结构中, 也可以包括 "通常的" 数据类型。因此, 如果我们想定义一个结构, 它包含一个 int, 一个 char, 和二个 1 位的标志, 那么, 下面的定义是有效的: struct table_entry{&&& int&&&&&&& char&&&&&&& unsigned int f1 :1;&&& unsigned int f2 :1;};当位段出现在结构定义中时, 它们就被压缩成字。如果某个位段无法放入一个字中, 那么该字的剩余部分跳过不用, 该位段被放入下一个字中。使用位段时, 必须注意下列事项:
在某些机器上, 位段总是作为 unsigned 处理, 而不管它们是否被说明成 unsigned 的。
大多数C 编译器都不支持超过一个字长的位段。
位段不可标明维数; 即, 不能说明位段数组, 例如 flag:l[2]。
最后, 不可以取位段地址。原因是, 在这种情况不, 显然没有称作为 "位段指针" 类型的变量。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
这里, 我们再深入讨论一下位段。如果使用下面的结构定义:
struct bits{&&& unsigned int f1:1;&&& int&&&&&&& unsigned int f3:1;};那么, 位段是怎样压缩的呢? 由于成员 word 出现于其间, 故 f1, f3 不会压缩在同一个字内。C 编译器不会重新安排位段定义来试图优化存储空间。可以指定无名位段, 使得一个字中的某些位被 "跳过"。因此, 定义:
struct x_entry{&&& unsigned int type :4;&&& unsigned int :3;&&& unsigned int count :9;};将定义一个结构 x_entry, 它包含两个位段变量 type 和 count, 而无名位段规定了 type 和 count 间隔三位。来自:http://its./xhyu/cai_c/c_web/c/c8/c83.htm
内存对齐&应该是编译器的&管辖范围&。编译器为程序中的每个&数据单元&安排在适当的位置上。但是C语言的一个特点就是太灵活,太强大,它允许你干预&内存对齐&。如果你想了解更加底层的秘密,&内存对齐&对你就不应该再透明了。
一、内存对齐的原因大部分的参考资料都是如是说的:1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
二、对齐规则每个特定平台上的编译器都有自己的默认&对齐系数&(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的&对齐系数&。
对齐步骤:1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。3、结合1、2颗推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。备注:数组成员按长度按数组类型长度计算,如char t[9],在第1步中数据自身长度按1算,累加结构体时长度为9;第2步中,找最大数据长度时,如果结构体T有复杂类型成员A的,该A成员的长度为该复杂类型成员A的最大成员长度。
三、试验我们通过一系列例子的详细说明来证明这个规则吧!我试验用的编译器包括GCC 3.4.2和VC6.0的C编译器,平台为Windows XP + Sp2。
我们将用典型的struct对齐来说明。首先我们定义一个struct:#pragma pack(n) /* n = 1, 2, 4, 8, 16 */struct test_t {&&&&};#pragma pack(n)首先我们首先确认在试验平台上的各个类型的size,经验证两个编译器的输出均为:sizeof(char) = 1sizeof(short) = 2sizeof(int) = 4
我们的试验过程如下:通过#pragma pack(n)改变&对齐系数&,然后察看sizeof(struct test_t)的值。
1、1字节对齐(#pragma pack(1))输出结果:sizeof(struct test_t) = 8 [两个编译器输出一致]分析过程:1) 成员数据对齐#pragma pack(1)struct test_t {&&&/* 长度4 & 1 按1对齐;起始offset=0 0%1=0;存放位置区间[0,3] */&&&/* 长度1 = 1 按1对齐;起始offset=4 4%1=0;存放位置区间[4] */&&/* 长度2 & 1 按1对齐;起始offset=5 5%1=0;存放位置区间[5,6] */&&&/* 长度1 = 1 按1对齐;起始offset=7 7%1=0;存放位置区间[7] */};#pragma pack()成员总大小=8
2) 整体对齐整体对齐系数 = min((max(int,short,char), 1) = 1整体大小(size)=$(成员总大小) 按 $(整体对齐系数) 圆整 = 8 /* 8%1=0 */ [注1]
2、2字节对齐(#pragma pack(2))输出结果:sizeof(struct test_t) = 10 [两个编译器输出一致]分析过程:1) 成员数据对齐#pragma pack(2)struct test_t {&&&/* 长度4 & 2 按2对齐;起始offset=0 0%2=0;存放位置区间[0,3] */&&&/* 长度1 & 2 按1对齐;起始offset=4 4%1=0;存放位置区间[4] */&&/* 长度2 = 2 按2对齐;起始offset=6 6%2=0;存放位置区间[6,7] */&&&/* 长度1 & 2 按1对齐;起始offset=8 8%1=0;存放位置区间[8] */};#pragma pack()成员总大小=9
2) 整体对齐整体对齐系数 = min((max(int,short,char), 2) = 2整体大小(size)=$(成员总大小) 按 $(整体对齐系数) 圆整 = 10 /* 10%2=0 */
3、4字节对齐(#pragma pack(4))输出结果:sizeof(struct test_t) = 12 [两个编译器输出一致]分析过程:1) 成员数据对齐#pragma pack(4)struct test_t {&&&/* 长度4 = 4 按4对齐;起始offset=0 0%4=0;存放位置区间[0,3] */&&&/* 长度1 & 4 按1对齐;起始offset=4 4%1=0;存放位置区间[4] */&&/* 长度2 & 4 按2对齐;起始offset=6 6%2=0;存放位置区间[6,7] */&&&/* 长度1 & 4 按1对齐;起始offset=8 8%1=0;存放位置区间[8] */};#pragma pack()成员总大小=9
2) 整体对齐整体对齐系数 = min((max(int,short,char), 4) = 4整体大小(size)=$(成员总大小) 按 $(整体对齐系数) 圆整 = 12 /* 12%4=0 */
4、8字节对齐(#pragma pack(8))输出结果:sizeof(struct test_t) = 12 [两个编译器输出一致]分析过程:1) 成员数据对齐#pragma pack(8)struct test_t {&&&/* 长度4 & 8 按4对齐;起始offset=0 0%4=0;存放位置区间[0,3] */&&&/* 长度1 & 8 按1对齐;起始offset=4 4%1=0;存放位置区间[4] */&&/* 长度2 & 8 按2对齐;起始offset=6 6%2=0;存放位置区间[6,7] */&&&/* 长度1 & 8 按1对齐;起始offset=8 8%1=0;存放位置区间[8] */};#pragma pack()成员总大小=9
2) 整体对齐整体对齐系数 = min((max(int,short,char), 8) = 4整体大小(size)=$(成员总大小) 按 $(整体对齐系数) 圆整 = 12 /* 12%4=0 */
5、16字节对齐(#pragma pack(16))输出结果:sizeof(struct test_t) = 12 [两个编译器输出一致]分析过程:1) 成员数据对齐#pragma pack(16)struct test_t {&&&/* 长度4 & 16 按4对齐;起始offset=0 0%4=0;存放位置区间[0,3] */&&&/* 长度1 & 16 按1对齐;起始offset=4 4%1=0;存放位置区间[4] */&&/* 长度2 & 16 按2对齐;起始offset=6 6%2=0;存放位置区间[6,7] */&&&/* 长度1 & 16 按1对齐;起始offset=8 8%1=0;存放位置区间[8] */};#pragma pack()成员总大小=9
2) 整体对齐整体对齐系数 = min((max(int,short,char), 16) = 4整体大小(size)=$(成员总大小) 按 $(整体对齐系数) 圆整 = 12 /* 12%4=0 */
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:"c语言中数据有哪些类型数据类型"的糗事
11173 好笑
你可能感兴趣:
糗事百科为大家收集了很多的c语言中数据有哪些类型数据类型的糗事,各种关于c语言中数据有哪些类型数据类型的爆笑经历、尴尬时刻和开心视频,想持续关注c语言中数据有哪些类型数据类型的糗事就收藏本页吧.
扫码下载糗事百科appC语言数据类型 - CSDN博客
C语言数据类型
原文:/question/.html?an=0&si=1
C语言各种数据类型及其在系统中占的字节和取值范围 09:53C语言包含5个基本数据类型: void, int, float, double, 和 char.
(另:C++ 定义了另外两个基本数据类型: bool 和 wchar_t.
一些基本数据类型能够被 signed, unsigned, short, 和 long 修饰
所以short,long等等都不算基本数据类型。
这是书上说的,所以C++是7种基本数据类型。
空值型是一种,但枚举型不算。原因就是枚举型可分的,所以不够基本。
不过不同的书也有不同的规定,比如C++Primer上就说是bool,char,wchar_t,short,int,long,float,double,long double和void,这个暂时没有定论。)
============================================================
基本类型包括字节型(char)、整型(int)和浮点型(float/double)。
定义基本类型变量时,可以使用符号属性signed、unsigned(对于char、int),和长度属性short、long(对
于int、double)对变量的取值区间和精度进行说明。
下面列举了Dev-C++下基本类型所占位数和取值范围:
符号属性 长度属性 基本型 所占位数 取值范围 输入符举例 输出符举例
-- -- char
8 -2^7 ~ 2^7-1 %c %c、%d、%u
signed -- char
8 -2^7 ~ 2^7-1 %c %c、%d、%u
unsigned -- char
8 0 ~ 2^8-1 %c %c、%d、%u
[signed] short [int]
16 -2^15 ~ 2^15-1 %hd
unsigned short [int]
16 0 ~ 2^16-1 %hu、%ho、%hx
[signed] -- int
32 -2^31 ~ 2^31-1 %d
unsigned -- [int]
32 0 ~ 2^32-1 %u、%o、%x
[signed] long [int]
32 -2^31 ~ 2^31-1 %ld
unsigned long [int]
32 0 ~ 2^32-1 %lu、%lo、%lx
[signed] long long [int]
64 -2^63 ~ 2^63-1 %I64d
unsigned long long [int]
64 0 ~ 2^64-1 %I64u、%I64o、%I64x
-- -- float
32 +/- 3.4 %f、%e、%g
-- -- double
64 +/- 1.7 %lf、%le、%lg %f、%e、%g
-- long double
96 +/- 1.7 %Lf、%Le、%Lg
几点说明:
1. 注意! 表中的每一行,代表一种基本类型。“[]”代表可省略。
例如:char、signed char、unsigned char是三种互不相同的类型;
int、short、long也是三种互不相同的类型。
可以使用C++的函数重载特性进行验证,如:
void Func(char ch) {}
void Func(signed char ch) {}
void Func(unsigned char ch) {}
是三个不同的函数。
2. char/signed char/unsigned char型数据长度为1字节;
char为有符号型,但与signed char是不同的类型。
注意! 并不是所有编译器都这样处理,char型数据长度不一定为1字节,char也不一定为有符号型。
3. 将char/signed char转换为int时,会对最高符号位1进行扩展,从而造成运算问题。
所以,如果要处理的数据中存在字节值大于127的情况,使用unsigned char较为妥当。
程序中若涉及位运算,也应该使用unsigned型变量。
4. char/signed char/unsigned char输出时,使用格式符%c(按字符方式);
或使用%d、%u、%x/%X、%o,按整数方式输出;
输入时,应使用%c,若使用整数方式,Dev-C++会给出警告,不建议这样使用。
5. int的长度,是16位还是32位,与编译器字长有关。
16位编译器(如TC使用的编译器)下,int为16位;32位编译器(如VC使用的编译器cl.exe)下,int为32
6. 整型数据可以使用%d(有符号10进制)、%o(无符号8进制)或%x/%X(无符号16进制)方式输入输出。
而格式符%u,表示unsigned,即无符号10进制方式。
7. 整型前缀h表示short,l表示long。
输入输出short/unsigned short时,不建议直接使用int的格式符%d/%u等,要加前缀h。
这个习惯性错误,来源于TC。TC下,int的长度和默认符号属性,都与short一致,
于是就把这两种类型当成是相同的,都用int方式进行输入输出。
8. 关于long long类型的输入输出:
&%lld&和&%llu&是linux下gcc/g++用于long long int类型(64 bits)输入输出的格式符。
而&%I64d&和&%I64u&则是Microsoft VC++库里用于输入输出__int64类型的格式说明。
Dev-C++使用的编译器是Mingw32,Mingw32是x86-win32 gcc子项目之一,编译器核心还是linux下的gcc。
进行函数参数类型检查的是在编译阶段,gcc编译器对格式字符串进行检查,显然它不认得&%I64d&,
所以将给出警告“unknown conversion type character `I' in format”。对于&%lld&和&%llu&,gcc理
所当然地接受了。
Mingw32在编译期间使用gcc的规则检查语法,在连接和运行时使用的却是Microsoft库。
这个库里的printf和scanf函数当然不认识linux gcc下&%lld&和&%llu&,但对&%I64d&和&%I64u&,它则是
乐意接受,并能正常工作的。
9. 浮点型数据输入时可使用%f、%e/%E或%g/%G,scanf会根据输入数据形式,自动处理。
输出时可使用%f(普通方式)、%e/%E(指数方式)或%g/%G(自动选择)。
10. 浮点参数压栈的规则:float(4 字节)类型扩展成double(8 字节)入栈。
所以在输入时,需要区分float(%f)与double(%lf),而在输出时,用%f即可。
printf函数将按照double型的规则对压入堆栈的float(已扩展成double)和double型数据进行输出。
如果在输出时指定%lf格式符,gcc/mingw32编译器将给出一个警告。
11. Dev-C++(gcc/mingw32)可以选择float的长度,是否与double一致。
12. 前缀L表示long(double)。
虽然long double比double长4个字节,但是表示的数值范围却是一样的。
long double类型的长度、精度及表示范围与所使用的编译器、操作系统等有关。
====================================================================
(一)32位平台:
分为有符号型与无符号型。
有符号型:
short 在内存中占两个字节,范围为-2^15~(2^15-1)
int 在内存中占四个字节,范围为-2^31~(2^31-1)
long在内存中占四个字节,范围为-2^31~2^31-1
无符号型:最高位不表示符号位
unsigned short 在内存中占两个字节,范围为0~2^16-1
unsigned int 在内存中占四个字节,范围为0~2^32-1
unsigned long在内存中占四个字节,范围为0~2^32-1
分单精度 float 和双精度 double 两种形式:
float:占四个字节,提供7~8位有效数字。
double: 占八个字节,提供15~16位有效数字。
(二)16位平台:
1)整型(基本型):类型说明符为int,在内存中占2个字节。
2)短整型:类型说明符为short int或short。所占字节和取值范围均与整型(基本型)相同。
3)长整型:类型说明符为long int或long,在内存中占4个字节。
无符号型:类型说明符为unsigned。
无符号型又可与上述三种类型匹配而构成:
各种无符号类型量所占的内存空间字节数与相应的有符号类型量相同。但由于省去了符号位,故不能表示负数。
分为单精度(float型)、双精度(double型)和长双精度(long double型)三类。
单精度型占4个字节(32位)内存空间,其数值范围为3.4E-38~3.4E+38,只能提供七位有效数字。
双精度型占8 个字节(64位)内存空间,其数值范围为1.7E-308~1.7E+308,可提供16位有效数字。
长双精度型16 个字节(128位)内存空间,可提供18-19位有效数字。
============================================================================
C语言中5种基本数据类型的存储空间长度的排列顺序:
char = signed char = unsigned char & short int = unsigned short int &= int = unsigned int &= long int = unsigned long int
&= long long int = unsigned long long int
float &= double &= long double
用short修饰int时,short int表示短整型,占2字节的数据位.用long修饰int时,long int表示长整型,占4字节的数据位,在vc++6.0中int的数据类型也是占用了4字节的数据位,
那么应用int型与long型有什么区别呢? 下面就让我们来解答这个问题.我们知道现在的C++开发工具非常的多,int型在不同的系统中有可能占用的字节数会不一样, 而short与long修饰的int型的字节数是固定的,任何支持标准C++编译系统中都是如此.所以如果需要编写可移植性好的程序,应该将整型数据声明为short与long修饰的int型。
----------------------------------------------------------------------------------------
在C语言中,数据类型可分为:基本数据类型,构造数据类型,指针类型,空类型四大类。
1.基本数据类型
基本数据类型最主要的特点是,其值不可以再分解为其它类型。也就是说,基本数据类型是自我说明的。
2.构造数据类型构造数据类型
是根据已定义的一个或多个数据类型用构造的方法来定义的。也就是说,一个构造类型的值可以分解成若干个“成员”或“元素”。每个“成员”都是一个基本数据类型或又是一个构造类型。在C语言中,构造类型有以下几种: ·数组类型 ·结构类型 ·联合类型
3.指针类型
指针是一种特殊的,同时又是具有重要作用的数据类型。其值用来表示某个量在内存储器中的地址。虽然指针变量的取值类似于整型量,但这是两个类型完全不同 的量,因此不能混为一谈。4.空类型在调用函数值时,通常应向调用者返回一个函数值。这个返回的函数值是具有一定的数据类型的,应在函数定义及函数说明中 给以说明,例如在例题中给出的max函数定义中,函数头为: int max(int a,int b);其中“int ”类型说明符即表示该函数的返回值为整型量。又如在例题中,使用了库函数 sin,由于系统规定其函数返回值为双精度浮点型,因此在赋值语句s=sin
(x);中,s 也必须是双精度浮点型,以便与sin函数的返回值一致。所以在说明部分,把s说明为双精度浮点型。但是,也有一类函数,调用后并不需要向调用者返回函数 值, 这种函数可以定义为“空类型”。其类型说明符为void。在第五章函数中还要详细介绍。在本章中,我们先介绍基本数据类型中的整型、浮点型和字符型。其余 类型在以后各章中陆续介绍。
对于基本数据类型量,按其取值是否可改变又分为常量和变量两种。在程序执行过 程中,其值不发生改变的量称为常量,取值可变的量称为变量。它们可与数据类型结合起来分类。例如,可分为整型常量、整型变量、浮点常量、浮点变量、字符常 量、字符变量、枚举常量、枚举变量。在程序中,常量是可以不经说明而直接引用的,而变量则必须先说明后使用。
整型量包括整型常量、整型变量。整型常量就是整常数。在C语言中,使用的整常数有八进制、十六进制和十进制三种。
1.八进制整常数八进制整常数必须以0开头,即以0作为八进制数的前缀。数码取值为0~7。八进制数通常是无符号数。 以下各数是合法的八进制数: 015(十进制为13) 0101(十进制为65) 0177777(十进制为65535) 以下各数不是合法的八进制数: 256(无前缀0) 03A2(包含了非八进制数码) -0127(出现了负号)
2.十六进制整常数 十六进制整常数的前缀为0X或0x。其数码取值为0~9,A~F或a~f。 以下各数是合法的十六进制整常数: 0X2A(十进制为42) 0XA0 (十进制为160) 0XFFFF (十进制为65535) 以下各数不是合法的十六进制整常数: 5A (无前缀0X) 0X3H (含有非十六进制数码)
3.十进制整常数 十进制整常数没有前缀。其数码为0~9。 以下各数是合法的十进制整常数: 237 -568
以下各数不是合法的十进制整常数: 023 (不能有前导0) 23D (含有非十进制数码)
在程序中是根据前缀来区分各种进制数的。因此在书写常数时不要把前缀弄错造成结果不正确。
4.整型常数的后缀在16位字长的机器上,基本整型的长度也为 16位,因此表示的数的范围也是有限定的。十进制无符号整常数的范围为0~65535,有符号数为-32768~+32767。八进制无符号数的表示范围 为0~0177777。十六进制无符号数的表示范围为0X0~0XFFFF或0x0~0xFFFF。如果使用的数超过了上述范围,就必须用长整型数来表 示。长整型数是用后缀“L”或“l”来表示的。例如: 十进制长整常数 158L (十进制为158) 358000L (十进制为-358000) 八进制长整常数 012L
(十进制为10) 077L (十进制为63) 0200000L (十进制为65536) 十六进制长整常数 0X15L (十进制为21) 0XA5L (十进制为165) 0X10000L (十进制为65536)
长整数158L和基本整常数158 在数值上并无区别。但对158L,因为是长整型量,C编译系统将为它分配4个字节存储空间。而对158,因为是基本整型,只分配2 个字节的存储空间。因此在运算和输出格式上要予以注意,避免出错。无符号数也可用后缀表示,整型常数的无符号数的后缀为“U”或“u”。例如: 358u,0x38Au,235Lu 均为无符号数。前缀,后缀可同时使用以表示各种类型的数。如0XA5Lu表示十六进制无符号长整数A5,其十进制为165。
整型变量可分为以下几类: 1.基本型 类型说明符为int,在内存中占2个字节,其取值为基本整常数。 2.短整量 类型说明符为short int或short'C110F1。所占字节和取值范围均与基本型相同。 3.长整型 类型说明符为long int或long ,在内存中占4个字节,其取值为长整常数。 4.无符号型 类型说明符为unsigned。 无符号型又可与上述三种类型匹配而构成: (1)无符号基本型 类型说明符为unsigned int或unsigned。 (2)无符号短整型 类型说明符为unsigned
short (3)无符号长整型 类型说明符为unsigned long 各种无符号类型量所占的内存空间字节数与相应的有符号类型量相同。但由于省去了符号位,故不能表示负数。 下表列出了Turbo C中各类整型量所分配的内存字节数及数的表示范围。 类型说明符 数的范围 分配字节数 int - ■■ short int - ■■ signed int - ■■ unsigned int 0~65535 ■■ long int -~
■■■■ unsigned long 0~ ■■■■ 整型变量的说明 变量说明的一般形式为: 类型说明符 变量名标识符,变量名标识符,...; 例如: int a,b,c; (a,b,c为整型变量) long x,y; (x,y为长整型变量) unsigned p,q; (p,q为无符号整型变量)
在书写变量说明时,应注意以下几点: 1.允许在一个类型说明符后,说明多个相同类型的变量。各变量名之间用逗号间隔。类型说明符与变量名之间至少用一个空格间隔。 2.最后一个变量名之后必须以“;”号结尾。 3.变量说明必须放在变量使用之前。一般放在函数体的开头部分。 &&& x, y是长整型变量,a, b是基本整型变量。它们之间允许进行运算,运算结果为长整型。但c,d被定义为基本整型,因此最后结果为基本整型。本例说明,不同类型的量可以参与运算并 相互赋值。其中的类型转换是由编译系统自动完成的。有关类型转换的规则将在以后介绍。
实型也称为浮点型。实型常量也称为实数或者浮点数。在C语言中,实数只采用十进制。它有二种形式: 十进制数形式指数形式 1.十进制数形式 由数码0~ 9和小数点组成。例如:0.0,.25,5.789,0.13,5.0,300.,-267.8230等均为合法的实数。 2.指数形式 由十进制数,加阶码标志“e”或“E”以及阶码(只能为整数,可以带符号)组成。其一般形式为a E n (a为十进制数,n为十进制整数)其值为 a*10,n 如: 2.1E5 (等于2.1*10,5), 3.7E-2 (等于3.7*10,)-2*)
0.5E7 (等于0.5*10,7), -2.8E-2 (等于-2.8*10,)-2*)以下不是合法的实数 345 (无小数点) E7 (阶码标志E之前无数字) -5 (无阶码标志) 53.-E3 (负号位置不对) 2.7E (无阶码) 标准C允许浮点数使用后缀。后缀为“f”或“F”即表示该数为浮点数。如356f和356.是等价的。例2.2说明了这种情况: void main() { printf(&%f\n%f\n&,356.,356f); } void 指明main不返回任何值 利用printf显示结果
实型变量分为两类:单精度型和双精度型, 其类型说明符为float 单精度说明符,double 双精度说明符。在Turbo C中单精度型占4个字节(32位)内存空间,其数值范围为3.4E-38~3.4E+38,只能提供七位有效数字。双精度型占8 个字节(64位)内存空间,其数值范围为1.7E-308~1.7E+308,可提供16位有效数字。 实型变量说明的格式和书写规则与整型相同。 例如: float x,y; (x,y为单精度实型量) double a,b,c; (a,b,c为双精度实型量) 实型常数不分单、双精度,都按双精度double型处理。
void main(){ a=; b=; printf(&%f\n%f\n&,a,b); } 此程序说明float、double的不同 a ■■■■ b ■■■■■■■■ a&--- b&---33333;; 显示程序结果 此程序说明float、double的不同 a=; b=;
从本例可以看出,由于a 是单精度浮点型,有效位数只有七位。而整数已占五位,故小数二位后之后均为无效数字。b 是双精度型,有效位为十六位。但Turbo C 规定小数后最多保留六位,其余部分四舍五入。
字符型量包括字符常量和字符变量。
字符常量 字符常量是用单引号括起来的一个字符。例如'a','b','=','+','?'都是合法字符常量。在C语言中,字符常量有以下特点: 1.字符常量只能用单引号括起来,不能用双引号或其它括号。 2.字符常量只能是单个字符,不能是字符串。 3.字符可以是字符集中任意字符。但数字被定义为字符型之后就 不能参与数值运算。如'5'和5 是不同的。'5'是字符常量,不能参与运算。
转义字符 转义字符是一种特殊的字符常量。转义字符以反斜?\&开头,后跟一个或几个字符。转义字符具有特定的含义,不同于字符原有的意义,故称“转义” 字符。例如,在前面各例题printf函数的格式串中用到的“\n”就是一个转义字符,其意义是“回车换行”。转义字符主要用来表示那些用一般字符不便于 表示的控制代码。 常用的转义字符及其含义 转义字符 转义字符的意义 \n 回车换行 \t 横向跳到下一制表位置 \v 竖向跳格 \b 退格 \r 回车 \f 走纸换页 \\ 反斜线符&\& \' 单引号符 \a
鸣铃 \ddd 1~3位八进制数所代表的字符 \xhh 1~2位十六进制数所代表的字符 广义地讲,C语言字符集中的任何一个字符均可用转义字符来表示。表2.2中的\ddd和\xhh正是为此而提出的。ddd和hh分别为八进制和十六进制的 ASCII代码。如\101表示字?A& ,\102表示字母&B&,\134表示反斜线,\XOA表示换行等。转义字符的使用 void main() { int a,b,c; a=5; b=6; c=7; printf(&%d\n\t%d %d\n %d %d\t\b%d\n&,a,b,c,a,b,c);
} 此程序练习转义字符的使用 a、b、c为整数 5-&a,6-&b,7-&c 调用printf显示程序运行结果 printf(&%d\n\t%d %d\n %d %d\t\b%d\n&,a,b,c,a,b,c); 程序在第一列输出a值5之后就是“\n”,故回车换行;接着又是“\t”,于是跳到下一制表位置(设制表位置间隔为8),再输出b值6;空二格再输出c 值7后又是&\n&,因此再回车换行;再空二格之后又输出a值5;再空三格又输出b的值6;再次后&\t&跳到下一制表位置(与上一行的6 对齐),但下一转义字符“\b”又使退回一格,故紧挨着6再输出c值7。
字符变量 字符变量的取值是字符常量,即单个字符。字符变量的类型说明符是char。字符变量类型说明的格式和书写规则都与整型变量相同。 例如: char a,b; 每个字符变量被分配一个字节的内存空间,因此只能存放一个字符。字符值是以ASCII码的形式存放在变量的内存单元之中的。如x的 十进制ASCII码是120,y的十进制ASCII码是121。对字符变量a,b赋予'x'和'y'值: a='x';b='y';实际上是在a,b两个单元内存放120和121的二进制代码: a 0 1 1 1 1 0 0 0 b 0 1
1 1 1 0 0 1 所以也可以把它们看成是整型量。 C语言允许对整型变量赋以字符值,也允许对字符变量赋以整型值。在输出时, 允许把字符变量按整型量输出,也允许把整型量按字符量输出。 整型量为二字节量,字符量为单字节量,当整型量按字符型量处理时, 只有低八位字节参与处理。 main(){ char a,b; a=120; b=121; printf(&%c,%c\n%d,%d\n&,a,b,a,b); } a ■ b ■ a &-- 120 b &--- 121 显示程序结果 char a,b; a=120;
b=121; 本程序中说明a,b为字符型,但在赋值语句中赋以整型值。从结果看,a,b值的输出形式取决于printf函数格式串中的格式符,当格式符为&c&时,对应输出的变量值为字符,当格式符为&d&时,对应输出的变量值为整数。 void main(){ char a,b; a='x'; b='y'; a=a-32; b=b-32; printf(&%c,%c\n%d,%d\n&,a,b,a,b); } a,b被说明为字符变量并赋予字符值 把小写字母换成大写字母 以整型和字符型输出 本例中,a,b被说明为字符变量并赋予字符值,C语言允许字符变量参与数值运算,即用字符的ASCII
码参与运算。由于大小写字母的ASCII 码相差32,因此运算后把小写字母换成大写字母。然后分别以整型和字符型输出。
字符串常量 字符串常量是由一对双引号括起的字符序列。例如: &CHINA& ,&C program: , &$12.5& 等都是合法的字符串常量。字符串常量和字符常量是不同的量。它们之间主要有以下区别: 1.字符常量由单引号括起来,字符串常量由双引号括起来。 2.字符常量只能是单个字符,字符串常量则可以含一个或多个字符。 3.可以把一个字符常量赋予一个字符变量,但不能把一个字符串常量赋予一个字符变量。在C语言中没有相应的字符串变量。 这是与BASIC 语言不同的。但是可以用一个字符数组来存放一个字符串常量。在数组一章内予以介绍。
4.字符常量占一个字节的内存空间。字符串常量占的内存字节数等于字符串中字节数加1。增加的一个字节中存放字符&\0&(ASCII码为0)。这是字符 串结束的标志。例如,字符串 &C program&在内存中所占的字节为:C program\0。字符常量'a'和字符串常量&a&虽然都只有一个字符,但在内存中的情况是不同的。 'a'在内存中占一个字节,可表示为:a &a&在内存中占二个字节,可表示为:a\0符号常量
符号常量 在C语言中,可以用一个标识符来表示一个常量,称之为符号常量。符号常量在使用之前必须先定义,其一般形式为: #define 标识符 常量 其中#define也是一条预处理命令(预处理命令都?#&开头),称为宏定义命令(在第九章预处理程序中将进一步介绍),其功能是把该标识符 定义为其后的常量值。一经定义,以后在程序中所有出现该标识符的地方均代之以该常量值。习惯上符号常量的标识符用大写字母,变量标识符用小写字母,以示区 别。 #define PI 3.14159 void main(){ float
s,r; r=5; s=PI*r*r; printf(&s=%f\n&,s); } 由宏定义命令定义PI 为3.14159 s,r定义为实数 5-&r PI*r*r-&s 显示程序结果 float s,r; r=5; s=PI*r*r; 本程序在主函数之前由宏定义命令定义PI 为3.14159,在程序中即以该值代替PI 。s=PI*r*r等效于s=3.14159*r*r。应该注意的是,符号常量不是变量,它所代表的值在整个作用域内不能再改变。也就是说,在程序中,不 能再用赋值语句对它重新赋值。
变量的初值和类型转换
变量赋初值 在程序中常常需要对变量赋初值,以便使用变量。语言程序中可有多种方法,在定义时赋以初值的方法,这种方法称为初始化。在变量说明中赋初值的一般形式为: 类型说明符 变量1= 值1,变量2= 值2,……; 例如: int a=b=c=5; float x=3.2,y=3f,z=0.75; char ch1='K',ch2='P'; 应注意,在说明中不允许连续赋值,如a=b=c=5是不合法的。 void main(){ int a=3,b,c=5; b=a+c; printf(&a=%d,b=%d,c=%d\n&,a,b,c);
} a&---3,b&--0,c&---5 b&--a+c 显示程序运行结果
变量类型的转换 变量的数据类型是可以转换的。转换的方法有两种, 一种是自动转换,一种是强制转换。
自动转换 自动转换发生在不同数据类型的量混合运算时,由编译系统自动完成。自动转换遵循以下规则: 1.若参与运算量的类型不同,则先转换成同一类型,然后进行运算。 2.转换按数据长度增加的方向进行,以保证精度不降低。如int型和long型运算时,先把int量转成long型后再进行运算。 3.所有的浮点运算都是以双精度进行的,即使仅含float单精度量运算的表达式,也要先转换成double型,再作运算。 4.char型和short型参与运算时,必须先转换成int型。 5.在赋值运算中,赋值号两边量的数据类型不同时,
赋值号右边量的类型将转换为左边量的类型。 如果右边量的数据类型长度左边长时,将丢失一部分数据,这样会降低精度, 丢失的部分按四舍五入向前舍入。图2 1表示了类型自动转换的规则。 void main(){ float PI=3.14159; int s,r=5; s=r*r*PI; printf(&s=%d\n&,s); } PI&--3.14159 s&--0,r&--5 s&--r*r*PI 显示程序运行结果 float PI=3.14159; int s,r=5; s=r*r*PI; 本例程序中,PI为实型;s,r为整型。在执行s=r*r*PI语句时,r和PI都转换成double型计算,结果也为double型。但由于s为整型,故赋值结果仍为整型,舍去了小数部分。
强制类型转换 强制类型转换是通过类型转换运算来实现的。其一般形式为: (类型说明符) (表达式) 其功能是把表达式的运算结果强制转换成类型说明符所表示的类型。例如: (float) a 把a转换为实型(int)(x+y) 把x+y的结果转换为整型在使用强制转换时应注意以下问题: 1.类型说明符和表达式都必须加括号(单个变量可以不加括号),如把(int)(x+y)写成(int)x+y则成了把x转换成int型之后再与y相加了。 2.无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类型。
main(){ float f=5.75; printf(&(int)f=%d,f=%f\n&,(int)f,f); } f&--5.75 将float f强制转换成int f float f=5.75;printf(&(int)f=%d,f=%f\n&,(int)f,f); 本例表明,f虽强制转为int型,但只在运算中起作用, 是临时的,而f本身的类型并不改变。因此,(int)f的值为 5(删去了小数)而f的值仍为5.75
  程序中使用的各种变量都应预先加以定义,即先定义,后使用。对变量的定义可以包括三个方面:数据类型、存储类型、作用域。
用户存储空间可以分为三个部分:&
程序区;静态存储区;动态存储区;
从变量的作用域(即从空间)角度来分,可以分为全局变量和局部变量。
从变量值存在的作时间(即生存期)角度来分,可以分为静态存储方式和动态存储方式。&
& &&静态存储方式:是指在程序运行期间分配固定的存储空间的方式。&
& & 动态存储方式:是在程序运行期间根据需要进行动态的分配存储空间的方式。
& 全局变量全部存放在静态存储区,在程序开始执行时给全局变量分配存储区,程序行完毕就释放。在程序执行过程中它们占据固定的存储单元,而不动态地进行分配和释放;
&&动态存储区存放以下数据:&
函数形式参数;自动变量(未加static声明的局部变量);函数调用实的现场保护和返回地址;
对以上这些数据,在函数开始调用时分配动态存储空间,函数结束时释放这些空间。在c语言中,每个变量和函数有两个属性:数据类型和数据的存储类别。
为了提高效率,C语言允许将局部变量得值放在CPU中的寄存器中,这种变量叫“寄存器变量”,用关键字register作声明。
只有局部自动变量和形式参数可以作为寄存器变量;一个计算机系统中的寄存器数目有限,不能定义任意多个寄存器变量;局部静态变量不能定义为寄存器变量。
& 外部变量(即全局变量)是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件终了。如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量作“外部变量声明”。表示该变量是一个已经定义的外部变量。有了此声明,就可以从“声明”处起,合法地使用该外部变量。
&&数据类型
按被定义变量的性质,表示形式,占据存储空间的多少,构造特点来划分的。在C语言中,数据类型可分为:基本数据类型,构造数据类型,指针类型,空类型四大类。
& 对于基本数据类型量,按其取值是否可改变又分为常量和变量两种。在程序执行过程中,其值不发生改变的量称为常量,其值可变的量称为变量。它们可与数据类型结合起来分类。例如,可分为整型常量、整型变量、浮点常量、浮点变量、字符常量、字符变量、枚举常量、枚举变量。在程序中,常量是可以不经说明而直接引用的,而变量则必须先定义后使用。整型量包括整型常量、整型变量。
在程序执行过程中,其值不发生改变的量称为常量。
直接常量(字面常量):
整型常量:12、0、-3;
实型常量:4.6、-1.23;
字符常量:‘a’、‘b’。
标识符:用来标识变量名、符号常量名、函数名、数组名、类型名、文件名的有效字符序列。
符号常量:用标示符代表一个常量。在C语言中,可以用一个标识符来表示一个常量,称之为符号常量。
符号常量在使用之前必须先定义,其一般形式为:#define 标识符 常量
其中#define也是一条预处理命令(预处理命令都以&#&开头),称为宏定义命令(在后面预处理程序中将进一步介绍),其功能是把该标识符定义为其后的常量值。一经定义,以后在程序中所有出现该标识符的地方均代之以该常量值。
习惯上符号常量的标识符用大写字母,变量标识符用小写字母,以示区别。使用符号常量的好处是:含义清楚;能做到“一改全改”。
一个变量应该有一个名字,在内存中占据一定的存储单元。变量定义必须放在变量使用之前。一般放在函数体的开头部分。要区分变量名和变量值是两个不同的概念。
就是整常数。在C语言中,使用的整常数有八进制、十六进制和十进制三种。
十进制整常数:十进制整常数没有前缀。其数码为0~9。
八进制整常数:八进制整常数必须以0开头,即以0作为八进制数的前缀。数码取值为0~7。八进制数通常是无符号数。
十六进制整常数:十六进制整常数的前缀为0X或0x。其数码取值为0~9,A~F或a~f。
整型常数的后缀:在16位字长的机器上,基本整型的长度也为16位,因此表示的数的范围也是有限定的。十进制无符号整常数的范围为0~65535,有符号数为-32768~+32767。八进制无符号数的表示范围为0~0177777。十六进制无符号数的表示范围为0X0~0XFFFF或0x0~0xFFFF。如果使用的数超过了上述范围,就必须用长整型数来表示。长整型数是用后缀“L”或“l”来表示的。
整型数据在内存中的存放形式
如果定义了一个整型变量i:
数值是以补码表示的:
正数的补码和原码相同;
负数的补码:将该数的绝对值的二进制形式按位取反再加1。
左面的第一位是表示符号的。
整型变量的分类
基本型:类型说明符为int,在内存中占2个字节。
短整量:类型说明符为short int或short。所占字节和取值范围均与基本型相同。
长整型:类型说明符为long int或long,在内存中占4个字节。
无符号型:类型说明符为unsigned。
无符号型又可与上述三种类型匹配而构成:
无符号基本型:类型说明符为unsigned int或unsigned。
无符号短整型:类型说明符为unsigned short。
无符号长整型:类型说明符为unsigned long。
各种无符号类型量所占的内存空间字节数与相应的有符号类型量相同。但由于省去了符号位,故不能表示负数。
类型说明& & & & & & & & & & 符数的范围& & & & & & & & & & & & & & 字节数
int-& & & & & & & & & & & & & 即-2&15~(2&15-1)
unsigned int0~65535& & & & & & & & & & 即0~(2&16-1) & & 2
short int-& & & & & & & & & 即-2&15~(2&15-1)
unsigned short int0~65535& & & & & & 即0~(2&16-1) & & 2
long int-~ 即-2&31~(2&31-1) 4
unsigned long0~& & & & & 即0~(2&32-1) & & 4
也称为浮点型。实型常量也称为实数或者浮点数。在C语言中,实数只采用十进制。它有二种形式:十进制小数形式,指数形式。
十进制数形式:由数码0~ 9和小数点组成。注意,必须有小数点。
指数形式:由十进制数,加阶码标志“e”或“E”以及阶码(只能为整数,可以带符号)组成。其一般形式为:a E n(a为十进制数,n为十进制整数)其值为 a*10n
标准C允许浮点数使用后缀。后缀为“f”或“F”即表示该数为浮点数。如356f和356.是等价的
实型数据在内存中的存放形式
实型数据一般占4个字节(32位)内存空间。按指数形式存储。实数3.14159在内存中的存放形式如下:
& & & & 数符& & & & & 小数部分& & & & & & & & & 指数
小数部分占的位(bit)数愈多,数的有效数字愈多,精度愈高。
指数部分占的位数愈多,则能表示的数值范围愈大。
实型变量的分类
实型变量分为:单精度(float型)、双精度(double型)和长双精度(long double型)三类。
在Turbo C中单精度型占4个字节(32位)内存空间,其数值范围为3.4E-38~3.4E+38,只能提供七位有效数字。双精度型占8 个字节(64位)内存空间,其数值范围为1.7E-308~1.7E+308,可提供16位有效数字。
类型说明符
比特数(字节数)
10-37~1038
10-307~10308
long double
10-4931~104932
实型数据的舍入误差
由于实型变量是由有限的存储单元组成的,因此能提供的有效数字总是有限的。
a 是单精度浮点型,有效位数只有七位。而整数已占五位,故小数二位后之后均为无效数字。
b 是双精度型,有效位为十六位。但Turbo C 规定小数后最多保留六位,其余部分四舍五入。
PS:实型常数不分单、双精度,都按双精度double型处理。
字符型数据
包括字符常量和字符变量。
字符常量是用单引号括起来的一个字符。例如:'a'、'b'、'='、'+'、'?'都是合法字符常量。
字符常量只能用单引号括起来,不能用双引号或其它括号。
字符常量只能是单个字符,不能是字符串。
字符可以是字符集中任意字符。但数字被定义为字符型之后就不能参与数值运算。如'5'和5 是不同的。'5'是字符常量,不能参与运算。
转义字符是一种特殊的字符常量。转义字符以反斜线&\&开头,后跟一个或几个字符。转义字符具有特定的含义,不同于字符原有的意义,故称“转义”字符。例如,在前面各例题printf函数的格式串中用到的“\n”就是一个转义字符,其意义是“回车换行”。转义字符主要用来表示那些用一般字符不便于表示的控制代码。
转义字符的意义
横向跳到下一制表位置
退格
反斜线符&\&
1~3位八进制数所代表的字符
1~2位十六进制数所代表的字符
广义地讲,C语言字符集中的任何一个字符均可用转义字符来表示。表中的\ddd和\xhh正是为此而提出的。ddd和hh分别为八进制和十六进制的ASCII代码。如\101表示字母&A& ,\102表示字母&B&,\134表示反斜线,\XOA表示换行等。
字符变量用来存储字符常量,即单个字符。字符变量的类型说明符是char。字符变量类型定义的格式和书写规则都与整型变量相同。例如:char a,b;
每个字符变量被分配一个字节的内存空间,因此只能存放一个字符。字符值是以ASCII码的形式存放在变量的内存单元之中的。
实际上是在a,b两个单元内存放120和121的二进制代码:
所以也可以把它们看成是整型量。C语言允许对整型变量赋以字符值,也允许对字符变量赋以整型值。在输出时,允许把字符变量按整型量输出,也允许把整型量按字符量输出。
整型量为二字节量,字符量为单字节量,当整型量按字符型量处理时,只有低八位字节参与处理。
字符串常量
字符串常量是由一对双引号括起的字符序列。
字符串常量和字符常量是不同的量。它们之间主要有以下区别:
字符常量由单引号括起来,字符串常量由双引号括起来。
字符常量只能是单个字符,字符串常量则可以含一个或多个字符。
可以把一个字符常量赋予一个字符变量,但不能把一个字符串常量赋予一个字符变量。在C语言中没有相应的字符串变量。这是与BASIC 语言不同的。但是可以用一个字符数组来存放一个字符串常量。在数组一章内予以介绍。
字符常量占一个字节的内存空间。字符串常量占的内存字节数等于字符串中字节数加1。增加的一个字节中存放字符&\0& (ASCII码为0)。这是字符串结束的标志。
字符串 &C program& 在内存中所占的字节为:
----------------------------------------------------------------------------------------
c语言基本数据类型short、int、long、char、float、double
& C 语言包含的数据类型如下图所示:
一、数据类型与“模子” &short、int、long、char、float、double 这六个关键字代表C 语言里的六种基本数据类型。 & 怎么去理解它们呢? 举个例子:见过藕煤球的那个东西吧?(没见过?煤球总见过吧)。那个东西叫藕煤器,拿着它在和好的煤堆里这么一咔,一个煤球出来了。半径12cm,12 个孔。不同型号的藕煤器咔出来的煤球大小不一样,孔数也不一样。这个藕煤器其实就是个模子。 & 现在我们联想一下,short、int、long、char、float、double 这六个东东是不是很像不同类型的藕煤器啊?拿着它们在内存上咔咔咔,不同大小的内存就分配好了,当然别忘了给它们取个好听的名字。
& 在32 位的系统上short 咔出来的内存大小是2 个byte; &int 咔出来的内存大小是4 个byte; &long 咔出来的内存大小是4 个byte; &float 咔出来的内存大小是4 个byte; &double 咔出来的内存大小是8 个byte; &char 咔出来的内存大小是1 个byte。 &(注意这里指一般情况,可能不同的平台还会有所不同,具体平台可以用sizeof 关键字测试一下) & 很简单吧?咔咔咔很爽吧?是很简单,也确实很爽,但问题就是你咔出来这么多内存块,你总不能给他取名字叫做x1,x2,x3,x4,x5…或者长江1
号,长江2 号…吧。它们长得这么像(不是你家的老大,老二,老三…),过一阵子你就会忘了到底哪个名字和哪个内存块匹配了(到底谁嫁给谁了啊?^_^)。所以呢,给他们取一个好的名字绝对重要。下面我们就来研究研究取什么样的名字好。 & 二、变量的命名规则 &1、命名应当直观且可以拼读,可望文知意,便于记忆和阅读。 &标识符最好采用英文单词或其组合,不允许使用拼音。程序中的英文单词一般不要太复杂,用词应当准确。 & 2、命名的长度应当符合“min-length && max-information”原则。 &C 是一种简洁的语言,
命名也应该是简洁的。例如变量名MaxVal 就比MaxValueUntilOverflow 好用。标识符的长度一般不要过长,较长的单词可通过去掉“元音”形成缩写。 & 另外,英文词尽量不缩写,特别是非常用专业名词,如果有缩写,在同一系统中对同一单词必须使用相同的表示法,并且注明其意思。 & 3、当标识符由多个词组成时,每个词的第一个字母大写,其余全部小写。比如: &&& int CurrentVal; &这样的名字看起来比较清晰,远比一长串字符好得多。 & 4、尽量避免名字中出现数字编号,如Value1,Value2
等,除非逻辑上的确需要编号。比如驱动开发时为管脚命名,非编号名字反而不好。 &初学者总是喜欢用带编号的变量名或函数名,这样子看上去很简单方便,但其实是一颗颗定时炸弹。这个习惯初学者一定要改过来。 & 5、对在多个文件之间共同使用的全局变量或函数要加范围限定符(建议使用模块名(缩写)作为范围限定符)。 &(GUI_ ,etc)标识符的命名规则: & 6、标识符名分为两部分:规范标识符前缀(后缀) + 含义标识。非全局变量可以不用使用范围限定符前缀。
7、作用域前缀命名规则。
8、数据类型前缀命名规则。
9、含义标识命名规则,变量命名使用名词性词组,函数命名使用动词性词组。例如:
变量含义标识符构成:目标词+ 动词(的过去分词)+ [状语] + [目的地];
函数含义标识符构成:动词(一般现时)+目标词+[状语]+[目的地]; & 10、程序中不得出现仅靠大小写区分的相似的标识符。例如: &&& int x, X; 变量x 与X 容易混淆 &&& void foo(int x); 函数foo 与FOO 容易混淆 &&& void FOO(float x); &这里还有一个要特别注意的就是1(数字1)和l(小写字母l)之间,0(数字0)和o(小写字母o)之间的区别。这两对真是很难区分的,我曾经的一个同事就被这个问题折腾了一次。 & 11、一个函数名禁止被用于其它之处。例如:
&#include &c_standards.h& &void foo(int p_1) &{ &&& int x = p_1; &} &void static_p(void) &{ &&& int foo = 1u; &} & 12、所有宏定义、枚举常数、只读变量全用大写字母命名,用下划线分割单词。例如: &const int MAX_LENGTH = 100; //这不是常量,而是一个只读变量,具体请往后看 &&& #define FILE_PATH “/usr/tmp” & 13、考虑到习惯性问题,局部变量中可采用通用的命名方式,仅限于n、i、j
等作为循环变量使用。 &一定不要写出如下这样的代码: &&& &&& &&& &&& char * &一般来说习惯上用n,m,i,j,k 等表示int 类型的变量;c,ch 等表示字符类型变量;a 等表示数组;p 等表示指针。当然这仅仅是一般习惯,除了i,j,k 等可以用来表示循环变量外,别的字符变量名尽量不要使用。
& 14、定义变量的同时千万千万别忘了初始化。定义变量时编译器并不一定清空了这块内存,它的值可能是无效的数据。这个问题在内存管理那章有非常详细的讨论,请参看。 & 15、不同类型数据之间的运算要注意精度扩展问题,一般低精度数据将向高精度数据扩展 &br /&本文来自【C语言中文网】:&a href=&&
target=&_blank&&http://see./cpp/html/437.html&/a&
本文已收录于以下专栏:
相关文章推荐
C语言的数据类型以及各数据类型的字节数。
转自:http://blog.csdn.NET/mafuli007/article/details/7325510
char -128 ~ +127 (1 Byte)
C语言中提供了许多的数据类型,如下图所示:C语言为什么要引入这么多的数据类型呢?因为C语言归根结底只是一门编程语言,一种让计算机为我们做事情的工具。引入这么多的数据类型是为了更加方便的表现现实世界中事...
一、变量二、类型修饰符三、不同编译器环境下基本数据类型的存储长度
说明:这个C语言专题,是学习iOS开发的前奏。也为了让有面向对象语言开发经验的程序员,能够快速上...
今天主要讲了C语言的基本数据类型与表达式。最基本的单位是位,字节,字。数据的存储方式包括整数和浮点数,还有c语言的基本数据类型,包括基本类型,构造类型,指针类型(*),还有空类型,以及常量和变量还有运...
给定A, B两个整数,不使用除法和取模运算,求A/B的商和余数。
最基本的算法是,从小到大遍历:
for (i = 2 to A -1)
if (i * B > A)...
K-means聚类算法是一种非层次聚类算法,在最小误差的基础上将数据划分了特定的类,类间利用距离作为相似度指标,两个向量之间的距离越小,其相似度就越高。程序读取全国省市经纬度坐标,然后根据经纬度坐标进...
本人最近在研究Radon变换,在查阅了各种资料之后在此写下个人的理解,希望与各位牛牛进行交流共同进步,也使得理解更加深刻些。
Radon变换的本质是将原来的函数做了一个空间转换,即,将原来的XY平...
由于csdn贴图不方便,并且不能上传附件,我把原文上传到了资源空间CT图像重建技术
计算机层析成像(Computed Tomography,CT)是通过对物体进行不同角度的射线投影测量而...
Matlab绘图强大的绘图功能是Matlab的特点之一,Matlab提供了一系列的绘图函数,用户不需要过多的考虑绘图的细节,只需要给出一些基本参数就能得到所需图形,这类函数称为高层绘图函数。此外,Ma...
他的最新文章
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 c语言的数据类型 的文章

 

随机推荐