c语言比较10个数字大小(语言速通(2)基本数据类型)

首页常识c语言比较10个数字大小更新时间:2023-10-13 06:09:49
C 语言数据类型概览

数据类型,是编程语言的基石。其最初的目的就是为了让程序(开发者)更加充分的利用稀缺的内存资源。随着技术的发展,数据类型也被赋予了更深厚的含义:

  1. 用于确定数据对象占用的内存空间大小。
  2. 用于确定数据对象的数值范围。
  3. 用于规定数据对象所能进行的操作(行为)。

例如:基本整型数据对象占用 4B 的内存空间,数值范围是 [0x0, 0xFFFF FFFF],可以进行算术运算。

四大数据类型
  1. 「基本数据类型」:是 C 语言中最基本的数据类型,它们用于存储基本的数据值,包括:整型、浮点型、字符型和布尔型。
  2. 「构造数据类型」:由多个基本数据类型组成,它们用于表示更复杂的数据结构,包括:数组、结构体、联合体和枚举类型。
  3. 「指针类型」:用于存储变量或数据的内存地址。
  4. 「空类型(void)」:是一种特殊的数据类型,它表示没有值。空类型通常用于表示函数没有返回值,或者指针没有指向任何数据。
  5. 「衍生数据类型」:是通过对其他类型进行修改而得到的新类型。C 语言中常见的衍生数据类型包括:常量类型、限定符类型和自定义类型。
基本数据类型取值范围概览

数值类型整型

整型又可以细分为 int、long、long long 这 3 类。

对于整型数据而言,我们首先需要关心的是整型的进制表示方式,这涉及到数值前缀。

  • 「10 进制(默认)」
  • 「2 进制(以 0b 开头)」:0b11101101
  • 「8 进制(以 0 开头)」:045,021
  • 「16 进制(以 0x 开头)」:0x21458adf

而后,因为整型数据有 signed 和 unsigned 之分,以及 int 和 long 之分,这涉及到数值后缀。

  • 「u 表示 unsigned」
  • 「l 表示 long」

85 /* 十进制 */ 0213 /* 八进制 */ 0x4b /* 十六进制 */ 30 /* 整数 */ 30u /* 无符号整数 */ 30l /* 长整数 */ 30ul /* 无符号长整数 */ 浮点型

在这里插入图片描述

浮点型可细分为 float(单精度)和 double(双精度)这 2 类,代码写法有所不同:

  • 「double(默认)」:2.3
  • 「float」:2.3f
  • 「long double」:2.3lf

另外,浮点数有 2 种表达方式:

  1. 「小数形式」
  2. 「指数形式(科学计数法)」:由数符尾数(整数或小数)、阶码标志(E 或 e)、阶符、整数阶码组成的常数。例如:2.129000e 001。

3.14159 /* 合法的 */ 314159E-5L /* 合法的 */ 510E /* 非法的:不完整的指数 */ 210f /* 非法的:没有小数或指数 */ .e55 /* 非法的:缺少整数或分数 */

示例:

#include <stdio.h> #include <float.h> // 定义了浮点型相关的宏,e.g. FLT_MIN、FLT_MAX 等。 int main(){ printf("float byte: %lu \n", sizeof(float)); printf("float MIN: %E \n", FLT_MIN); // 以指数形式输出单、双精度实数。 printf("float MAX: %E \n", FLT_MAX); printf("float DIG: %d \n", FLT_DIG); return 0; }

运行:

$ ./main float byte: 4 float MIN: 1.175494E-38 float MAX: 3.402823E 38 float DIG: 6 字符类型字符型

字符型(Char)数据需要使用单引号 'c' 括起来,占用 1B 内存空间,范围是 [-128, 127] 与 ASCII 码的编号对应。另外,字符型数据本质是一个 “数字“,所以可以和整型数据相互转换。

字符型数据具有 2 种类型:

  1. 「一般字符数据」:一个用单引号 ' ' 括起来的字符。
  2. 「转义字符数据」:一个用单引号 ' ' 括起的,并以反斜杠 '' 开头的字符,用于表示具有特殊功能的字符。

下表列出了转义序列表:

无符号和有符号的区别

只有整型和字符型数据具有无符号和有符号的特性。

对于同一种数据类型而言,有符号的区别就在于具有 “符号位”,所以,虽然两者都占用相同的内存空间,但拥有的数值范围却不同。

