Bootstrap

03-数据类型——整型、浮点型、字符、字符串、布尔型、常量与变量的解析

03-数据类型

整型、浮点型、字符、字符串、布尔型、常量与变量的解析

一、整型

int a = 0;

注意事项
在32位系统和64位系统中,整型(int)都占用4字节

1.1 取值范围

通过命令行工具getconf可以获取整型的最大值和最小值:

$ getconf INT_MAX
2147483647
$ getconf INT_MIN
-2147483648

1.2 整型的修饰符

short:短整型,用于将整型的尺寸减少为原本的一半,减少内存开支,缩小取值范围。
long:长整型,用于将整型的尺寸变大,增加内存开支,扩大取值范围。
long long:长长整型,用于进一步增加整型的尺寸和取值范围。在64位系统中,long与long long的大小一致。
unsigned:无符号整型,用于去掉符号位,使得整型数据没有负数,扩展正整数的取值范围(0到4294967295)。

1.3 整型数据的符号位

整型数据在二进制存储时,最高位(第31位)表示符号位:

如果符号位为1,则表示负数。
如果符号位为0,则表示正数。

1.4 整数的存储方式

1.4.1 原码

正整数是直接使用原码进行存储的。原码是指整数的绝对值的二进制表示。
例如,整数100的原码表示如下:

100  -->  0000 0000 0000 0000 0000 0000 0110 0100
1.4.2 补码

负数使用补码来存储。补码的计算方法是:取该数的原码的绝对值,取反加1。
符号位(最高位)不变。

例如,-100的补码表示如下:

  1. 计算100的二进制原码:

(注意其实是-100的原码,符号位带上了为1)

100  -->  1000 0000 0000 0000 0000 0000 0110 0100
  1. 取反(符号位保持不变):
取反->  1111 1111 1111 1111 1111 1111 1001 1011
  1. 加1:
加1 ->  1111 1111 1111 1111 1111 1111 1001 1100

所以,-100的补码表示为:

1111 1111 1111 1111 1111 1111 1001 1100
1.4.3 溢出

当整数运算的结果超过其取值范围时,会发生溢出。溢出后的结果会变成相邻的最小值或最大值

