在VB6中使用指针:字节的计算

VBA,VB 6.0计算数据类型占用内存大小 需求背景  C、C++和.net语言都提供了计算机变量内存大小的函数即SizeOf,该函数能正确返回数据类型占用的内存字节数,但是VBA、VB6.0没有直接提供。特别在调用Windows API的时候,该功能显示得特别重要。 实现思路  VBA、VB6.0虽然没有提供指针运算符,但提供了几个获取变量指针(内存地址)的值的函数。 public function VarPtr(ptr as Any) as longPtr '获取变量自身的内存地址 public function StrPtr(ptr as A 阅读详情

版权声明:可以任意转载,转载时请务必以超链接形式标明如下文章原始出处和作者信息及本声明

作者:xixi

出处:http://blog.youkuaiyun.com/slowgrace/archive/2009/04/26/4124347.aspx

本文主要来自此帖的讨论,感谢unsigned、Soyokaze、Chen8013、Tiger_Zhao、m60a1、myjian、PctGL等朋友的指点,本文很多文字直接来自他们的发言。 

在VB中指针的算法非常诡异,你必须计算元素的大小,因为VB不会帮你完成这项工作。 

1、引言:VC指针和VB指针(来自unsigned)

指针只是一个形象的说法,实际在内存当中就是一个地址。VB没有C语言的指针类型,从而带来的问题是,在VB中,对你声明的长整形指针变量自加自减只是机械地加了“1”而已,并没有像C编译器那样,会根据指针指向的数据类型自动地加减这个数据类型的字节数。比如:

int a [ 2 ] = { 99 , 88 };
int *p = a;
p ++;

a的每个元素是两个字节,p自加后,指向a[1]。因此,如果是在VB里,想指向a(1),需要这样:

Dim a( 1) As Integer
a( 0) = 99
a( 1) = 88
Dim p As Long
p = VarPtr( a( 0))
p = p + 2

再如C/C++等当中,当定义好一个结构指针类型之后,进行指移偏移运算的时候,会以结构大小进行偏移移位:

typedef struct _tagMyStruct {
  unsigned char x;
  unsigned char y;
  short reserved;
  int z;
} MyStruct , * LPMyStruct;

LPMyStruct P;
P = 0;
P ++; //这里是P = (LPMyStruct)((unsigned long)P + sizeof(MyStruct)),而不是P = (LPMyStruct)((unsigned long)P + 1);

而在VB当中则完全需要自己对指针偏移进行正确计算,这种计算可以借助于API,以及VarPtr、StrPtr以及address of等等操作符做到。不过在这之前,我们最好还是熟悉一下VB使用内存的方式。

 

2、VB使用内存的方式

2.1 按字长对齐(来自unsigned)

主流编译器为了内存访问的优化,会按机器字长进行内存对齐,从而导致某些结构例如:

typedef struct _tagMyStruct {
  unsigned char x;
  unsigned char y;
  int z;
} MyStruct;

看上去只有 sizeof(unsigned char) +  sizeof(unsigned char) + sizeof(int) = 1 + 1 + 4。但是在Win32平台下,在没有强制做存储压缩的情况下,编译器却实际上让它占用了8字节的空间。x和y各占一个字节,所以x和y被分到同一个机器字长的空间当中;由于z是int,刚好是一个机器字长,为了访问z的时候能够一次性读入cache,而不是先从第一个机器字长的空间当中读取半个z,然后再读取第二个机器字长的空间才读取到后半个z,编译器就把z直接放到了下一个机器字长的空间当中,从而就导致了y和z中间隐藏了2个字节的空间。

而在有的编译器当中,数据是压缩存储的,也就是说

type MyStruct
  x as byte
  y as byte
  z as long
End Type

这样一个结构,在有的编译器当中就是6个字节。从而如果你在调用一个API的时候,刚好碰到上面的C结构,那么你就很有可能会把一个在C当中占了8字节的结构定义成了只有6个字节。如此你在调用API的时候,就会导致内存访问溢出,后果是非常严重的。

2.2 堆和栈 

通常,局部变量是放在栈中的,动态分配的内存则是放在堆中的。如果你声明一个含动态数组成员的结构,那么结构中指向数组注册地址的指针是在栈中的,4字节。而数组的具体内容则是在堆中的,一般是连续存放的。详见堆与栈的区别(1)和堆和栈的区别(2)。栈里的内存的对齐方式,通常由编译器决定;堆里内存的对齐方式,通常由操作系统决定。

注意1:数组元素的存放应该是连续的,只是首址按双字对齐。也就是,数组的第一个元素的地址是双字对齐的,后续元素则不再按双字对齐,而是依次连续不间断地排放,中间没有填充空闲字节。既使是结构数组也是这样(未经xixi验证)。

注意2:VB6中动态数组和字符串是动态分配内存的。也就是变长字符串运算和redim动态数组是要重新分配内存的,重新Redim时,各元素地址会发生变化。

2.3 有关无符号长整型

此外,在VB中运用指针,我们还必须处理缺乏无符号长整型数据类型的问题,详见这篇文章。

 

下面让我们通过几个例子来体会VB中指针位移的计算: 

3、一个关于局部变量的内存分配的例子(来自Chen8013)

Private Sub Command1_Click()
    Dim t As Boolean , strTest$ , bB As Byte , iLong&
VB6程序中验证ByREF, ByVal, VarPtr, StrPtr, Poke, Peek, DBCS, SBCS, Ansi, Unicode的区别与使用 字符串存储格式影响着编程使用,C格式字符串是以 \0 作为结束符,其长度可以由此计算,而VB格式的字符串其长度存于字符串前缀之中。不仅如此,字符串编码方式 ansi, unicode, widestring, dbcs, sbcs 这些概念也影响着长度计算。笔记用VB6程序对它们进行剖析验证。 阅读详情

