指针与字节序

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

相关推荐
小蜗牛慢慢爬行2 分钟前
有关异步场景的 10 大 Spring Boot 面试问题
java·开发语言·网络·spring boot·后端·spring·面试
小俊俊的博客30 分钟前
海康RGBD相机使用C++和Opencv采集图像记录
c++·opencv·海康·rgbd相机
goTsHgo31 分钟前
在 Spring Boot 的 MVC 框架中 路径匹配的实现 详解
spring boot·后端·mvc
waicsdn_haha43 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
_WndProc1 小时前
C++ 日志输出
开发语言·c++·算法
薄荷故人_1 小时前
从零开始的C++之旅——红黑树及其实现
数据结构·c++
m0_748240021 小时前
Chromium 中chrome.webRequest扩展接口定义c++
网络·c++·chrome
Q_19284999061 小时前
基于Spring Boot的摄影器材租赁回收系统
java·spring boot·后端
qq_433554541 小时前
C++ 面向对象编程:+号运算符重载,左移运算符重载
开发语言·c++
良许Linux1 小时前
0.96寸OLED显示屏详解
linux·服务器·后端·互联网