指针与字节序

指针的3种含义

对于再熟悉不过指针来说,我们还是要理解为什么会有指针,以及指针存在的意义是什么。

指针一般有3种含义:

  1. 指明数据的位置 ,体现在指针的值表示一个地址,这也是我们最容易理解的含义,即指针就是变量的地址。
  2. 表示数据类型的大小,虽然指针本身的值是一样大小的,但是不同类型的指针所表示的数据类型是不一样的。比如int指针表示4个字节为一组数据,体现在当使用指针的加减法时,会自动跳过4个字节。
  3. 表示数据被如何解释 ,虽然float指针和int指针,都是4个字节,但是他们的解释完全不同,就体现在对指针解引用时,同样是4个字节,解析出来的数据是不一样的。

void指针它只有第一层含义,不能表示数据如何解释 ,以及也不能表示数据的大小,只是指明了数据的位置。

字节序

在计算机中,存储是按字节来为单位来寻址和存储的,比如一个int类型数据,需要4个字节来存储,这种多字节数据一般都是被存储为连续的字节序列

比如一个4字节的int类型变量a,其存储的起始字节地址为0x80901100,则剩下的3个字节地址就分别为0x809011010x809011020x80901103,这时问题就来了,a的最低有效位可以存储在低地址,也可以存储在高地址中,这就引出了大端序和小端序

大端序和小端序

比如一个int类型的变量为0x12345678其中0x12为最高有效位字节,0x78为最低有效位字节 ,如果最高有效位存储在前面,则这种存储规则就是大端序,大端序就是我们日常的书写顺序

假如低有效位存储在前面,这种存储方式就是小端序,我们日常使用的x86架构就是小端序

0x12345678采用大端序存储方式的形式:

0 1 2 3
0x12 0x34 0x56 0x78

采用小端序存储的形式:

0 1 2 3
0x78 0x56 0x34 0x12

这里我们一定要切记,我们日常使用的芯片架构采用的是小端序。

指针和字节序实践

记住前面所说的,指针的3层含义,其中不同类型的指针所对应的指针加减操作,以及解引用是不一样的,我们来看个例子:

C++ 复制代码
#include <stdio.h>
#include <arpa/inet.h>

/*
* 传入字节数组,打印字节的值以及其地址
*/
void stringToHex(char *string, unsigned int len) {
        unsigned int loop = 0;
        char* temp = string;
        if (NULL == temp) {
                printf("input param is null \n");
                return;
        }

        for (loop = 0; loop < len; loop++) {
                printf("address %p:0x%x \n", temp, *temp);
                temp ++; 
        }
}

int main() {
        printf("转换前\n");
        int a = 0x12345678;
        printf("a = 0x%x \n", a); 

        stringToHex((char*)&a, sizeof(int));
        printf("转换后\n");

        a = htonl(a);
        printf("a = 0x%x \n", a); 
        stringToHex((char*)&a, sizeof(int));
    
        return 0;
}

//输出结果:
转换前
a = 0x12345678 
address 0x7fffe1415e84:0x78 
address 0x7fffe1415e85:0x56 
address 0x7fffe1415e86:0x34 
address 0x7fffe1415e87:0x12 
转换后
a = 0x78563412 
address 0x7fffe1415e84:0x12 
address 0x7fffe1415e85:0x34 
address 0x7fffe1415e86:0x56 
address 0x7fffe1415e87:0x78

我们来逐一分析:

  1. stringToHex方法中,我们使用printf格式化打印结果,其中%p表示打印地址,%x表示按16进制打印。
  2. a的类型是int,先使用&a获取到变量a的地址,然后使用(char*)&a把指针类型转成char类型。这时我们应该知道,不论是int类型指针还是char类型指针,都是地址,只是在解引用时会取不同长度的字节来进行解析 。这里也就可以解释为什么变量是int类型,我们却可以使用char类型指针来指向它。
  3. 从打印结果可以看出,a默认情况下,就是小端序存储的0x78为最低有效位,但是保存在前面。然后调用htonl方法,该方法的原型以及描述:
vbnet 复制代码
uint32_t htonl(uint32_t hostlong);

The htonl() function converts the unsigned integer hostlong from host byte order 
to network byte order.

接收无符号int类型数据,把主机字节序(当前为小端序)转成网络字节序(大端序),经过转换后,我们可以发现a的值变成了大端序形式。

相关推荐
paopaokaka_luck2 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
捕鲸叉3 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer4 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
码农小旋风4 小时前
详解K8S--声明式API
后端
Peter_chq4 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml44 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~4 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616884 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
青花瓷5 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode
睡觉谁叫~~~5 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust