欢迎访问 生活随笔!

凯发ag旗舰厅登录网址下载

当前位置: 凯发ag旗舰厅登录网址下载 > 编程语言 > c/c >内容正文

c/c

c/c 之数据类型 -凯发ag旗舰厅登录网址下载

发布时间:2024/10/14 c/c 26 豆豆
凯发ag旗舰厅登录网址下载 收集整理的这篇文章主要介绍了 c/c 之数据类型 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

tips:
 1. 本人当初学习c/c 的记录。
 2. 资源很多都是来自网上的,如有凯发ag旗舰厅登录网址下载的版权请及时告知!
 3. 可能会有些错误。如果看到,希望能指出,以此共勉!


ansi c99标准中规定的数据类型如下图所示。

说明:

  • 同一行类型的语义相同,即可以相互替代。
  • long float类型与double相同,故在c99标准中没有此类型。
  • 部分编译器也提供了unsigned float和unsigned double,最好不要使用,以免影响程序的可移植性。
  • int默认是signed,所以int, signed, signed int三者等价。其它unsigned的情况类似。char默认情况不确定。

c语言中数据类型的长度

  ansi c99标准中定义了两类(四个)类型修饰符:long/short和unsigned/signed。c99标准规定,long类型不能比变通类型短,short类型不能比普通类型长。而unsigned与signed的区别在实现上是有无符号的区别,而是使用上是取值范围的区别,两者表示范围相同,但前者全是正数,后者关于0对称。
说明:

  • long/short可以修饰int,long还可以修饰double。
  • unsigned/signed可以修饰int、char,不可以修饰浮点型。
  • int长度是机器的字长,short int是半个字长,long int是一个或两个字长。
  • unsigned/signed长度与普通类型一样,只是表示区间不同。

c语言中数据类型的转换

类型转换分为显示和隐式两种,前者比较简单,这里只讲后者。下面是c99标准中给出的各种类型对象的基本转换规则:

  • 枚举常量: 转换成int,如超出int范围,则转成long int等
  • 浮点型:
    • 如果转成整类型,只保留整数部分,如果超出整型表示范围,则转换错误;
    • 如果向上转成double/long double,值不变;
    • 如果向下转成float/double等,如果能用float/double表示,则正常,如果超出表示范围,则转换错误,而如果在表示范围内,但精度降低,则要依赖于编译器的处理了
  • 整型: short int/char/枚举类型/位类型都可转换成int,如果超出int表示范围,则提升到unsigned int。
    对于二元运算符中的普通算术运算转换,c99标准给出了如下图所示的转换规则:

    说明:

  • 对于unsigned char和unsigned short int的整型提升问题,c99标准给出“保值”的转换方法:方法是将unsigned char和unsigned short int转换成int,如果超出表示范围,则转成unsigned int。

  • 对于表格中第五行,long int与unsigned int的情况,在vc6.0没有这样实现,是直接转成unsigned int。

  面向对象编程(oop)的本质是设计并扩展自己的数据类型。c 兼容c的数据类型,又稍有区别。当然,下面的数据类型说明多数同样适用于c类型,部分不同于c的地方将单独指出。

基本类型

  基本类型主要就是整型和浮点型,同时对这两种进行了多种变形。(c 11新增了bool类型,兼容c99)

整型

  基本整型包括:char、short、int、long和c 11中新增的long long(兼容c99)。其中每种类型都有有符号版和无符号版。