例如,对于32位有符号整数(int):

  • 最大值是2147483647(0111 1111 1111 1111 1111 1111 1111 1111
  • 最小值是-2147483648(1000 0000 0000 0000 0000 0000 0000 0000

如果将最大值加1,则会溢出为最小值:

2147483647 + 1 = -2147483648
1.4.4 示例

以下示例代码演示了正整数和负整数的存储方式及溢出情况:

#include <stdio.h>
#include <limits.h>

int main() {
    int positive = 100;
    int negative = -100;

    printf("正整数 %d 的二进制表示(原码):%x\n", positive, positive);
    printf("负整数 %d 的二进制表示(补码):%x\n", negative, negative);

    // 演示溢出
    int max_int = INT_MAX;
    int min_int = INT_MIN;
    printf("最大整型值: %d\n", max_int);
    printf("最小整型值: %d\n", min_int);
    printf("最大整型值加1(溢出):%d\n", max_int + 1);
    printf("最小整型值减1(溢出):%d\n", min_int - 1);

    return 0;
}

输出结果

正整数 100 的二进制表示(原码):64
负整数 -100 的二进制表示(补码):ffffff9c
最大整型值: 2147483647
最小整型值: -2147483648
最大整型值加1(溢出):-2147483648
最小整型值减1(溢出):2147483647

二、浮点型(实型)

概念:浮点型用于表达一个实数的数据类型。

2.1 分类

  1. 单精度浮点型(float
    • 典型尺寸:4字节
  2. 双精度浮点型(double
    • 典型尺寸:8字节
  3. 长双精度浮点型(long double
    • 典型尺寸:16字节

占用的内存越多,则精度越高。但是注意是经典尺寸,在不同系统中可能不同。

2.2 浮点数的存储

IEEE 754浮点数标准采用如下形式来表示一个浮点数:
在这里插入图片描述

  • 单精度浮点数(32位)
    • 符号位(S):1位
    • 指数位(E):8位
    • 尾数位(M):23位

在这里插入图片描述

  • 双精度浮点数(64位)

    • 符号位(S):1位
    • 指数位(E):11位
    • 尾数位(M):52位
  • 长双精度浮点数(128位)

    • 符号位(S):1位
    • 指数位(E):15位
    • 尾数位(M):112位

2.3 示例代码

以下代码展示了如何声明和打印浮点数,以及如何用不同的解析方式查看存储的二进制值:

#include <stdio.h>

int main() {
    float f = 3.14;
    double d = 3.14;
    long double ld = 3.14;

    // 输出浮点数
    printf("float f: %f\n", f);
    printf("double d: %lf\n", d);
    printf("long double ld: %Lf\n", ld);

    // 使用整型方式查看浮点数存储的二进制值
    printf("float f (as int): %d\n", *(int*)&f);
    printf("double d (as int): %lld\n", *(long long*)&d);
    printf("long double ld (as int): %lld\n", *(long long*)&ld); // 这只是部分显示

    return 0;
}

注意事项

  • 当使用printf函数输出浮点数时,需要使用对应的格式化标识符:
    • float%f
    • double%lf
    • long double%Lf
  • 当直接使用整型方式查看浮点数的存储值时,可以将浮点数的地址转换为整型指针,然后解引用该指针。这样可以直接看到存储的二进制值(以整型形式展示)。

输出结果

float f: 3.140000
double d: 3.140000
long double ld: 3.140000
float f (as int): 1078523331
double d (as int): 4614253070214989087
long double ld (as int): 4614253070214989087

三、字符

概念:字符类型(char)用于存储单个字符的数据类型。

3.1 字符的详细解释

  1. 声明和初始化字符变量

    char c = 'K';
    
    • 申请一片内存并命名为c
    • 确定内存的大小为char(1字节)
    • 把字符'K'的ASCII码值(75)转换为二进制,并存储到该内存中
  2. 打印字符及其ASCII码值

    printf("字符:%c\n", c); 
    printf("整型ASCII值:%d\n", c);
    
    • printf("%c", c):以字符的形式来解析内存c的内容,得到字符'K'
    • printf("%d", c):以十进制整型来解析内存c的内容,得到字符'K'对应的ASCII值75
  3. 字符类型支持整型操作

    char k = 'H';
    printf("%c\n", k + 1); 
    printf("%c\n", k - 1); 
    
    • char k = 'H':字符'H'的ASCII值是72
    • printf("%c", k + 1)'H'的ASCII值加1得到73,对应字符'I'
    • printf("%c", k - 1)'H'的ASCII值减1得到71,对应字符'G'

3.2 示例代码及解释

#include <stdio.h>

int main() {
    // 声明并初始化字符变量
    char c = 'K';
    
    // 申请一片内存并且命名为c
    // 确定内存的大小为char(1字节)
    // 把字符‘K’的ASCII码值转换为二进制,并存储到该内存中
    
    // 打印字符及其ASCII码值
    printf("字符:%c\n", c); // 以字符的形式来解析内存c的内容,得到字符'K'
    printf("整型ASCII值:%d\n", c); // 以十进制整型来解析内存c的内容,得到'K'对应的ASCII值

    // 声明并初始化另一个字符变量
    char c1 = '1';

    // 打印字符及其ASCII码值
    printf("字符:%c\n", c1); // 以字符的形式来解析内存c1的内容,得到字符'1'
    printf("整型ASCII值:%d\n", c1); // 以十进制整型来解析内存c1的内容,得到'1'对应的ASCII值

    // 字符类型支持整型操作
    char k = 'H';
    printf("字符加一:%c\n", k + 1); // 'H'的ASCII值是72,加1后得到73,对应字符'I'
    printf("字符减一:%c\n", k - 1); // 'H'的ASCII值是72,减1后得到71,对应字符'G'

    return 0;
}

注意事项

  • 在计算机中,所有数据都是以二进制形式存储的。因此,字符必须映射到某个数字才能被存放到计算机中。这个映射表称为ASCII表,可以使用man ascii命令查看。
  • 字符实质上是一个单字节的整型,因此支持所有整型的操作。

四、字符串

字符串在C语言中的表示有两种形式:数组和指针。

4.1 形式一:数组(可读、可写)

char s1[] = "Hello";使用一个数组来存放字符串 "Hello"

在这里插入图片描述

  • 使用一个数组来存放字符串 “Hello”。
  • 实际上是把字符串常量 “Hello” 复制到数组 s1 所代表的内存中。

示例代码:

#include <stdio.h>

int main() {
    char s1[] = "Hello";
    
    // 修改数组中的字符
    s1[0] = 'h';
    
    printf("%s\n", s1); // 输出 "hello"
    return 0;
}

4.2 形式二:指针(只读)

char *s2 = "Even"; // 使用一个指针来指向常量字符串

在这里插入图片描述

  • 使用一个指针来指向字符串常量 “Even”。
  • 字符串常量存储在只读存储区,因此通过指针 s2 访问的字符串是只读的,不能修改。

示例代码:

#include <stdio.h>

int main() {
    char *s2 = "Even";
    
    // 尝试修改指针指向的字符串内容会导致未定义行为
    // s2[0] = 'e'; // 这行代码会导致运行时错误
    
    printf("%s\n", s2); // 输出 "Even"
    return 0;
}

4.3 综合示例代码

#include <stdio.h>

int main() {
    char s1[] = "Hello";
    char *s2 = "Even";
    
    // 修改数组中的字符
    s1[0] = 'h';
    
    // 打印字符串
    printf("%s %s\n", s1, s2); // 输出 "hello Even"
    
    return 0;
}

解释

  1. 字符串数组char s1[] = "Hello";
  • 数组的内存是可读可写的,可以修改字符串内容。
  • 示例中,s1[0] = 'h'; 将 “Hello” 修改为 “hello”。
  1. 字符串指针char *s2 = "Even";
  • 指针指向字符串常量,存储在只读内存区。
  • 尝试修改 s2 指向的内容(如 s2[0] = 'e';)会导致运行时错误。

输出结果

hello Even

五、布尔型

概念:布尔类型用于表示真/假(非零则为真)。

  • true
  • false

在使用布尔类型时需要包含头文件<stdbool.h>

5.1 详细解释

  1. 布尔变量声明和初始化

    bool a = 1;       // 真
    bool b = 0;       // 假
    bool c = true;    // 真
    bool d = false;   // 假
    
    • bool类型的变量可以使用整数或布尔常量进行初始化。
    • 1true表示真,0false表示假。
  2. 打印布尔值

    printf("a: %d\n", a);
    printf("b: %d\n", b);
    printf("c: %d\n", c);
    printf("d: %d\n", d);
    
    • 布尔值在输出时显示为整数,true1false0
  3. 打印布尔类型和变量的大小

    printf("sizeof(bool): %ld\n", sizeof(bool));   // 布尔类型的大小
    printf("sizeof(a): %ld\n", sizeof(a));         // 变量a的大小
    printf("sizeof(true): %ld\n", sizeof(true));   // 常量true的大小
    printf("sizeof(false): %ld\n", sizeof(false)); // 常量false的大小
    
    • 在C语言中,bool类型的大小为1字节。
    • 变量a的大小也是1字节。
    • 常量truefalse在C语言中的大小为4字节,因为它们被视为int常量。
  4. 打印布尔常量的整数值

    printf("false: %d\n", false); // 0
    printf("true: %d\n", true);   // 1
    
    • false的整数值为0
    • true的整数值为1

示例代码

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

int main() {
    bool a = 1;       // 真
    bool b = 0;       // 假
    bool c = true;    // 真
    bool d = false;   // 假

    // 打印布尔值及其大小
    printf("a: %d\n", a);
    printf("b: %d\n", b);
    printf("c: %d\n", c);
    printf("d: %d\n", d);

    printf("sizeof(bool): %ld\n", sizeof(bool));   // 布尔类型的大小
    printf("sizeof(a): %ld\n", sizeof(a));         // 变量a的大小
    printf("sizeof(true): %ld\n", sizeof(true));   // 常量true的大小
    printf("sizeof(false): %ld\n", sizeof(false)); // 常量false的大小

    printf("false: %d\n", false); // 打印false的整数值
    printf("true: %d\n", true);   // 打印true的整数值

    return 0;
}

运行结果

a: 1
b: 0
c: 1
d: 0
sizeof(bool): 1
sizeof(a): 1
sizeof(true): 4
sizeof(false): 4
false: 0
true: 1

六、 常量与变量

概念

  • 常量:不可以被改变的内存。
  • 变量:可以被改变的内存。

6.1 示例代码

#include <stdio.h>

int main() {
    int a = 100;           // a是一个变量,而100是常量
    float f = 3.1415;      // f是一个变量,而3.1415是常量
    char s1[] = "abcdefg"; // s1是一个变量,而"abcdefg"是常量(字符串常量)
    
    printf("a: %d\n", a);
    printf("f: %f\n", f);
    printf("s1: %s\n", s1);
    
    return 0;
}

练习
在这里插入图片描述

;