可以在C中比较指针和整数吗?

时间:2015-03-13 19:27:49

标签: c pointers

我正在编写一些将虚拟地址映射到物理地址的代码。

我有这些代码:

if (address > 0xFFFF)
   Status = XST_FAILURE; // Out of range
else if (address <= 0xCFFF || address >= 0xD400) {
   // Write to OCM
   Xil_Out8(OCM_HIGH64_BASEADDR + OCM_OFFSET + address, data);
else { // (address >= 0xD000)
   // Write to external CCA
   Status = ext_mem_write(address, data);

我收到编译器警告: comparison between pointer and integer [enabled by default]

我意识到我正在比较两种不同的类型(指针和整数),但这是一个问题吗?毕竟,将指针与整数进行比较正是我想要做的。

定义要比较的指针常量而不是整数会更清晰吗?

const int *UPPER_LIMIT = 0xFFFF;
...
if (address > UPPER_LIMIT ){
    ....

3 个答案:

答案 0 :(得分:3)

干净的方法是使用uintptr_t类型的符号,它被定义为无符号整数,可以在指针和整数之间进行唯一映射。

这应该由#include <stdint.h>定义。如果未定义,则表示您的编译器不遵循C标准,或者系统没有平坦的内存模型。

它的目的是映射在&#34;显而易见的&#34;方式,即每个字节按升序排列一个整数。标准并不能绝对保证,但作为实施质量的问题,很难看到其他任何事情发生。

示例:

uintptr_t foo = 0xFFFF;

void test(char *ptr)
{
    if ( (uintptr_t)ptr < foo )
         // do something...
}

这是C标准明确定义的。使用void *而不是uintptr_t的版本是未定义的行为,但如果您的编译器不具有过于激进性,它可能会起作用。

答案 1 :(得分:2)

这可能是Linux内核使用unsigned long表示地址的原因(注意区别 - 指针指向一个对象,而地址是表示内存中位置的抽象代码)。

从编译器的角度看它是怎样的:

  1. C标准没有定义如何比较int(算术类型)文字0xFFFF和指针address - 请参阅段落 6.5.8
  2. 所以,它必须以某种方式转换操作数。两种转换都是实现定义为段落 6.3.2.3 状态。以下是编译器有资格做出的几个疯狂的决定:
    • 由于0xFFFF可能是int - 请参阅 6.4.4 ,它可能会强制指向int,如果是sizeof(int) < sizeof(void*),您将会失去更高的字节。
    • 0xFFFF符号扩展为0xFFFFFFFF时,我可以想象更疯狂的情况(不应该,但为什么不呢)
  3. 当然,(2)都不应该发生,现代编译器足够聪明。但它可能会发生(我假设您正在编写嵌入式内容,更有可能发生这种情况),这就是编译器发出警告的原因。

    这是&#34;疯狂编译器事物的一个实际例子&#34;:在GCC 4.8中,优化器开始将整数溢出视为UB(未定义行为)并省略指令,假设程序员没有&#39 ; t想要整数溢出https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61569

    我指的是 N1570 - C11标准草案

答案 2 :(得分:-1)

将指针转换为unsigned int以避免警告:(unsigned)address - 如果是32位或16位地址空间。