1. 每种数据类型都有一定的数据范围,不同的系统可能有不能的范围。c 采用灵活的标准,确保了数据类型的最小长度(c语言可能不同):

  • short 至少16位
  • int 至少与short一样长
  • long 至少32位,且至少与int一样长
  • long long 至少64位,且至少与long一样长
    在头文件climits(旧limits.h)中包含了关于整型限制的信息。如下图(vs2010):

    数据类型的范围是怎么算出来的。(c及c )
  • 计算机中数据都是以二进制存储;
  • 二进制可以由不同的编码(原码、补码、反码)表示,计算机统一采用补码表示。
  • 计算机中的正负号,0表示正数,1表示负数
    以2字节(16位)有符号类型来说:
    范围: (10进制)-32768到32767;(16进制)8000到7fff;(2进制补码)1000,0000,0000 ,0000到0111,1111,1111,1111
    原码:最高位为符号位,其余位与正常二进制表示方法一致;
    原码表示范围:
    最大为0111111111111111 = 2^15-1 = 32767
    最小为1111111111111111 = -2^15-1 = -32767
    0和-0:
    0:0000000000000000
    -0:1000000000000000
    即正零与负零表示方法不同。也就意味着:原码能表示的有符号数范围是:-32767~-0和0~32767
    补码: 正数补码与原码相同,负数补码需要把除符号位以外的原码取反加1
    补码表示范围:
    最大为0111111111111111 = 2^15-1 = 32767
    最小为1000000000000001 = 原码:1111111111111111的符号不变其余取反为:1000000000000000,再加1为:1000000000000001
    0和-0:
    0:0000000000000000 // 与原码相同
    -0:0000000000000000 // 原码:1000000000000000的符号不变其余取反为:1111111111111111,再加1为:0000000000000000(进位舍掉)
    也就是正0和负0在补码系统中的编码是一样的。也就是补码会比原码多一个编码出来,这个编码就是1000000000000000。因为任何一个原码都不可能在转成补码时变成1000000000000000。所以,人为规定1000000000000000这个补码编码为-32768。所以,补码系统中,范围是-23768~32767。

  • c 中,对于变量的赋值更加灵活,原来用于结构体和数组的赋值,现在对于单个变量也是可以的。
  • c 如何确定整型常数的类型
  • 对于有字符修饰的整型数字,根据字符来判断类型。例如:123l,则为long;123ul为unsigned long。
  • 对于没有符号修饰的十进制数字,c 总是采用int、unsigned int、long、unsigned long、long long (没有short)中能够存储该数的最小类型表示。
  • 对于没有符号修饰的十六进制或者八进制,则总是以对应的无符号类型表示。

浮点型

c 基本浮点型包括:float、double、long double。unsigned和signed不能修饰浮点型
c/c 对于浮点型有效位的规定:

  • float至少32位
  • double 至少48位,且不少于float
  • long double 至少和double一样多

注意:默认情况下,浮点常数字为double型,例如程序中直接写1.0,其被当做double型数字。

在头文件cfloat(旧float.h)中包含了关于浮点型限制的信息(有些系统没有提供该文件)。如下图:

从上表中可看到,在vs2010中,double的有效位数为15,float的有效位数为6

浮点数的存储

  c/c 编译器都是按照ieee的浮点数表示法,即一种科学计数法,用符号、指数和尾数来表示,底数为2。也就是把浮点数表示为尾数乘以2的指数次方再添加上符号的形式。因为科学技术法 a×bm的形式,a介于1~10,而浮点数表示法中,a始终为1,所以在最终的表示结果中,这个1被略去。即:尾数二进制最高位的1不要
具体规格是:

类型符号位阶码尾数总长度
float182332
double1115264