例如:若 unsigned char 和 signed char 都占用 1B 的内存空间。那么,signed char 的数值范围为 [-128, 127],而 unsigned char 的数据范围为 [0, 255]。这是因为有符号类型数据的最高位被用作为符号位。

CPU 平台适配

值得注意的是,C 语言基本数据类型的实际大小还与 CPU 的字长(32bit 还是 64bit)有关。为了让程序对不同的 CPU 具有更好兼容性,C 提供了 sizeof 关键字和 size_t 数据类型。

sizeof 关键字

sizeof 关键字用于获得某个数据类型在当前 CPU 平台上的准确大小(字节数)。

int main() { char stringA[] = "Hello World!\r\n"; printf(" sizeif( char ) = %d\r\n", sizeof(char)); printf(" sizeif( int ) = %d\r\n", sizeof(int)); printf(" sizeif( long int ) = %d\r\n", sizeof(long int)); printf(" sizeif( float ) = %d\r\n", sizeof(float)); printf(" sizeif( double ) = %d\r\n", sizeof(double)); // 注意 stringA 的末尾还存放着 '\0' printf(" sizeif( stringA ) = %d\r\n", sizeof(stringA)/sizeof(char)); return 0; } size_t 自定义数据类型

在 C 程序中使用 size_t(size_type)可以有效提高代码的跨平台可移植性和可读性。C 语言原生数据类型并不包含 size_t,而是 C 标准委员会为了解决程序可移植性问题才引入的。sizeof() 函数返回值就是 size_t 类型。

_t 后缀的含义是 type,表明这是 POSIX 或 GNU 保留的一种数据类型,防止命名空间污染(Namespace Pollution)。POSIX 规定 C 语言自身扩展的类型都有 _t 后缀,这样就不会与用户自定义的类型的命名冲突了。

size_t 的定义在 stddef.h、stdio.h、stdlib.h、string.h、time.h 和 wchar.h 这些标准 C 的头文件中,include l了以上任一头文件,则表明 size_t 将作为一个全局关键字。

  • 在 32bit CPU 平台中的定义:

typedef unsigned int size_t;

  • 在 64bit CPU 平台中的定义:

typedef unsigned long size_t;

可见,size_t 是一种无符号的整型(unsigned int、unsigned long、unsigned long long),取值范围是目标 CPU 平台中最大的可能范围。

#include <stdio.h> int main() { printf("Int size: %d", sizeof(int)); } // Int size: 4

为什么需要额外引入一个 size_t 自定义数据类型呢?本质上是为了弥补整型数据类型在 CPU 地址线宽度不匹配的缺陷。

在 C 语言种,整型数据类型的大小通常会小于等于 CPU 数据线的宽度,例如:int 对应的数据线宽度普遍是 32bit,而地址线的宽度普遍是 64bit。所以引入了 size_t 类型,它通常会大于等于 CPU 地址线宽度,以此来表示 CPU 平台中最大的可能范围。

size_t 数据类型的另一个好处是见名知义,通常只用于表示 “字节大小" 或 “数量”,而不是一个普通的算术值,适当地使用 size_t 会使你的代码变得更加可读。

C 的标准函数中大量使用到了 size_t 类型来表示取值的字节数:

void *malloc(size_t size); void *memcpy(void *s1, void const *s2, size_t size); size_t strlen(char const *s); uintX_t 类型

在 C99 标准的 stdint.h 头文件中通过 typedef 定义了 uint8_t、uint_16_t、uint32_t、uint64_t 等数据类型,同样是为了优化跨 64bit 或 32bit CPU 平台的可移植性。

格式化输出符为:

  • uint16_t:%hu
  • uint32_t:%u
  • uint64_t:%llu
  • uint8_t:本质是一个 char 类型,所以在输出 uint8_t 类型的变量时,实际上输出了其对应的字符,而不是数值。

#ifndef __int8_t_defined # define __int8_t_defined typedef signed char int8_t; typedef short int int16_t; typedef int int32_t; # if __WORDSIZE == 64 typedef long int int64_t; # else __extension__ typedef long long int int64_t; # endif #endif typedef unsigned char uint8_t; typedef unsigned short int uint16_t; #ifndef __uint32_t_defined typedef unsigned int uint32_t; # define __uint32_t_defined #endif #if __WORDSIZE == 64 typedef unsigned long int uint64_t; #else __extension__ typedef unsigned long long int uint64_t; #endif

- END -

,
推荐内容
热门内容