指针与字节序

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

相关推荐
Charles Ray14 分钟前
C++学习笔记 —— 内存分配 new
c++·笔记·学习
重生之我在20年代敲代码14 分钟前
strncpy函数的使用和模拟实现
c语言·开发语言·c++·经验分享·笔记
爱上语文16 分钟前
Springboot的三层架构
java·开发语言·spring boot·后端·spring
serve the people20 分钟前
springboot 单独新建一个文件实时写数据,当文件大于100M时按照日期时间做文件名进行归档
java·spring boot·后端
罗政6 小时前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端
迷迭所归处6 小时前
C++ —— 关于vector
开发语言·c++·算法
CV工程师小林6 小时前
【算法】BFS 系列之边权为 1 的最短路问题
数据结构·c++·算法·leetcode·宽度优先
拾光师7 小时前
spring获取当前request
java·后端·spring
white__ice7 小时前
2024.9.19
c++
天玑y7 小时前
算法设计与分析(背包问题
c++·经验分享·笔记·学习·算法·leetcode·蓝桥杯