学习中的一些牢骚。栈/堆地址标准写法。

2017-02-12 • 杂谈 • 暂无评论 • 老衲 •浏览 226 次

我一直都在寻找各种业务功能的最简单写法,用减法的模式来开发软件。下面是我的写法,如果有更简单的方法,请留言告知。

本人再学习的过程中,遇到很多难题,delphi很多地方自身的设计就很乱。
比如对参数修饰符的理解,网上100篇文章 90篇都有问题 错误率非常高。delphi 的数据类型有很多
同一个参数修饰符 修饰 不同数据类型 的意义都是有差异的。你或许认为你知道 传值与传址;
传址 又可分2种情况,你可知道。


再比如 把指针 转换成 16进制。网上有很多人的写法 都不是标准的。可以讨论下,我弄了一个标准的写法,兼容32位与64位。

从IntToHex()说起,这个方法 官方设计时 是如何想的 我不懂;反正乱,这也是导致很多人 把指针转换成16 多种写法的主要原因。

看下图 官方提供了 3个函数:

你要知道 32位程序,指针是无符号32位的 即Cardinal 类型;64位是 UInt64 类型。

官方上面三个函数中提供了 Uint64 入参,却没有提供Cardinal入参的重载。

再看这三个函数的实现:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function IntToHex(Value: Integer; Digits: Integer): string;
begin
  Result := _IntToHex(Cardinal(Value), Digits);
end;
 
function IntToHex(Value: Int64; Digits: Integer): string;
begin
  Result := _IntToHex(Value, digits);
end;
 
function IntToHex(Value: UInt64; Digits: Integer): string;
begin
  Result := _IntToHex(Value, digits);
end;

你会发现第一个函数,Integer的这个 内部又转成了 Cardinal ,然后调用了_IntToHex ,而这个函数的入参是Uint64,所以又再次把Cardinal 转成了UInt64;折腾不折腾,多写一个函数会死啊;上面三个函数 都调用了 _IntToHex,我们接下来看这个函数;

function _IntToHex(Value: UInt64; Digits: Integer): string;

他的入参是 UInt64,所以说 上面三个IntToHex 最终都变成了UInt64;为什么最终 都用了 UInt64,我们要看这个函数的名字: IntToHex 意思是把整型转成16进制,而无符号64位 所能表达的范围最广,能兼容一切整型;即Int8、UInt8、Int32、UInt32(Cardinal)、Int64都能转换成 UInt64 而不溢出。

罢了 罢了 不管官方的设计了,我们只能再官方的基础上 做我们想做的事:

拿到栈中指针的地址与堆中数据的地址的标准写法是(谁不同意欢迎讨论):

 
1
2
3
4
5
6
7
8
9
10
procedure TForm4.Button1Click(Sender: TObject);
var
  s: string;
begin
  s := 'QDAC';
 
  //标准写法
  Memo1.Lines.Add('栈中指针地址:' + IntToHex(UInt64(Pointer(@s)), SizeOf(s)*2));
  Memo1.Lines.Add('堆中数据地址:' + IntToHex(UInt64(Pointer(s)), SizeOf(s)*2));
end;
http://blog.qdac.cc/?p=4440
https://sourceforge.net/projects/qdac/
 
-------------------------------------------------------------------------------------
再加上两句:
Memo1.Lines.Add('堆中数据地址:' + IntToStr(Integer(Pointer(s))));

Memo1.Lines.Add(Format('S[1]的地址: %p', [@S[1]]));
Memo1.Lines.Add(Format('S[2]的地址: %p', [@S[2]]));

Memo1.Lines.Add(Format('S[1]的地址: %d', [Integer(@S[1])]));
Memo1.Lines.Add(Format('S[2]的地址: %d', [Integer(@S[2])]));

输出结果:

栈中指针地址:0019F4BC
堆中数据地址:0044FD4C // 等于十进制 4521292

堆中数据地址:4521340 // 为什么不等于上面那个值,而是相差了48个字节?
S[1]的地址: 02242590
S[2]的地址: 02242591
S[1]的地址: 35923344 // 就是02242590的十进制
S[2]的地址: 35923345

为什么s[1]的地址,和上面2个值(栈中指针和堆中数据)都没有关系?
我觉得S字符串的内容,肯定在堆里啊,但是S[1]和堆里的地址不是连续的,这是怎么回事?

你用 integer就是个错误
你要知道 内存编号 是只有正数 何来负数
为了兼容64位与32位 必须得用 64位无符号 整型
64下 你用 integer就会 内存编号 过大的话 就会溢出