相关推荐

VB6实现AES加密:为遗留系统注入现代安全能力

AES(高级加密标准)作为当前应用最广泛的对称加密算法,其核心原理基于替换-置换网络,通过多轮迭代的字节代换、行移位、列混合和轮密钥加操作,实现对数据块的混淆与扩散,从而确保机密性。该算法因其安全性高、效率优异,已成为HTTPS、数据库加密、文件保护等众多场景的基石。在工程实践中,为Visual Basic 6.0等遗留技术栈集成AES能力,是满足现代数据安全法规与业务升级需求的关键技术手段。本文聚焦于在VB6环境中实现AES-CBC模式与PKCS7填充,深入剖析纯代码实现与DLL调用的方案选型、核心算法模

weixin_33733810的博客 387

获取本机网卡的物理地址程序(VB6.0源代码编写)' API函数声明

获取本机网卡的物理地址程序(VB6.0源代码编写)' API函数声明

Modbus IEEE754 浮点数 转换 方法 VB 代码

Modbus IEEE754 浮点数 转换 方法 VB 代码 使用VB6把MODBUS协议中的32位整数,变换为浮点数 MODBUS协议 数据 转换 IEEE754 Float Long

VB6指针技术大揭秘.doc

VB6指针技术大揭秘

USB HID虚拟电池:Windows零驱动电源状态模拟方案

虚拟电池是一种在硬件测试与功耗分析中替代真实电池、实现可控电源状态注入的关键技术。其核心原理是通过标准USB HID协议(特别是UPS设备类)向操作系统上报可编程的AC/DC状态、剩余电量、容量参数等,绕过内核驱动限制,达成毫秒级响应与跨Windows版本兼容。该技术显著提升SoC能效验证、电池健康度校准及低电量行为触发等场景的可重复性与精度。本文基于CH554微控制器实现符合HID UPS规范的物理层虚拟电池设备,支持零驱动安装、USB原生识别与实时参数调控,适用于笔记本平台功耗建模、电源管理策略验证及自

weixin_35755188的博客 355

最新版 Akamai 逆向 风控破解

经过测试,捷星 jetstar.com,德州仪器 ti.com,w6 wizzair.com,还有一些航空公司的都是可以实现一个并发的有需要的可以。

m0_72605044的博客 6624

字节跳动已上岸测试工程师的面试经验

这个时候发面经已经有点晚了,所以现在打算让这篇面经主要面向即将秋招的童鞋,当然现在还在春招的童鞋也可以看哈,我和大家一起聊聊关于测试的二三事。   一、测试工程师的工作是什么?   测试工程师简单点说就是找bug,然后反馈给开发人员,不要小看这个工作。   首先很明显的bug开发人员有时候自己就能找到,测试人员要有比开发人员更加全面的想法才能找到深层次的问题点,   其次,要端正一个态度就是测试人员不是一个电脑小白,相反国外顶级的测试开发工程师同时也是顶级的开发工程师甚至更厉害,所以作为一个测试工程师一定要

m0_60745607的博客 2933

HFSS实战项目——Ku波段微带发夹线滤波器

保姆级教程!!!看完必会,非常详细!!!Ku频段5阶切比雪夫微带线带通滤波器的仿真实例。首先介绍了滤波器的技术指标和基本理论知识,重点介绍了滤波器的耦合系数和外部品质因数。建立了谐振器的设计模型、耦合系数与谐振器间距的设计模型、外部品质因数与抽头位置的设计模型和滤波器整体电路的模型。详细介绍了谐振器设计模型的建立步骤。

2401_87464239的博客 3043

056:vue+openlayers 风场快速移动效果(图文代码)

本示例的目的是介绍演示如何在vue+openlayers中使用wind插件来实现风场快速移动的效果。

大剑师兰特的GIS世界 1583

[QMT和ptrade量化交易小白入门]-120、卖出深度虚值期权的三重过滤策略

本专栏主要是介绍QMT和ptrade的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写200篇左右。QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。

木头大左的博客 284

论文翻译:Automatic Lesson Plan Generation via Large Language Models with Self-critique Prompting

在本文中,我们利用大型语言模型(LLMs)的理解和生成能力来自动生成定制化的课程计划。这解决了传统计划可能无法充分满足不同教学环境和学生群体的特定需求的常见挑战。我们提出了一个新颖的三阶段过程,包括使用检索增强生成(RAG)逐步生成课程计划的每个关键组成部分,通过LLMs进行自我批评,以及随后的细化。我们使用这种方法为小学2至5年级生成了涵盖80多个主题的数学课程计划。邀请了三位经验丰富的教育工作者制定全面的课程计划评估标准,然后使用这些标准将我们的LLM生成的课程计划与同一主题的实际课程计划进行基准比较。

CSPhD-winston的博客 1102

指纹浏览器降维打击(下):Cloudflare Turnstile 与 hCaptcha 的底层交互逻辑

本文将深度拆解:Turnstile 与 hCaptcha 的 Iframe 沙箱通信机制,动态混淆 JS 与 PoW(工作量证明)的物理破解法则,以及如何通过 C++ 底层事件合成与环境基因强绑定,实现验证码的“无感过验”。

数据知道的博客 423

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

上一篇: VBA中使用API的方式:TLIB or Declare
下一篇: 关于类间消息的讨论(2)
slowgrace
博客等级 码龄18年 4613粉丝 205原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值