当前位置:主页C 语言入门教程

6. 数据类型

文章来源:知付 更新时间:2022-05-28 16:09 热度:410

C 语言的每一种数据,都是有类型(type)的,编译器必须知道数据的类型,才能操作数据。所谓“类型”,就是相似的数据所拥有的共同特征,那么一旦知道某个值的数据类型,就能知道该值的特征和操作方式。

基本数据类型有三种:字符(char)、整数(int)和浮点数(float)。复杂的类型都是基于它们构建的。

目录
  • 字符类型

  • 整数类型

  • 简介

  • signed,unsigned

  • 整数的子类型

  • 整数类型的极限值

  • 整数的进制

  • 浮点数类型

  • 布尔类型

  • 字面量的类型

  • 字面量后缀

  • 溢出

  • sizeof 运算符

  • 类型的自动转换

  • 赋值运算

  • 混合类型的运算

  • 整数类型的运算

  • 函数

  • 类型的显式转换

  • 可移植类型

字符类型

字符类型指的是单个字符,类型声明使用 char 关键字。

char c = 'B';

上面示例声明了变量 c 是字符类型,并将其赋值为字母 B

C 语言规定,字符常量必须放在单引号里面。

在计算机内部,字符类型使用一个字节(8位)存储。C 语言将其当作整数处理,所以字符类型就是宽度为一个字节的整数。每个字符对应一个整数(由 ASCII 码确定),比如 B 对应整数 66

字符类型在不同计算机的默认范围是不一样的。一些系统默认为 -128127 ,另一些系统默认为 0255 。这两种范围正好都能覆盖 0127 的 ASCII 字符范围。

只要在字符类型的范围之内,整数与字符是可以互换的,都可以赋值给字符类型的变量。

char c = 66;
// 等同于
char c = 'B';

上面示例中,变量 c 是字符类型,赋给它的值是整数66。这跟赋值为字符 B 的效果是一样的。

两个字符类型的变量可以进行数学运算。

char a = 'B'; // 等同于 char a = 66;
char b = 'C'; // 等同于 char b = 67;

printf("%dn", a + b); // 输出 133

上面示例中,字符类型变量 ab 相加,视同两个整数相加。占位符 %d 表示输出十进制整数,因此输出结果为133。

单引号本身也是一个字符,如果要表示这个字符常量,必须使用反斜杠转义。

