C++ 简单的功能尺寸;理解指针差异

C++ 简单的功能尺寸;理解指针差异,c++,function,pointers,memory-address,C++,Function,Pointers,Memory Address,我正在测试一些计算函数大小的方法,以字节为单位(我熟悉x86上的操作码)。这段代码是不言自明的: void exec(void* addr){ int (WINAPI *msg)(HWND,LPCSTR,LPCSTR,UINT)=(int(WINAPI *)(HWND,LPCSTR,LPCSTR,UINT))addr; msg(0,"content","title",0); } void dump(){}; int main() { cout<<(cha

我正在测试一些计算函数大小的方法,以字节为单位(我熟悉x86上的操作码)。这段代码是不言自明的:

void exec(void* addr){
    int (WINAPI *msg)(HWND,LPCSTR,LPCSTR,UINT)=(int(WINAPI *)(HWND,LPCSTR,LPCSTR,UINT))addr;

    msg(0,"content","title",0);
}
void dump(){};

int main()
{

    cout<<(char*)dump-(char*)exec;  // this is 53
    return 0;
}
void exec(void*addr){
int(WINAPI*msg)(HWND,LPCSTR,LPCSTR,UINT)=(int(WINAPI*)(HWND,LPCSTR,LPCSTR,UINT))addr;
味精(0,“内容”,“标题”,0);
}
void dump(){};
int main()
{

cout指针减法告诉您两个地址之间的元素数,因此使用DWORD*将以DWORD大小为单位。

C/C++中的指针算法是为访问数组的元素而设计的。事实上,数组索引只是指针算法的一种简单语法。例如,如果您有一个名为
array的数组de>,
array[1]
*(array+1)
是一样的,无论
数组中元素的数据类型如何

(我在这里假设没有发生运算符重载;这可能会改变一切。)

如果有一个
char*
unsigned char*
,指针将指向一个字节,递增指针将使其前进到下一个字节

在Windows中,
DWORD
是一个32位的值(四个字节),
DWORD*
指向一个32位的值。如果您增加一个
DWORD*
,指针将前进四个字节,就像
array[1]
给您数组的第二个元素,即四个字节(一个
DWORD
)在第一个元素之后。类似地,如果将10添加到
DWORD*
,它将前进40个字节,而不是10个字节

无论哪种方式,只有当结果指针指向与原始指针相同的数组,或指向超过末尾的一个元素时,递增或添加到指针才有效。否则,这是未定义的行为

指针减法的工作原理与加法类似。当从一个指针减去另一个指针时,它们必须是相同类型的指针,并且必须是指向同一数组的指针,或者是超过末尾的指针

你要做的是计算两个指针之间的元素数,就好像它们是指向同一数组的指针(或者一个指针超过了数组的末尾)。但是当两个指针没有指向同一数组(或者再一次,一个指针超过了数组的末尾)时,结果是未定义的行为

以下是卡内基梅隆大学的参考资料:

您有:

cout<<(char*)dump-(char*)exec;
(对于C有一个类似的诊断,我认为这并不完全正确,但这是另一个故事。)

不能保证对象指针和函数指针之间存在任何有意义的关系

显然,您的编译器允许您进行强制转换,并且可能结果是函数地址的
char*
表示。减去两个指针可以得到两个地址之间的距离(以指针指向的类型为单位)。减去两个
char*
指针可以得到
ptrdiff\u t
结果是以字节为单位的差异。减去两个
DWORD*
指针将产生以
sizeof(DWORD)
为单位的差异(可能是4个字节?)。这就解释了为什么会得到不同的结果。如果两个
DWORD
指针没有指向内存中相隔不到整数个
DWORD
的地址,则结果是不可预测的,但在您的示例中,得到13个而不是53个(截断)是合理的

但是只有当两个指针操作数都指向同一数组对象的元素或刚刚超过该数组对象的末尾时,才定义指针减法。对于任何其他操作数,其行为都是未定义的

对于允许强制转换的实现,对于对象指针和函数指针使用相同的表示,并且函数指针的值以与对象指针的值相同的方式引用内存地址,您可能可以通过将其地址转换为
字符来确定函数的大小*
并从相邻函数的转换地址中减去结果。但是编译器和/或链接器可以自由地按任意顺序为函数生成代码,包括可能在源代码中定义相邻的两个函数之间插入其他函数的代码

如果要确定以字节为单位的大小,请使用指向字节大小类型的指针,如
char
。请注意,您使用的方法不可移植,也不能保证有效


<>如果你真的需要一个函数的大小,看看你能否让你的链接器生成一个显示你的函数的大小和位置的映射。没有从C++中可以移植的方法。

<代码>指针到两个无关的东西的C++是没有意义的。输出文件中的顺序;此减法可能不会给出您期望的结果。@wildplasser:
(char*)dump
是指针(如果接受强制转换)。
(char*)dump-(char*)exec
是类型为
ptrdiff\u t
的整数。(顺便说一句,
@KeithThompson oops。你当然是对的。假设有3个字节。这将如何转换为DWORD大小的单位?@sergiureznicencu如果要减去的两个东西不是指向同一数组的元素的指针,这是未定义的行为。在DWORD数组中,不能有2个元素被3个字节分隔。不仅仅是e同一类型。[expr.add]/6状态:除非两个指针都指向同一数组对象的元素,或者一个指针超过了数组对象的最后一个元素,否则该行为是未定义的。是的,我第一次写它时不太清楚;当你写评论时,我正在编辑以解决这个问题。谢谢你一直提醒我!
cout<<(char*)dump-(char*)exec;
warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object [-Wpedantic]