下面通过例子来解释上面的表示规格:

  • 38414.4表示为double:
    • 分开整数和小数部分,整数化为16进制,0x960e;小数部分为:0.4=0.5×0 0.25×1 0.125×1 …… 0.5×(1 or 0)/n ……。//实际上这永远算不完!
    • 有的小数可以穷尽,有的是永远不会穷尽的,此时只需要提取出各项的系数,即011……,这些项的和加上整数部分共53位就可以了。正如上面所言的,最高为不变的1可以省略(归一化),最终是53-1=52位。
    • 38414.4可以表示为1001011000001110.0110011001100110011001100110011001100b。
    • 用科学计数法表示为1.0010110000011100110011001100110011001100110011001100×215。
    • 然后计算阶码,阶码共11位,可以表示-1024~1023,因为指数可以为负数,规定先加上1023变为非负数(指数偏移),上面的15表示为15 1023=1038,二进制为10000001110。符号位,0为正,1为负。所以最终结果是
    • 0 10000001110 0010110000011100110011001100110011001100110011001100
    • 颜色与上表对应。
  • 3490593表示为float:
    • 3490593的浮点数为3490593.0。
    • 整数化为二进制,为1101010100001100100001b,即1.101010100001100100001×221,由于float的尾数有23位,需要补0。即1.10101010000110010000100×221。
    • 计算阶码时,类似double的表示,阶码共8位,表示的范围是-128~127,为了方便,加上127,上面的21表示为21 127=148=10010100b。最终结果是:
    • 0 10010100 10101010000110010000100
    • 颜色与上表对应。
  • 0.5的二进制表示:
    • 上面给出了0.4的二进制表示的计算方法:
    • 0.4 = 0.5×0 0.25×1 0.125×1 …… 0.5×(1 or 0)/n ……。
    • 它是无穷尽的,直到精度合适了为止。
    • 然而对于有的数来说,是有穷的,比如0.5=1×0.5。整数部分为0,小数部分为0.1,所以0.5的二进制形式是0.1,即1.0 × 2-1。
    • 计算阶码时,用127 (-1)=126=b1111110b。所以最终结果是:
    • 0 01111110 00000000000000000000000
    • 颜色与上表对应。
  • -12.5的二进制浮点表示:
    • 整数部分为12,即1100b;小数部分为0.5,即0.1b,即1100.10000000000000000000,即1.10010000000000000000000 × 23。
    • 计算阶码,3 127=130,即10000010b,所以最终结果是:
    • 1 10000010 10010000000000000000000
    • 颜色与上表对应。
  • 逆向求取,1011 1101 0100 0000 0000 0000 0000 0000转为十进制:
    • 1011 1101 0100 0000 0000 0000 0000 0000为:
    • 1 01111010 10000000000000000000000
    • 所以该数为-1.10000000000000000000000 × 201111010-127=-5 = -0.000011b = 0.046875
      详细见http://blog.163.com/yql_bl/blog/static/847851692008112013117685/
      有了以上知识,那么printf(“%f”,10/3);的结果是什么?结果是0.0000
      10/3的结果无疑应该是3,但是,我们却要求printf按照浮点数来去这个数,通过以上我们知道,整数和浮点数的存储方式是不一样的。
      整型数3在内存存储如下:
      0000 0000 0000 0000 0000 0000 0000 0011
      但是现在我们要用浮点数的方式来解析这32位数字。按照浮点数方式:
      0000 0000 0000 0000 0000 0000 0000 0011
      上面红色是符号为0,表示正数;蓝色的是指数位,结果为0,但是这儿要注意的一点是指数在存储的时候是进行过偏移的,所以这儿要剪掉127,所以指数为-127。最后的紫色是尾数,结果是2^(-22) 2^(-23),但是也要注意一点是,尾数在进行存储的时候是归一化过的,小数点前面其实有个1,所以最后尾数是1 2^(-22) 2^(-23)。所以最后的浮点数是:[1 2^(-22) 2^(-23)]*2^(-127)转化为可读数字就是5.87747385606e-39 ,这个数就非常小了,所以显示的时候就是0.000000啦。

数据类型转换

隐式类型转换

在某些情况下,c 将自动对数据类型进行转换:

  • 不同数据类型之间的赋值 例如:int a = 1.0;目标类型是被赋值对象的类型。
  • 算数表达式中存在不同数据类型的数运算,例如int a = 1;double b = 2.0; int c = a b;
  • 将一个表达式作为实参传递给函数调用,此时形参和实参类型不一致:目标转换类型为形参的类型
  • 从一个函数返回一个表达式,表达式类型与返回类型不一致:目标转换类型为函数的返回类型
    c 11表达中,不同数据进行运算时的校验规则(与c语言稍有区别):
  • 如果其中有一个数为long double,那么另一个就被转换为long double
  • 否则,如果有一个数double,那么另一个就被转换为double
  • 否则,如果有一个数为float,那么另一个数就被转换为float
  • 否则,否则说明操作数都是整型,执行整型提升
  • 如果两个操作数同是有符号或同是无符号,这转换为等级较高的类型进行运算
  • 如果一个有符号一个无符号,且无符号类型级别高,这转换无符号数运算
  • 否则,如果有符号可以表示所有无符号取值,这转换为有符号类型运算
  • 否则,将两个数都转换为有符号数的无符号版本运算

显示类型转换

(typename)value; // c语言风格 typename(value); // c 风格

此外,c 还提供了四个关键字来实现转换,与传统强制转换相比,其转换更加严格

static_cast (expression); //该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。 dynamic_cast (expression); //该运算符把expression转换成type-id类型的对象。type-id必须是类的指针、类的引用或者void *;如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。 reinpreter_cast (expression); // type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值) const_cast (expression); // 用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。

显示对浮点数进行强制转换时,规则如下:

