【问题标题】:Subtracting a value from a typedef in C?从C中的typedef中减去一个值?
【发布时间】:2020-12-30 18:47:25
【问题描述】:

我正在阅读一些 Windows API 头文件,并且看到了一些我不理解的代码:

typedef void *HANDLE;

typedef HANDLE DPI_AWARENESS_CONTEXT;

#define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1)

void * typedef 中减去一个值是什么意思?

【问题讨论】:

  • 我认为它是 (void*) -1 的转换,而不是从 void* 中减去 1
  • 假设#define 不存在,那么在代码中DPI_AWARENESS_CONTEXT 将是指向某个地址的指针。现在让我们介绍#define。在所有出现的DPI_AWARENESS_CONTEXT 中都会有一个尾随-1。指针算术中的那个意思是前面的地址。

标签: c winapi


【解决方案1】:

没有减法 - DPI_AWARENESS_CONTEXT_UNAWARE 扩展为 -1 转换为 void *。它似乎被用作DPI_AWARENESS_CONTEXT 类型的标记值(这是HANDLE 的typedef,这是void * 的typedef)。

【讨论】:

    【解决方案2】:

    这是一个演员,而不是一个减法。

    typedef void *HANDLE;
    

    导致符号 HANDLE 等效于 void *

    然后依次

    typedef HANDLE DPI_AWARENESS_CONTEXT;
    

    产生一个新符号DPI_AWARENESS_CONTEXT,它等同于void *

    导致表达式:

    #define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1)
    

    相当于:

    #define DPI_AWARENESS_CONTEXT_UNAWARE ((void *)-1)
    

    意味着源代码中DPI_AWARENESS_CONTEXT_UNAWARE 的任何实例在编译时扩展为(void *)

    顺便说一句 - 以下是方法和原因:

    (void *) -1 == (size_t) -1
    

    在 32 位机器上是 0xFFFFFFFF
    0xFFFFFFFFFFFFFFFF 在 64 位机器上。

    在每个各自架构的 twos complement 实现中,这些值等同于 -1,因此它们可用作sbrk())(内存分配支持)等例程中的标记值,或指定 dots per inch (dpi) awareness context

    注意:上述陈述对于一个补码系统是不正确的,但正如answers in this post 所指出的那样,一个补码很少见,并且不太可能用于任何最近的大规模商业环境。

    【讨论】:

    • 根据各自的架构,这两个地址都是有效的。这两个地址都不等同于-1,除非您假设2s 补码表示。尽管 Windows 的 ABI 要求它,但两种架构都没有强制要求。许多错误与权利交织在一起仍然会产生错误。对不起。
    • @IInspectable - 大声笑,无需抱歉 :) 我说 不太可能的地址 而不是 无效地址 会更正确,但因为 不太可能的地址 没有增加任何价值,所以我编辑了这一点。至于我对二进制补码的假设,再次,如果辩论这一点,我认为你会赢,因为世界仍然包含补码环境,尽管很少见。我还进行了编辑以解决这一点。感谢您的评论,这两点都是有效的,需要更正。
    猜你喜欢
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 2021-04-11
    • 1970-01-01
    • 2012-03-14
    • 1970-01-01
    相关资源
    最近更新 更多