java 如何使指针像对象一样指向数组的中间

kknvjkwl  于 2023-04-19  发布在  Java
关注(0)|答案(1)|浏览(111)

我有一个字节缓冲区,并希望有标识符,指向第一个元素,这将被写入,不一定是数组本身的第一个元素。

private void uint32ToBuffer(int val, byte[] buffer)
    {
        buffer[0] = (byte)val;
        buffer[1] = (byte)(val >>> 8);
        buffer[2] = (byte)(val >>> 16);
        buffer[3] = (byte)(val >>> 24);
    }

我想做

byte[] buffer = new byte[512];
uint32ToBuffer(3, &buffer[2]);

但显然它不起作用。有没有可能做到这一点,而不让函数uint32ToBuffer知道它应该写入数组的初始位置,以复制类似语言的C的指针算术逻辑?

uttx8gqw

uttx8gqw1#

没有。
你有几个选择:

使用java.nio.buffer.ByteBuffer

ByteBuffer是一个抽象的概念;与byte[]不同的是,它有一个有意义的API,与byte[]不同的是,它在跟踪中进行了烘焙。(比如,它有一个'位置',不像字节数组只有长度).事实上,非常棒的跟踪,有标记,重置和限制.在实践中,一个字节缓冲区由“一个围绕包含数据的数组的轻量级对象 Package 器”或“直接访问内存MapI/O事物”组成。
实际上,ByteBuffer已经有了write-int-to-byte-array-as-little-endian功能!

byte[] buffer = new byte[512];
ByteBuffer bb = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN);
bb.position(2);
bb.putInt(3);

此时不再需要uint32ToBuffer方法;bytebuffer已经有了。putInt(3)调用:

  • 将“3”作为32位整数写入位置[2][3][4][5]处的字节(因为bb的位置是“2”;这是一个相对写)。具体来说,它写3/0/0/0,因为缓冲区对象的字节顺序是LITTLE_ENDIAN。默认情况下,它们是大端,应该写0/0/0/3。不知道为什么你想要小端,这是一个非常过时的概念,只有x86/x64芯片仍然使用它:互联网倾向于大字节序,ARM芯片在这一点上也相当受欢迎。如果你正在设计协议,我强烈建议你重写东西,而不是大字节序。
  • 将bb的位置前移到6。

还有一个绝对的写:

bb.putInt(2, 3);

这具有相同的效果(将3写入buffer[2],并将0写入buffer[3]buffer[5]),但不依赖于缓冲区的位置值,也不修改它。
我强烈建议你在这里使用它,以及你正在做的任何涉及“将小端整型写入字节数组”的事情。

只要传递沿着

或者,沿着位置传递;这在Java API中非常常见:

private void uint32ToBuffer(int val, byte[] buffer, int pos) {
    buffer[pos] = (byte)val;
    buffer[pos + 1] = (byte)(val >>> 8);
    buffer[pos + 2] = (byte)(val >>> 16);
    buffer[pos + 3] = (byte)(val >>> 24);
}

// ... and if you want, for convenience:
private void uint32ToBuffer(int val, byte[] buffer) {
  uint32ToBuffer(val, buffer, 0);
}

在Java中没有办法创建作为其他数组的子切片的数组;数组是非常基本的,并且绝对不支持任何可能算作“花哨”的东西。Java也没有任何类型的指针算法,因此,将2个插槽指向字节数组的引用根本不是一件事。在C语言中,字节数组本质上“只是一个指针”,你不知道它有多长。在Java中,因为缓冲区溢出是一个相当常见的安全问题,字节数组实际上是它们自己数据结构,特别是知道它们实际上是一个字节数组,也知道它们有多长。Java使得不可能(除非你写了一些被破解的类文件 * 并 * 禁用JVM的类验证器)来编程缓冲区溢出问题。指针不能以这种方式修改(你不能在java中给指针'加2')。

相关问题