c++ - 简单的功能大小;了解指针与指针的区别

标签 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<<(char*)dump-(char*)exec;  // this is 53
    return 0;
}

它应该从'dump'中减去'exec'的地址。这可行,但我注意到使用其他类型的指针(如 DWORD*)时值不同:

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<<(DWORD*)dump-(DWORD*)exec;  // this is 13
    return 0;
}

根据我的理解,无论指针类型如何,它始终是最大可能的数据类型(以便它可以处理大地址),在我的例子中是 4 字节(x86 系统)。指针之间唯一变化的是它指向的数据类型。

这是什么解释?

最佳答案

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

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

如果您有一个 char*unsigned char*,指针指向一个字节,递增指针会使它前进到下一个字节。

在 Windows 中,DWORD 是一个 32 位值(四个字节),DWORD* 指向一个 32 位值。如果您递增 DWORD*,指针将前进 四个字节,就像 array[1] 为您提供数组的第二个元素一样,这是第一个元素之后的四个字节(一个 DWORD)。同样,如果您将 10 添加到 DWORD*,它会前进 40 个字节,而不是 10 个字节。

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

指针减法和加法一样。当您从一个指针中减去另一个指针时,它们必须是同一类型,并且必须是指向同一数组的指针或指向末尾的指针。

您正在做的是计算两个指针之间的元素数量,就好像它们是指向同一个数组(或最后一个数组)的指针一样。但是当两个指针指向同一个数组时(或者,一个指向末尾),结果是未定义的行为。

这是卡内基梅隆大学关于此的引用资料:

ARR36-C. Do not subtract or compare two pointers that do not refer to the same array - SEI CERT C Coding Standard

关于c++ - 简单的功能大小;了解指针与指针的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48310589/

相关文章:

c++ - 使用 offsetof() 从成员变量中获取所有者对象

c - 如何从C中的数字中读取单独的(+,-)行

python - 为什么我的 Python 代码从一个函数跳转到另一个我没有调用的函数?

您能使用小端概念解释以下源代码的输出吗?

c++ - Objective-C 是否有 C++11 右值引用和 move 语义等价物或如何实现它?

C++模拟鼠标左键点击最小化程序

swift - 使用默认值参数覆盖函数时,如何保持默认值与父类(super class)相同?

C++ <type>*& 类函数或结构错误

C++:从另一个 vector 指向对象的指针 vector

c++ - 使用 enable_if 匹配数字作为函数参数