指针与字节序

指针的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的值变成了大端序形式。

相关推荐
lingran__3 小时前
C++ STL unordered系列(哈希) 底层剖析与模拟实现万字详解 | 基于哈希表,复刻 SGI-STL 泛型哈希容器架构
开发语言·c++·后端·哈希算法·哈希表·泛型编程·unordered系列
鸿芯微控科技3 小时前
MFC设定流量达不到怎么办?上游供气能力、压差与管路阻力排查
c++·mfc·质量流量控制器·流量不足排查·压差测试·气体流量控制
小林ixn3 小时前
NestJS 入门实战:从 0 到 1 撸一个 Todo CRUD,感受装饰器与模块化的优雅
后端·mvc·nestjs
阿弱3 小时前
graph-core 的边与命令模式设计
java·后端·agent
智驭未来掌门人3 小时前
利用Qt设计实现一款桌面程序
后端
长栎4 小时前
你以为抽象工厂是「创建一组对象」——其实它是「锁定产品族兼容性」
后端
郝学胜_神的一滴4 小时前
C++20 高级编程 003:吃透现代基础语法与标准容器
c++
长栎4 小时前
你的 AI 品控规则越来越多了——但它们已经在打架了,你没看见
后端
有脚就行4 小时前
第24篇-Go-gRPC推理服务-高性能跨语言通信
开发语言·人工智能·后端·golang
码匠许师傅4 小时前
【C++ 面试真题】聊聊 C++ 的关联容器
开发语言·c++·面试