char t = ''';

上面示例中,变量 t 为单引号字符,由于字符常量必须放在单引号里面,所以内部的单引号要使用反斜杠转义。

这种转义的写法,主要用来表示 ASCII 码定义的一些无法打印的控制字符,它们也属于字符类型的值。

  • a :警报,这会使得终端发出警报声或出现闪烁,或者两者同时发生。

  • b :退格键,光标回退一个字符,但不删除字符。

  • f :换页符,光标移到下一页。在现代系统上,这已经反映不出来了,行为改成类似于 v

  • n :换行符。

  • r :回车符,光标移到同一行的开头。

  • t :制表符,光标移到下一个水平制表位,通常是下一个8的倍数。

  • v :垂直分隔符,光标移到下一个垂直制表位,通常是下一行的同一列。

  • 0 :null 字符,代表没有内容。注意,这个值不等于数字0。

转义写法还能使用八进制和十六进制表示一个字符。

  • nn :字符的八进制写法, nn 为八进制值。

  • xnn :字符的十六进制写法, nn 为十六进制值。

char x = 'B';
char x = 66;
char x = '102'; // 八进制
char x = 'x42'; // 十六进制

上面示例的四种写法都是等价的。

整数类型

简介

整数类型用来表示较大的整数,类型声明使用 int 关键字。

int a;

上面示例声明了一个整数变量 a

不同计算机的 int 类型的大小是不一样的。比较常见的是使用4个字节(32位)存储一个 int 类型的值,但是2个字节(16位)或8个字节(64位)也有可能使用。它们可以表示的整数范围如下。

  • 16位:-32,768 到 32,767。

  • 32位:-2,147,483,648 到 2,147,483,647。

  • 64位:-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807。

signed,unsigned

C 语言使用 signed 关键字,表示一个类型带有正负号,包含负值;使用 unsigned 关键字,表示该类型不带有正负号,只能表示零和正整数。

对于 int 类型,默认是带有正负号的,也就是说 int 等同于 signed int 。由于这是默认情况,关键字 signed 一般都省略不写,但是写了也不算错。

signed int a;
// 等同于
int a;

int 类型也可以不带正负号,只表示非负整数。这时就必须使用关键字 unsigned 声明变量。

unsigned int a;

整数变量声明为 unsigned 的好处是,同样长度的内存能够表示的最大整数值,增大了一倍。比如,16位的 signed int 最大值为32,767,而 unsigned int 的最大值增大到了65,535。

unsigned int 里面的 int 可以省略,所以上面的变量声明也可以写成下面这样。

unsigned a;

字符类型 char 也可以设置 signedunsigned

signed char c; // 范围为 -128 到 127
unsigned char c; // 范围为 0 到 255

注意,C 语言规定 char 类型默认是否带有正负号,由当前系统决定。这就是说, char 不等同于 signed char ,它有可能是 signed char ,也有可能是 unsigned char 。这一点与 int 不同, int 就是等同于 signed int

整数的子类型

如果 int 类型使用4个或8个字节表示一个整数,对于小整数,这样做很浪费空间。另一方面,某些场合需要更大的整数,8个字节还不够。为了解决这些问题,C 语言在 int 类型之外,又提供了三个整数的子类型。这样有利于更精细地限定整数变量的范围,也有利于更好地表达代码的意图。

  • short int (简写为 short ):占用空间不多于 int ,一般占用2个字节(整数范围为-32768~32767)。

  • long int (简写为 long ):占用空间不少于 int ,至少为4个字节。

  • long long int (简写为 long long ):占用空间多于 long ,至少为8个字节。

short int a;
long int b;
long long int c;

上面代码分别声明了三种整数子类型的变量。

默认情况下, shortlonglong long 都是带符号的(signed),即 signed 关键字省略了。它们也可以声明为不带符号(unsigned),使得能够表示的最大值扩大一倍。

unsigned short int a;
unsigned long int b;
unsigned long long int c;

C 语言允许省略 int ,所以变量声明语句也可以写成下面这样。

short a;
unsigned short a;

long b;
unsigned long b;

long long c;
unsigned long long c;

不同的计算机,数据类型的字节长度是不一样的。确实需要32位整数时,应使用 long 类型而不是 int 类型,可以确保不少于4个字节;确实需要64位的整数时,应该使用 long long 类型,可以确保不少于8个字节。另一方面,为了节省空间,只需要16位整数时,应使用 short 类型;需要8位整数时,应该使用 char 类型。

整数类型的极限值

有时候需要查看,当前系统不同整数类型的最大值和最小值,C 语言的头文件 limits.h 提供了相应的常量,比如 SCHAR_MIN 代表 signed char 类型的最小值 -128SCHAR_MAX 代表 signed char 类型的最大值 127

为了代码的可移植性,需要知道某种整数类型的极限值时,应该尽量使用这些常量。

  • SCHAR_MINSCHAR_MAX :signed char 的最小值和最大值。

  • SHRT_MINSHRT_MAX :short 的最小值和最大值。

  • INT_MININT_MAX :int 的最小值和最大值。

  • LONG_MINLONG_MAX :long 的最小值和最大值。

  • LLONG_MINLLONG_MAX :long long 的最小值和最大值。

  • UCHAR_MAX :unsigned char 的最大值。

  • USHRT_MAX :unsigned short 的最大值。

  • UINT_MAX :unsigned int 的最大值。

  • ULONG_MAX :unsigned long 的最大值。

  • ULLONG_MAX :unsigned long long 的最大值。

整数的进制

C 语言的整数默认都是十进制数,如果要表示八进制数和十六进制数,必须使用专门的表示法。

八进制使用 0 作为前缀,比如 0170377

int a = 012; // 八进制,相当于十进制的10

十六进制使用 0x0X 作为前缀,比如 0xf0X10

int a = 0x1A2B; // 十六进制,相当于十进制的6699

有些编译器使用 0b 前缀,表示二进制数,但不是标准。

int x = 0b101010;

注意,不同的进制只是整数的书写方法,不会对整数的实际存储方式产生影响。所有整数都是二进制形式存储,跟书写方式无关。不同进制可以混合使用,比如 10 + 015 + 0x20 是一个合法的表达式。

printf() 的进制相关占位符如下。

  • %d :十进制整数。

  • %o :八进制整数。

  • %x :十六进制整数。

  • %#o :显示前缀 0 的八进制整数。

  • %#x :显示前缀 0x 的十六进制整数。

  • %#X :显示前缀 0X 的十六进制整数。

int x = 100;
printf("dec = %dn", x); // 100
printf("octal = %on", x); // 144
printf("hex = %xn", x); // 64
printf("octal = %#on", x); // 0144
printf("hex = %#xn", x); // 0x64
printf("hex = %#Xn", x); // 0X64

浮点数类型

任何有小数点的数值,都会被编译器解释为浮点数。所谓“浮点数”就是使用 m * be 的形式,存储一个数值, m 是小数部分, b 是基数(通常是 2 ), e 是指数部分。这种形式是精度和数值范围的一种结合,可以表示非常大或者非常小的数。

浮点数的类型声明使用 float 关键字,可以用来声明浮点数变量。

float c = 10.5;

上面示例中,变量 c 的就是浮点数类型。

float 类型占用4个字节(32位),其中8位存放指数的值和符号,剩下24位存放小数的值和符号。 float 类型至少能够提供(十进制的)6位有效数字,指数部分的范围为(十进制的) -3737 ,即数值范围为10-37到1037。

有时候,32位浮点数提供的精度或者数值范围还不够,C 语言又提供了另外两种更大的浮点数类型。

  • double :占用8个字节(64位),至少提供13位有效数字。

  • long double :通常占用16个字节。

注意,由于存在精度限制,浮点数只是一个近似值,它的计算是不精确的,比如 C 语言里面 0.1 + 0.2 并不等于 0.3 ,而是有一个很小的误差。

if (0.1 + 0.2 == 0.3) // false

C 语言允许使用科学计数法表示浮点数,使用字母 e 来分隔小数部分和指数部分。

double x = 123.456e+3; // 123.456 x 10^3
// 等同于
double x = 123.456e3;

上面示例中, e 后面如果是加号 + ,加号可以省略。注意,科学计数法里面 e 的前后,不能存在空格。

另外,科学计数法的小数部分如果是 0.xx.0 的形式,那么 0 可以省略。

0.3E6
// 等同于
.3E6

3.0E6
// 等同于
3.E6

布尔类型

C 语言原来并没有为布尔值单独设置一个类型,而是使用整数 0 表示伪,所有非零值表示真。

int x = 1;
if (x) {
  printf("x is true!n");
}

上面示例中,变量 x 等于 1 ,C 语言就认为这个值代表真,从而会执行判断体内部的代码。

C99 标准添加了类型 _Bool ,表示布尔值。但是,这个类型其实只是整数类型的别名,还是使用 0 表示伪, 1 表示真,下面是一个示例。

_Bool isNormal;

isNormal = 1;
if (isNormal)
  printf("Everything is OK.n");

头文件 stdbool.h 定义了另一个类型别名 bool ,并且定义了 true 代表 1false 代表 0 。只要加载这个头文件,就可以使用这几个关键字。

#include <stdbool.h>

bool flag = false;

上面示例中,加载头文件 stdbool.h 以后,就可以使用 bool 定义布尔值类型,以及 falsetrue 表示真伪。

字面量的类型

字面量(literal)指的是代码里面直接出现的值。

int x = 123;

上面代码中, x 是变量, 123 就是字面量。

编译时,字面量也会写入内存,因此编译器必须为字面量指定数据类型,就像必须为变量指定数据类型一样。

一般情况下,十进制整数字面量(比如 123 )会被编译器指定为 int 类型。如果一个数值比较大,超出了 int 能够表示的范围,编译器会将其指定为 long int 。如果数值超过了 long int ,会被指定为 unsigned long 。如果还不够大,就指定为 long longunsigned long long

小数(比如 3.14 )会被指定为 double 类型。

字面量后缀

有时候,程序员希望为字面量指定一个不同的类型。比如,编译器将一个整数字面量指定为 int 类型,但是程序员希望将其指定为 long 类型,这时可以为该字面量加上后缀 lL ,编译器就知道要把这个字面量的类型指定为 long

int x = 123L;

上面代码中,字面量 123 有后缀 L ,编译器就会将其指定为 long 类型。这里 123L 写成 123l ,效果也是一样的,但是建议优先使用 L ,因为小写的 l 容易跟数字 1 混淆。

八进制和十六进制的值,也可以使用后缀 lL 指定为 Long 类型,比如 020L0x20L

int y = 0377L;
int z = 0x7fffL;

如果希望指定为无符号整数 unsigned int ,可以使用后缀 uU

int x = 123U;

LU 可以结合使用,表示 unsigned long 类型。 LU 的大小写和组合顺序无所谓。

int x = 123LU;

对于浮点数,编译器默认指定为 double 类型,如果希望指定为其他类型,需要在小数后面添加后缀 f (float)或 l (long double)。

科学计数法也可以使用后缀。

1.2345e+10F
1.2345e+10L

总结一下,常用的字面量后缀有下面这些。

  • fFfloat 类型。

  • lL :对于整数是 long int 类型,对于小数是 long double 类型。

  • llLL :Long Long 类型,比如 3LL

  • uU :表示 unsigned int ,比如 15U0377U

    u 还可以与其他整数后缀结合,放在前面或后面都可以,比如 10UL10ULL10LLU 都是合法的。

下面是一些示例。

int           x = 1234;
long int      x = 1234L;
long long int x = 1234LL

unsigned int           x = 1234U;
unsigned long int      x = 1234UL;
unsigned long long int x = 1234ULL;

float x       = 3.14f;
double x      = 3.14;
long double x = 3.14L;

溢出

每一种数据类型都有数值范围,如果存放的数值超出了这个范围(小于最小值或大于最大值),需要更多的二进制位存储,就会发生溢出。大于最大值,叫做向上溢出(overflow);小于最小值,叫做向下溢出(underflow)。

一般来说,编译器不会对溢出报错,会正常执行代码,但是会忽略多出来的二进制位,只保留剩下的位,这样往往会得到意想不到的结果。所以,应该避免溢出。

unsigned char x = 255;
x = x + 1;

printf("%dn", x); // 0

上面示例中,变量 x1 ,得到的结果不是 256 ,而是 0 。因为 xunsign char 类型,最大值是 255 (二进制 11111111 ),加 1 后就发生了溢出, 256 (二进制 100000000 )的最高位 1 被丢弃,剩下的值就是 0

再看下面的例子。

unsigned int ui = UINT_MAX;  // 4,294,967,295
ui++;
printf("ui = %un", ui); // 0
ui--;
printf("ui = %un", ui); // 4,294,967,295

上面示例中,常量 UINT_MAX 是 unsigned int 类型的最大值。如果加 1 ,对于该类型就会溢出,从而得到 0 ;而 0 是该类型的最小值,再减 1 ,又会得到 UINT_MAX

溢出很容易被忽视,编译器又不会报错,所以必须非常小心。

for (unsigned int i = n; i >= 0; --i) // 错误

上面代码表面看似乎没有问题,但是循环变量 i 的类型是 unsigned int,这个类型的最小值是 0 ,不可能得到小于0的结果。当 i 等于0,再减去 1 的时候,并不会返回 -1 ,而是返回 unsigned int 的类型最大值,这个值总是大于等于 0 ,导致无限循环。

为了避免溢出,最好方法就是将运算结果与类型的极限值进行比较。

unsigned int ui;
unsigned int sum;

// 错误
if (sum + ui > UINT_MAX) too_big();
else sum = sum + ui;

// 正确
if (ui > UINT_MAX - sum) too_big();
else sum = sum + ui;

上面示例中,变量 sumui 都是 unsigned int 类型,它们相加的和还是 unsigned int 类型,这就有可能发生溢出。但是,不能通过相加的和是否超出了最大值 UINT_MAX ,来判断是否发生了溢出,因为 sum + ui 总是返回溢出后的结果,不可能大于 UINT_MAX 。正确的比较方法是,判断 UINT_MAX - sumui 之间的大小关系。

下面是另一种错误的写法。

unsigned int i = 5;
unsigned int j = 7;

if (i - j < 0) // 错误
  printf("negativen");
else
  printf("positiven");

上面示例的运算结果,会输出 positive 。原因是变量 ij 都是 unsigned int 类型, i - j 的结果也是这个类型,最小值为 0 ,不可能得到小于 0 的结果。正确的写法是写成下面这样。

if (j > i) // ....

sizeof 运算符

sizeof 是 C 语言提供的一个运算符,返回某种数据类型或某个值占用的字节数量。它的参数可以是数据类型的关键字,也可以是变量名或某个具体的值。

// 参数为数据类型
int x = sizeof(int);

// 参数为变量
int i;
sizeof(i);

// 参数为数值
sizeof(3.14);

上面的第一个示例,返回得到 int 类型占用的字节数量(通常是 48 )。第二个示例返回整数变量占用字节数量,结果与前一个示例完全一样。第三个示例返回浮点数 3.14 占用的字节数量,由于浮点数的字面量一律存储为 double 类型,所以会返回 8 ,因为 double 类型占用的8个字节。

sizeof 运算符的返回值,C 语言只规定是无符号整数,并没有规定具体的类型,而是留给系统自己去决定, sizeof 到底返回什么类型。不同的系统中,返回值的类型有可能是 unsigned int ,也有可能是 unsigned long ,甚至是 unsigned long long ,对应的 printf() 占位符分别是 %u%lu%llu 。这样不利于程序的可移植性。

C 语言提供了一个解决方法,创造了一个类型别名 size_t ,用来统一表示 sizeof 的返回值类型。该别名定义在 stddef.h 头文件(引入 stdio.h 时会自动引入)里面,对应当前系统的 sizeof 的返回值类型,可能是 unsigned int ,也可能是 unsigned long

C 语言还提供了一个常量 SIZE_MAX ,表示 size_t 可以表示的最大整数。所以, size_t 能够表示的整数范围为 [0, SIZE_MAX]

printf() 有专门的占位符 %zd%zu ,用来处理 size_t 类型的值。

printf("%zdn", sizeof(int));

上面代码中,不管 sizeof 返回值的类型是什么, %zd 占位符(或 %zu )都可以正确输出。

如果当前系统不支持 %zd%zu ,可使用 %u (unsigned int)或 %lu (unsigned long int)代替。

类型的自动转换

某些情况下,C 语言会自动转换某个值的类型。

赋值运算

赋值运算符会自动将右边的值,转成左边变量的类型。

(1)浮点数赋值给整数变量

浮点数赋予整数变量时,C 语言直接丢弃小数部分,而不是四舍五入。

int x = 3.14;

上面示例中,变量 x 是整数类型,赋给它的值是一个浮点数。编译器会自动把 3.14 先转为 int 类型,丢弃小数部分,再赋值给 x ,因此 x 的值是 3

这种自动转换会导致部分数据的丢失( 3.14 丢失了小数部分),所以最好不要跨类型赋值,尽量保证变量与所要赋予的值是同一个类型。

注意,舍弃小数部分时,不是四舍五入,而是整个舍弃。

int x = 12.99;

上面示例中, x 等于 12 ,而不是四舍五入的 13

(2)整数赋值给浮点数变量

整数赋值给浮点数变量时,会自动转为浮点数。

float y = 12 * 2;

上面示例中,变量 y 的值不是 24 ,而是 24.0 ,因为等号右边的整数自动转为了浮点数。

(3)窄类型赋值给宽类型

字节宽度较小的整数类型,赋值给字节宽度较大的整数变量时,会发生类型提升,即窄类型自动转为宽类型。

比如, charshort 类型赋值给 int 类型,会自动提升为 int

char x = 10;
int i = x + y;

上面示例中,变量 x 的类型是 char ,由于赋值给 int 类型,所以会自动提升为 int

(4)宽类型赋值给窄类型

字节宽度较大的类型,赋值给字节宽度较小的变量时,会发生类型降级,自动转为后者的类型。这时可能会发生截值(truncation),系统会自动截去多余的二进制位,导致难以预料的结果。

int i = 321;
char ch = i; // ch 的值是 65 (321 - 256)

上面例子中,变量 chchar 类型,宽度是8个二进制位。变量 iint 类型,将 i 赋值给 ch ,后者只能容纳 i (二进制形式为 101000001 ,共9位)的后八位,前面多出来的二进制位被丢弃,保留后八位就变成了 01000001 (十进制的65,相当于字符 A )。

浮点数赋值给整数类型的值,也会发生截值,浮点数的小数部分会被截去。

double pi = 3.14159;
int i = pi; // i 的值为 3

上面示例中, i 等于 3pi 的小数部分被截去了。

混合类型的运算

不同类型的值进行混合计算时,必须先转成同一个类型,才能进行计算。转换规则如下:

(1)整数与浮点数混合运算时,整数转为浮点数类型,与另一个运算数类型相同。

3 + 1.2 // 4.2

上面示例是 int 类型与 float 类型的混合计算, int 类型的 3 会先转成 float3.0 ,再进行计算,得到 4.2

(2)不同的浮点数类型混合运算时,宽度较小的类型转为宽度较大的类型,比如 float 转为 doubledouble 转为 long double

(3)不同的整数类型混合运算时,宽度较小的类型会提升为宽度较大的类型。比如 short 转为 intint 转为 long 等,有时还会将带符号的类型 signed 转为无符号 unsigned

下面例子的执行结果,可能会出人意料。

int a = -5;
if (a < sizeof(int))
  do_something();

上面示例中,变量 a 是带符号整数, sizeof(int)size_t 类型,这是一个无符号整数。按照规则,signed int 自动转为 unsigned int,所以 a 会自动转成无符号整数 4294967291 (转换规则是 -5 加上无符号整数的最大值,再加1),导致比较失败, do_something() 不会执行。

所以,最好避免无符号整数与有符号整数的混合运算。因为这时 C 语言会自动将 signed int 转为 unsigned int ,可能不会得到预期的结果。

整数类型的运算

两个相同类型的整数运算时,或者单个整数的运算,一般来说,运算结果也属于同一类型。但是有一个例外,宽度小于 int 的类型,运算结果会自动提升为 int

unsigned char a = 66;

if ((-a) < 0) printf("negativen");
else printf("positiven");

上面示例中,变量 a 是 unsigned char 类型,这个类型不可能小于0,但是 -a 不是 unsigned char 类型,会自动转为 int 类型,导致上面的代码输出 negative。

再看下面的例子。

unsigned char a = 1;
unsigned char b = 255;
unsigned char c = 255;

if ((a - 5) < 0) do_something();
if ((b + c) > 300) do_something();

上面示例中,表达式 a - 5b + c 都会自动转为 int 类型,所以函数 do_something() 会执行两次。

函数

函数的参数和返回值,会自动转成函数定义里指定的类型。

int dostuff(int, unsigned char);

char m = 42;
unsigned short n = 43;
long long int c = dostuff(m, n);

上面示例中,参数变量 mn 不管原来的类型是什么,都会转成函数 dostuff() 定义的参数类型。

下面是返回值自动转换类型的例子。

char func(void) {
  int a = 42;
  return a;
}

上面示例中,函数内部的变量 aint 类型,但是返回的值是 char 类型,因为函数定义中返回的是这个类型。

类型的显式转换

原则上,应该避免类型的自动转换,防止出现意料之外的结果。C 语言提供了类型的显式转换,允许手动转换类型。

只要在一个值或变量的前面,使用圆括号指定类型 (type) ,就可以将这个值或变量转为指定的类型,这叫做“类型指定”(casting)。

(unsigned char) ch

上面示例将变量 ch 转成无符号的字符类型。

long int y = (long int) 10 + 12;

上面示例中, (long int)10 显式转为 long int 类型。这里的显示转换其实是不必要的,因为赋值运算符会自动将右边的值,转为左边变量的类型。

可移植类型

C 语言的整数类型(short、int、long)在不同计算机上,占用的字节宽度可能是不一样的,无法提前知道它们到底占用多少个字节。

程序员有时控制准确的字节宽度,这样的话,代码可以有更好的可移植性,头文件 stdint.h 创造了一些新的类型别名。

(1)精确宽度类型(exact-width integer type),保证某个整数类型的宽度是确定的。

  • int8_t :8位有符号整数。

  • int16_t :16位有符号整数。

  • int32_t :32位有符号整数。

  • int64_t :64位有符号整数。

  • uint8_t :8位无符号整数。

  • uint16_t :16位无符号整数。

  • uint32_t :32位无符号整数。

  • uint64_t :64位无符号整数。

上面这些都是类型别名,编译器会指定它们指向的底层类型。比如,某个系统中,如果 int 类型为32位, int32_t 就会指向 int ;如果 long 类型为32位, int32_t 则会指向 long

下面是一个使用示例。

#include <stdio.h>
#include <stdint.h>

int main(void) {
  int32_t x32 = 45933945;
  printf("x32 = %dn", x32);
  return 0;
}

上面示例中,变量 x32 声明为 int32_t 类型,可以保证是32位的宽度。

(2)最小宽度类型(minimum width type),保证某个整数类型的最小长度。

  • int_least8_t

  • int_least16_t

  • int_least32_t

  • int_least64_t

  • uint_least8_t

  • uint_least16_t

  • uint_least32_t

  • uint_least64_t

上面这些类型,可以保证占据的字节不少于指定宽度。比如, int_least8_t 表示可以容纳8位有符号整数的最小宽度的类型。

(3)最快的最小宽度类型(fast minimum width type),可以使整数计算达到最快的类型。

  • int_fast8_t

  • int_fast16_t

  • int_fast32_t

  • int_fast64_t

  • uint_fast8_t

  • uint_fast16_t

  • uint_fast32_t

  • uint_fast64_t

上面这些类型是保证字节宽度的同时,追求最快的运算速度,比如 int_fast8_t 表示对于8位有符号整数,运算速度最快的类型。这是因为某些机器对于特定宽度的数据,运算速度最快,举例来说,32位计算机对于32位数据的运算速度,会快于16位数据。

(4)可以保存指针的整数类型。

  • intptr_t :可以存储指针(内存地址)的有符号整数类型。

  • uintptr_t :可以存储指针的无符号整数类型。

(5)最大宽度整数类型,用于存放最大的整数。

  • intmax_t :可以存储任何有效的有符号整数的类型。

  • uintmax_t :可以存放任何有效的无符号整数的类型。

上面的这两个类型的宽度比 long longunsigned long 更大。

分享到:

#免责声明#

版权声明:《 6. 数据类型 》为作者 知付 原创文章,转载请注明原文地址!
本站所有文章,如无特殊说明或标注,均为本站原创或整合发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
本文地址:https://www.yoppunion.com/C%20%E8%AF%AD%E8%A8%80%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B/92.html
同类推荐
评论列表
签到

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

支付宝扫一扫打赏

微信扫一扫打赏

微信扫一扫打赏