【问题标题】:error C2446: '==' : no conversion from 'int *' to 'int'错误 C2446:“==”:没有从“int *”转换为“int”
【发布时间】:2017-04-14 01:35:40
【问题描述】:

我想比较一个数字和一个地址。 这是代码。

#include "stdio.h"
int main (void) {
    int a = 1;
    printf("%#x\n", &a);  // The address of a is 0x18ff44
    int  b = 0x18ff44;
    if (b == &a) {        //error
       printf("no\n"); 
    }
    return 0;
}

我想知道是否可以将数字与地址进行比较。

错误:错误 C2446:'==':没有从 'int *' 到 'int' 的转换

我做了一些研究,我有两个假设:

  • 可能是因为不同的数据类型无法比较。

    但我尝试将float的数据类型与char进行比较,代码编译正确。

  • 我了解到 MSDN 的编译器错误 c2446。翻译为“编译器无法将 type1 转换为 type2。”

我的假设是,在执行关系操作时,编译器需要将 type1 转换为 type2。但是 'int *' 到 'int' 的转换没有意义。 我的问题:这个假设正确吗?如果不是,为什么会发生这种情况?

编译器信息:从https://www.microsoft.com下载的VC 6.0

【问题讨论】:

  • 首先如果你想打印一个指针,你应该使用"%p"格式,并且它必须是void *(需要显式转换)。阅读例如this printf (and family) reference 了解更多信息。
  • 您的代码调用了未定义的行为。要打印指针,请使用 %p,它需要 void *
  • 至于错误,应该很清楚了:你有两个不兼容类型的值要比较。
  • @Someprogrammerdude 这是 Visual C 6.0。如果它完全符合 C89 那就太神奇了,更不用说符合现代 C 标准了。

标签: c pointers


【解决方案1】:

b (int) 的类型与表达式&a (int *) 的类型不兼容。修复很简单——将b 声明为int *

int *b = (int *) 0x18ff44; // literal will have integral, non-pointer type,
...                        // so the cast is necessary
if ( b == &a )  // int * == int *
{
  ...
}

现在表达式具有兼容的类型,错误将消失。

打印指针值,使用%p转换说明符:

printf( "&a = %p\n", (void *) &a );

这是 C 语言中极少数(如果不是唯一的话)需要使用 void * 的地方之一。

编辑

要回答更大的问题,为什么intint * 不兼容?

int 数据类型是有符号类型,并且仅保证表示[-32767,32767] 范围内的值。它可能能够表示更广泛的值(在大多数现代实现中,它确实如此,通常是[-2<sup>32</sup>, 2<sup>32</sup>-1]),但它可能能够也可能不能表示所有可能的指针值。指针值可以转换为int 值,反之亦然,但不能保证结果是有意义的或定义明确的。

指针类型的表示基本上取决于实现,并且该表示甚至可能不是标量值。对于不同的指针类型,它甚至可能不同(尽管void *char * 必须具有相同的表示和对齐方式)。因此,int 和指针类型之间的直接比较可能没有意义。实现可能在后台使用相同的字长和表示,但由于不能保证是这种情况,语言要求类型不兼容。

【讨论】:

    【解决方案2】:

    是的,您可以将变量与地址进行比较,但这非常危险。

    首先,您的代码可以使用 gcc 4.6.3 版正确编译。所以我假设编译器错误与 MSVC 有关,肯定可以禁用。

    尽管如此,

    地址类型是size_t,取决于您的机器和构建环境,它(通常)可以是 32 或 64。另一方面,一个整数可能小于 size_t,不足以寻址整个 RAM!

    所以我建议您使用 size_t 而不是 int(或将整数和指针都转换为 size_t)然后比较它们,我认为这是最安全且更有意义的,因为我们真正比较的是两种内存指针类型而不是整数和浮点数。

    我会这样做:

    size_t a_adr = (size_t)&a;
    size_t b_adr = (size_t)&b;
    
    if (a_adr == b_adr)
       ..
    

    处理指针时要小心我的朋友。

    【讨论】:

    • 我不认为size_t 保证足够大以容纳指针。如果编译器有它 intptr_t 是正确的类型。对于 VC 6,int 已经足够大了,尽管我会选择 unsigned long
    • 为什么不将b 声明为int *
    【解决方案3】:

    这似乎有效:

    #include "stdio.h"
    int main (void) {
        int a = 1;
        printf("%p\n", &a);  // The address of a is 0x18ff44
        int  b = 0x18ff44;
        if (b == (int) &a) {        //no error
           printf("no\n"); 
        }
        return 0;
    }
    

    编辑:为了 64 位系统的通用性,使用这个:

    #include "stdio.h"
    int main (void) {
        int a = 1;
        printf("%p\n", &a);  // The address of a is 0x18ff44
        long long b = 0x18ff44;
        if (b == (long long) &a) {        //no error
           printf("no\n"); 
        }
        return 0;
    }
    

    【讨论】:

    • 它可能似乎工作,但如果指针不适合int(这在 64 位系统上通常是正确的)怎么办?这通常是比较指针的一种非常糟糕的方式。
    • @Someprogrammerdude 这是 VC6。它是严格的 32 位。
    • @JeremyP:这仍然是比较指针值的一种非常糟糕的方式。
    • @JohnBode 对此没有异议。据我所知,没有可移植的方式将文字值与指针进行比较。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多