从IntToHex()说起,栈/堆地址标准写法 good的更多相关文章

  1. C# 获取变量或对象的栈与堆地址

    C# 获取变量或对象的栈与堆地址 来源 https://www.cnblogs.com/xiaoyaodijun/p/6605070.html using System; using System.C ...

  2. 栈 堆 stack heap 堆内存 栈内存 内存分配中的堆和栈 掌握堆内存的权柄就是返回的指针 栈是面向线程的而堆是面向进程的。 new/delete and malloc/ free 指针与内存模型

    小结: 1.栈内存 为什么快? Due to this nature, the process of storing and retrieving data from the stack is ver ...

  3. GDB调试汇编栈堆过程的学习

    前期调试 我的程序代码是: 首先,用gcc g gdb.c -o gdb -m32产生32位汇编. 输入gdb gdb进入gdb调试器 在main函数处设置一个断点:b main 用disassemb ...

  4. 对抗栈帧地址随机化/ASLR的两种思路和一些技巧

    栈帧地址随机化是地址空间布局随机化(Address space layout randomization,ASLR)的一种,它实现了栈帧起始地址一定程度上的随机化,令攻击者难以猜测需要攻击位置的地址. ...

  5. Java内存分析--栈--堆

    Java内存分析--栈--堆 JVM的内存分析: 1.栈内存 1.连续的存储空间,遵循后进先出的原则. 2.每个线程包含一个栈区,栈区只保存基础数据类型的对象和自定义对象的引用. 3.每个栈中的数据都 ...

  6. $.ajax()参数详解及标准写法(转)

    1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如 ...

  7. jQuery ajax 标准写法及进度条绘制

    jQuery ajax 标准写法及进度条绘制 $.ajax({ url: "http://www.microsoft.com", //请求的url地址 dataType: &quo ...

  8. JQuery的Ajax标准写法

    Ajax的标准写法 $.ajax({ url:"http://www.xxx",//请求的url地址 dataType:"json",//返回的格式为json ...

  9. ajax标准写法

    ajax 标准写法 $.ajax({ url:"http://www.microsoft.com", //请求的url地址 dataType:"json", / ...

随机推荐

  1. 选iphone5可以正常编译运行 , 但是5s和6和6s都会编译报错

    选iphone5可以正常编译运行   但是5s和6和6s都会编译报错 iphone6编译报错iphone5s编译报错 解决办法是,Build settings里面把Architectures里面的$( ...

  2. js声明json数据,打印json数据,遍历json数据,转换json数据为数组

    1.js声明json数据: 2.打印json数据: 3.遍历json数据: 4.转换json数据为数组; //声明JSON var json = {}; json.a = 1; //第一种赋值方式(仿 ...

  3. ASP.NET中进度条的简单应用

    <html xmlns="http://www.w3.org/1999/xhtml" id="mainWindow"> <head> & ...

  4. 线性方程组的求解(C++)

    1. 最佳求解方案 Most efficient way to solve a system of linear equations 求解形如 Ax=b 的最佳方式 将 A 分解为三角矩阵,A=M1⋅ ...

  5. VS2010中新控件的编程------颜色按钮类和颜色对话框

    (1)      颜色按钮类和颜色对话框 1) 颜色对话框 MFC提供了颜色对话框类CMFCColorDialog进行颜色的选择,系统可以利用DoModal()调用,然后选择相应的颜色. CMFCCo ...

  6. sqlserver中获取最后一个字符所在的位置

    CHARINDEX('字符',reverse(字段名称)) 这个意思就是将字段进行反转,就是从后往前取,这样就能够获取一个字符最后所在的位置

  7. python 快速排序 完整

    两头开始 以第一个为基准,从有往左,找第一个比基准数 大的,然后交换 从左往右,找第一个比基准数晓得,然后交换 遍历剩下的 基准数  左边的数们  以及  基准数 右边的数们 def quick_so ...

  8. SQLite介绍及使用

    SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了 ...

  9. 此C语言功能---A

    功能名称: abort 动力 能够: 异常终止的过程的 使用 法国: void abort(void); 程序示例: #include <stdio.h> #include <std ...

  10. [GEiv]第七章:着色器 高效GPU渲染方案

    第七章:着色器 高效GPU渲染方案 本章介绍着色器的基本知识以及Geiv下对其提供的支持接口.并以"渐变高斯模糊"为线索进行实例的演示解说. [背景信息] [计算机中央处理器的局限 ...