d的指针算术

原文
如下在ldc更好C下编译:

import core.stdc.stdio;
import core.stdc.stdlib;

struct MemoryBlock {
  char* ptr;
  ulong length;
}

void* ptr = cast(void*)0x7a7;

void* right() {
  return cast(MemoryBlock*)(ptr + MemoryBlock.sizeof);
 //在括号间转换整个`式`.取正确的值!
}
 //以上代码向`ptr`加了`16`个字节

void* wrong() {
  return cast(MemoryBlock*)ptr + MemoryBlock.sizeof;
 //先转换`'ptr'`变量,然后加上数字.得到错误的值...
}
 //上面的代码向`ptr`加了`16*MemoryBlock.sizeof`字节`(16*16)`,因为先转换`ptr`,`+1`才是正确的

char* return_address_wrong() {
  MemoryBlock* local_ptr = cast(MemoryBlock*)ptr;
  return cast(char*)(local_ptr + MemoryBlock.sizeof);
 //转换了整个式.但得到了错误的值`!!!!`为什么`???`
}
 //因为加的是`16`字节块的指针,而不是单字节的`void*`

char* return_address_right() {
  MemoryBlock* local_ptr = cast(MemoryBlock*)ptr;
  return cast(char*)local_ptr + MemoryBlock.sizeof;
 //现在我先转换`'local_ptr'`变量,然后加上数字,但这次得到了正确的值`..`,
}
//这是单个字节.

extern (C) void main() {
  printf("期望位置:", ptr + MemoryBlock.sizeof);
  printf("正确位置: %p\n", right());
  printf("错误位置: %p\n", wrong());

  printf("返回地址(错误)): %p\n", return_address_wrong());
  printf("返回地址(正确): %p\n", return_address_right());
}

T*+10==10 * T.sizeof
64位系统上,MemoryBlock.sizeof16.
参考:
结果值是指针加上(或减去)第二个操作数乘以第一个操作数指向类型的大小.
因为加的是16字节块指针,而不是单字节的void*.

C和D根据基础值类型实现指针算术.即,向char*,加1加为基础地址加1,但向int*加1,则是基础地址加int.sizeof而不是1.即:

int[2] x;
    int* p = &x[0]; // 假设这是1234地址
    p++;//p现在为1238,而*不是*1235(int.sizeof==4)

因为更容易操作.
如,如果是指向4个有符号32位整数的数组,那么可简单地给指针递增1.
如果是原始字节,那么必须给指针加4才能移动到下个元素.
如果要移动到循环中的下个元素,这是反直觉的.
这是惯用法:

foreach (i; 0 .. list.length)
{
    (*cast(int*)(ptr + i)) = i;
}

比较:

foreach (i; 0 .. list.length)
{
    (*cast(int*)(ptr + (i * 4))) = i;
}

可这样:

foreach (i; 0 .. list.length) {
  (cast(int*)ptr[i]) = i;
}

只要稍微移动右括号.可用指针加括号标记法.
假设ptrvoid*,这些都是等价的:

(cast(int*) ptr)[i] = whatever;
*((cast(int*) ptr) + i) = whatever;
*(cast(int*) (ptr + i * int.sizeof)) = whatever;
posted @   zjh6  阅读(20)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示