数据类型


程序在执行的过程中,需要运算许多的信息,也需要存储许多的信息,信息是存储在内存空间中,由于数据的类型各不相同,在存储时所需要的容量不一,不同的数据必须要配给不同的空间大小来存储,因而有了数据类型(Data type)的规范。

C 的基本数据类型主要区分为整数(Integer)、浮点数(Float)、字符(Character),而这几种还可以细分,如下所示:

  • 整数 用来表示整数值,可以区分为 short、int、long 与 long long(C99),配置的内存长度在不同编译器上各不相同,可容纳的大小各不相同,例如,在 64 位 Ubuntu 16.04 中的 gcc 编译器下,int 与 long 为 8 字节,在 Windows 10 使用 MinGW-w64,GNU 编译器版本是 8.1.0 类型的话,int 与 long 为 4 字节,长度越长,表示可表示的整数值范围越大。
  • 浮点数 用来表示小数值,可以区分为 float、double 与 long double,越后面的类型使用的内存空间越大,精度也就越高。
  • 字符 char 的 sizeof(char) 结果要是 1,基本上用来存储字符数据,但没有规定什么是字符数据,也可用来存储较小范围的整数。 与字符相关的类型,其实还有来自 C89 的 wchar_t,以及 C11 标准规范的 char16_t、char32_t(定义在 unchar.h 标头文件)。

在 C11 标准中,建议包括 stdint.h 程序库,使用int8_tint16_tint32_tint64_tuint8_tuint16_tuint32_tuint64_t等作为整数类型的定义,以避免平台依赖性的问题。

以上的数据类型在内存中占有的大小依编译器而有所差异,想知道这些数据类型在使用的平台上,占有的内存空间有多少,可以使用sizeof运算符,它可以告诉你确实的内存大小,下面这个程序是个简单的示范:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    printf("类型\t\t大小(bytes)\n");
    printf("short\t\t%lu\n", sizeof(short));
    printf("int\t\t%lu\n", sizeof(int));
    printf("long\t\t%lu\n", sizeof(long));
    printf("float\t\t%lu\n", sizeof(float));
    printf("double\t\t%lu\n", sizeof(double));
    printf("long double\t%lu\n", sizeof(long double));
    printf("char\t\t%lu\n", sizeof(char));

    return 0;
}

其中'\t'是跳格字符,它相当于在控制台中按下 Tab 键的效果,可以用来对齐下一个显示位置,%lu为格式指定码,表示该位置将放置一个long unsigned类型的整数,也就是由sizeof()所计算出来的数字取代,在控制台输出输入(Input/Output)中,将针对格式控制作进一步说明。

以下是执行结果:

类型            大小(bytes)
short           2
int             4
long            4
float           4
double          8
long double     12
char            1

由于平台不同,你的执行结果不一定会与这边相同;因为每种数据类型占有的内存大小不同,因而可以存储的数值范围也就不同。

例如在上例中,整数int的内存空间是 4 个字节,可以存储的整数范围为 -2147483648 至 2147483647,如果存储值超出这个范围的话称之为「溢值」 (Overflow),会造成程序不可预期的结果。

整数计算范围的方式很简单,例如int整数占 4 字节的话,可存储范围为 2^32 / 2,除以 2 是因为要分另一半存储负整数的关系,整数的最左边位被用来表示正负号,如果最左边位为 0 表示正号,若为 1 表示负号。

在 C 中可以使用signedunsigned定义有符号、无符号整数,无符号整数最左边位不用来表示正负号,例如一个 8 位字符被用来表示整数时,可以表示数值 -128 到 127,而一个无符号字符可以表示 0 到 255 的正整数。

size_t是个机器特定的无符号类型,定义于stddef.h标头文件,保证够大可以容纳任何对象,若数据结构具有长度或索引概念,而且需要很大的容量,例如数组,可以使用size_t类型变量来实现长度或索引。

浮点数的存储方式则是分为两个部份,例如float占四个字节的话,前三个字节用来存储假数,后一个字节存储指数,例如 3.14 * 108, 3.14 存储在前三字节,而 8 存储于后一字节,所以float大致上可以存储的范围为 1038 到 10-38(就指数来算出的),而double可以大致存储 10308 至 10^-308 之间的数值。

C 语言一开始并没有布尔值类型,而是将空值或 NULL 视为不成立,其他值都是成立,C99 有bool名称,定义于 stdbool.h,用来表示布尔数,是 C99 布尔类型_Bool的宏(也就是会编译后会展开为_Bool),在程序中占一个字节,也可以使用宏truefalse字面常量(Literal constant)来表示,展开后成为 1 与 0:

#include <stdio.h>
#include <stdbool.h>

int main(void) {
    printf("sizeof(bool)\t%d\n", sizeof(bool));
    printf("sizeof(true)\t%d\n",  sizeof(true));
    printf("sizeof(false)\t%d\n",  sizeof(false));

    printf("true\t%d\n", true);
    printf("false\t%d\n", false);

    return 0;
}

执行结果:

sizeof(bool)    1
sizeof(true)    4
sizeof(false)   4
true    1
false   0




展开阅读全文