较大浮点转较小浮点,例如double转float精度降低,如果超出float范围,结果不确定
浮点型转整型小数被省略,如果超出float范围,结果不确定
较大整型转较小整型,例如long转int如果超出int范围,通常只复制右边的值

潜在的数据转换问题

复合数据类型由基本数据类型组成,c 中类就是一种符合数据类型。此外数组、字符串、结构体、共同体、枚举、指针和自由存储空间都作为复合数据类型

数组(c/c )

  • 如果只对数组部分赋值,后面的默认为零。

  • 不能将一个数组赋值给另一个数组。

  • 指针和二维数组(c/c )

    指针

    首先,指针也是一个变量,其在内存中一般占用4个字节。比较特殊的是,指针变量中存放的值是一个地址。例如:
    int *p;
    这里,定义了一个指针,编译器在内存中拿出4个字节,名字叫p,里面存放一个4字节的地址。对于未初始化的指针,其值是随机的,很危险!
    常见的指针操作:*与 、–

    int a=2, b=5, c, d, *p; p = &a;(*p); // 等价于a c = *p; // 等价于 c = *p; p; 两句 d = *p // 等价于 p; d = *p; 两句

    指针和引用的联系与区别(仅c )
    (1)指针是一个实体,而引用仅是个别名;
    (2)引用使用时无需解引用(*),指针需要解引用;
    (3)引用只能在定义时被初始化一次,之后不可变;指针可变;
    (4)引用没有 const,指针有 const;
    (5)引用不能为空,指针可以为空;
    (6)“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;
    (7)指针和引用的自增( )运算意义不一样;
    (8)从内存分配上看:程序为指针变量分配内存区域,而引用不需要分配内存区域。
    在说明指针的时候,有必要额外说明一下二维数组。

    char str1[] = "abc"; char str2[] = "abc"; const char str3[] = "abc"; const char str4[] = "abc"; const char *str5 = "abc"; const char *str6 = "abc"; char *str7 ="abc"; char *str8 = "abc"; cout << ( str1 == str2 ) << endl; cout << ( str3 == str4 ) << endl; cout << ( str5 == str6 ) << endl; cout << ( str7 == str8 ) <以上的输出结果为:0 0 1 1

    二维数组

      有很多地方说数组就是指针,这是错误的一种说法。这两者是不同的数据结构。其实,在c/c 中没有所谓的二维数组,书面表达就是数组的数组。为了表述方便才叫它二维数组。二维数组在概念上是二维的,即其下标在两个方向上变化,下标变量在数组中的位置也处于一个平面之中,而不是像一维数组只是一个向量。但是,实际的硬件存储器却是连续编址的,也就是说存储器单元是按一维线性排列的。如何在一维存储器中存放二维数组,可有两种方式:一种是按行排放, 即放完一行之后顺次放入第二行。另一种是按列排放, 即放完一列之后再顺次放入第二列。
      在c语言中,二维数组是按行排列的。即,先存放a[0]行,再存放a[1]行,最后存放a[n]行。每行中的元素也是依次存放。例如对数组a[5][3]赋值两种方式(结果完全相同):

    • 按行分段赋值可写为:
      int a[5][3]={ {80,75,92}, {61,65,71}, {59,63,70}, {85,87,90}, {76,77,85} };
    • 按行连续赋值可写为:
      int a[5][3]={ 80,75,92,61,65,71,59,63,70,85,87,90,76,77,85};
      注意:
    • 可以只对部分元素赋初值,未赋初值的元素自动取0值。
    • 如果对全部元素赋初值,则第一维的长度可以不给出,例如:int a[][3]={1,2,3,4,5,6,7,8,9};

    二维数组一维化

      我们可以用一个指向int型的指针变量来访问这个数组,下面的代码是将数组一维化(以上面的a数组为例):

    int *p = a[0]; // 这样就可以用 p 访问每个元素了 p[3] // 第三个元素 *(p 3) // 这个 = p[3]

    这样就实现了将二维数组一维化,通过p访问的是每个元素,而不是行

    数组指针和指针数组

    指针数组: 指针数组就是个数组,只不过元素是指针。定义方式如:int *p[3]; 表示三个指针,分别为:p[0]、p[1]、p[2]
    数组指针: 指向数组的指针。定义方式如:int (*p)[3]; 表示 p指向的是一个数组元素为int类型并且数组元素的个数为3的一个指针。

    int (*parr)[3] = a; *(*(parr 1) 2) // 这就相当于 a[1][2]

    上例中,parr是个数组指针,每次 1是移动一行,不是一个元素。比如说,parr 1代表的现在指针已经指向第一行元素了(0行开始),而要取得指针所指的对象,就要用到解引用运算符,所以(parr 1)就代表第一行数组,是整个这一行元素就取到了,那现在要取这一行的第二个元素,只须将指针再移动两个元素,即*(iarr 1) 2,这样就指向了这个元素的地址,再解引用取得元素的值即可。

    也许我们应该这样来数组指针:
    int (*)[10] p2;
    int (*)[10]是指针类型,p2 是指针变量。这样看起来的确不错,不过就是样子有些别扭。其实数组指针的原型确实就是这样子的,只不过为了方便与好看把指针变量p2 前移了而已。
    既然这样,那问题就来了。现在再来看看下面的代码:

    int main() {char a[5]={'a','b','c','d'};char (*p3)[5] = &a;char (*p4)[5] = a; //必须使用强制转换,如:char (*p2)[5]=(char (*)[5])a;return 0; }

    上面对p3 和p4 的使用,哪个正确呢?p3 1 的值会是什么?p4 1 的值又会是什么?
    毫无疑问,p3 和p4 都是数组指针,指向的是整个数组。&a 是整个数组的首地址,a是数组首元素的首地址,其值相同但意义不同。在c 语言里,赋值符号“=”号两边的数据类型必须是相同的,如果不同需要显示或隐式的类型转换。p3 这个定义的“=”号两边的数据类型完全一致,而p4 这个定义的“=”号两边的数据类型就不一致了。左边的类型是指向整个数组的指针,右边的数据类型是指向单个字符的指针。在visual c 6.0 上给出如下警告:
    warning c4047: 'initializing' : 'char (*)[5]' differs in levels of indirection from 'char *'。
    还好,这里虽然给出了警告,但由于&a 和a 的值一样,而变量作为右值时编译器只是取变量的值,所以运行并没有什么问题。不过我仍然警告你别这么用。
    但是如果修改一下代码,把数组大小改小点,会有什么问题?p3 1 和p4 1 的值又是多少呢?

    int main() {char a[5]={'a','b','c','d'};char (*p3)[3] = &a;char (*p4)[3] = a;return 0; }

    或把数组大小改大点:

    int main() {char a[5]={'a','b','c','d'};char (*p3)[10] = &a;char (*p4)[10] = a;return 0; }

    测试结果:把数组大小改变,都会编译不通过。

    地址的强制转换

    以下,以x86 windows为例

    #include int main() {int a[4]={1,2,3,4};int *ptr1=(int *)(&a 1);int *ptr2=(int *)((int)a 1);printf("%x,%x",ptr1[-1],*ptr2);return 0; }

    下面分析上面的数据结果

    ptr1: a为数组名,那么&a 1不是增一个int,而是(int*)(a的地址 sizeof(a)),因此ptr1指向了数组结尾的第一个字节。
    可以这样理解:不管是增1还是减1,这里的1都是sizeof(类型),上面对a取地址,可认为此时类型为int a[4],这里增的是sizeof(a)
    ptr2: 任何数值一旦被强制转换,其类型就改变了。这里实际上就是将地址a,转换为了数,然后 1,把转换后的数再次转换为地址。如下图:

    字符串

    c 有两种风格的字符串,一种是c语言风格的,一种是c 语言风格string。

    c语言风格字符串

    c语言风格的字符串以空字符结尾,空字符被写作\0,ascii码为0。c不会检查字符串长度是否越界。
    对于c风格的字符串操作一般通过库函数来实现,在头文件string.h中(c cstring)包换大量字符串操作的函数。

    要保证目的字符串可以容纳原字符串,否则,编译不会出错,但是运行时,会出现错误:stack around the variable ‘xxx’ was corrupted.

    c 字符串 string

    ios/ansi c 98标准添加了string类,使用者可以直接将它作为一种数据类型来用,定义字符串变量(对象)。要使用string类必须包含头文件string,而且string位于std命名空间中。
    详细的使用方法见文件: 双击图标查看!

    结构体

    无论在c还是c 中,结构体都是很常用的一种数据类型。结构体名,用作结构体类型的标志,它又称结构体标记。大括号内是该结构体中的成员列表,又称为域表。

    结构体的内存对齐

    结构体内存分配的原则:编译器按照成员列表顺序一个接一个地给每个成员分配内存。只有当存储成员需要满足正确的边界对齐要求时,成员之间才可能出现用于填充的额外内存空间。如果不按照平台要求对数据存放进行对齐,会带来存取效率上的损失。此外,合理利用字节对齐还可以有效地节省存储空间。但要注意,在32位机中使用1字节或2字节对齐,反而会降低变量访问速度。因此需要考虑处理器类型。还应考虑编译器的类型。在vc/c 和gnu gcc中都是默认是4字节对齐。
    结构体字节对齐的细节和具体编译器实现相关,但一般而言满足三个准则:
    1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
    2) 结构体每个成员相对结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
    3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节{trailing padding}。

    位域(位段)

    有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,c语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。定义方式如下:

    struct 位域结构名 { 类型说明符 位域名:位域长度 }; 例: struct bs {int a:8; // 8个二进制位int b:2; // 2个二进制位int c:6; // 6个二进制位 };

    位域需要遵循以下规则:
    1. 位域的长度不能大于数据类型本身的长度,比如int类型就能超过32位二进位。有其他人说是不能超过8位,我在我的机子上是可以实现int :32的位域长度的。
    2. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的
    3. 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
    4. 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
    5. 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,vc6采取不压缩方式(不同位域字段存放在不同的位域类型字节中),dev-c 和gcc都采取压缩方式;
    6. 如果位域字段之间穿插着非位域字段,则不进行压缩
    7. 整个结构体的总大小为最宽基本类型成员大小的整数倍
    8. c99规定int、unsigned int和bool可以作为位域类型

    系统会先为结构体成员按照对齐方式分配空间和填塞(padding),然后对变量进行位域操作。

    举例如下:

    #include #include using namespace std; struct a {int a:5;int b:3; }; int main(void) {char str[100] = "0134324324afsadfsdlfjlsdjfl";struct a d;memcpy(&d, str, sizeof(a));cout << d.a << endl;cout << d.b << endl;return 0; }

    如上代码,执行结果如下:

    分析:
    高位 00110100 00110011 00110001 00110000 低位
    ‘4’ ‘3’ ‘1’ ‘0’ // 以上二进制位字符的ascii码
    其中d.a和d.b共同占用低位一个字节(00110000), d.a : 10000, d.b : 001
    然后,int 是有符号的。所以d.a对应的数为11111111 11111111 11111111 11110000;d.b对应的二进制为10000000 00000000 00000000 00000001
    同理,如果int a:5改为了int a:16,此时,d.a对应的值就是10000000 00000000 00110001 00110000

    共同体(联合体)

    共同体是一种数据格式,它能够存储不同的数据类型,但同时只能存储一种。
    匿名共同体:定义时,直接省去共同体的名称,但这里一般同时定义一个对象,因为没有名字以后就没法定义了!除非是放在其他结构里面,可以不定义对象。

    关于共同体的嵌套

    注:结构体与联合体有何区别?

  • 结构体变量所占内存长度是各成员占的内存长度的总和(不考虑内存对其)。联合体变量所占内存长度是最长的成员占的内存长度。
  • 结构体和联合体都是由多个不同的数据类型成员组成,但在任何同一时刻,联合中只存放了一个被选中的成员(所有成员共用一块地址空间), 而结构的所有成员都存在(不同成员的存放地址不同)。
  • 对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了,而对于结构的不同成员赋值是互不影响的。
  • 枚举

    1、枚举值默认从零开始,后面的比前面的增加1
    2、c早期版本规定,枚举赋值必须是int型,现在该限制被取消了,赋值可以是long、long long
    3、可以定义具有相同值的枚举值
    在c 98中enum变量的实际大小由编译器决定,只要能够保存enum的成员即可,而在将要发布的新的c 0x中,可以指定enum的实际实现类型,如实现为int类型。
    enum month:int{ jan, feb, …, dec }

    其他类型:自由存储

    单独说明

    总结

    以上是凯发ag旗舰厅登录网址下载为你收集整理的c/c 之数据类型的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得凯发ag旗舰厅登录网址下载网站内容还不错,欢迎将凯发ag旗舰厅登录网址下载推荐给好友。

    网站地图