比较常规算术与指针算术

时间:2016-01-19 20:47:08

标签: c++ pointers pointer-arithmetic

我在64位计算机上遇到C ++程序错误。错误如下。为了完全理解错误,我尝试了一些程序变体来查看错误/警告何时没有出现。随着变化,我希望更好地理解它。

程序用

编译
gcc -Wall -Werror -Wextra
  

错误:有符号和无符号整数表达式之间的比较

这个程序给我错误。这是我看到的模式。

  • sizeof返回size_t,这是一个unsigned long int。
  • len作为常规算术的一部分被提升为unsigned long int,因此可以从size_t
  • 中减去
  • 使用ptr和ptr2进行正常算术
  • len是10所以len-sizeof(unint32_t)将产生6这是一个正数
#include <cstdio>
#include "stdint.h"

int main()
{
uint16_t len =10; 
uint8_t number  =5; 
uint8_t number2  =10; 
uint8_t * ptr =&number;
uint8_t * ptr2 =&number2;

        if(len - sizeof(uint32_t) < ptr -ptr2)
        {   
                 printf("done\n");
        }   
return 0;
}

此代码编译文件但没有上述错误。 我从中看到的模式是

  • 他们属于同一类型
  • 没有整数提升,因为它们都是整数。
  • 指针减法必须返回unsigned int类型,因此它与左侧匹配。
#include <cstdio>
#include "stdint.h"

int main()
{
uint32_t len =1; 
uint32_t len2 =3; 
uint32_t number  =5; 
uint32_t number2  =10; 
uint32_t * ptr =&number;
uint32_t * ptr2 =&number2;

    if(len - len2 < ptr -ptr2)
    {
        printf("Worked\n");
    }
}

这个程序编译好,没有上面的错误。 我在这里看到的模式

  • len和len2到32位整数有整数提升,所以
    他们可以减去。
  • ptr的正常指针算法 - ptr2。
#include <cstdio>
#include "stdint.h"

int main()
{
uint16_t len =2;
uint16_t len2 =5;
uint8_t number  =5; 
uint8_t number2  =10; 
uint8_t * ptr =&number;
uint8_t * ptr2 =&number2;

    if(len - len2 < ptr -ptr2)
    {
         printf("done\n");
    }
}

问题

  • 是减去ptr-ptr2返回ptrdiff_t类型的 有符号整数类型?如果是这样,正常工作的2个程序将左侧类型提升为signed int,因为它们是uint16和uint8,它们的值可以放在signed int中。因此,正在进行比较的2个程序正在进行比较。签了int?但是程序2没有使它成为有效的答案,因为所有变量都是uint32。如果指针在右侧返回一个符号整数,并且左侧的uint32返回一个unsigned int,则它们将是不同的signess,因此程序2将具有相同的错误。
  • 当整数提升发生时,如果结果没有分配给任何东西,那么采取他们被提升的类型吗?就像比较左边的符号整数一样?

感谢您的帮助

1 个答案:

答案 0 :(得分:3)

我认为是时候有人把我们在评论中学到的东西放到答案中了,所以就这样了。

在此实现中,size_t是无符号的64位整数,ptrdiff_t是带符号的64位整数。

在第一次比较中,if(len - sizeof(uint32_t) < ptr -ptr2)len被提升为64位,但仍然是无符号的,以匹配sizeof,但指针算术的结果是有符号的( ptrdiff_t)。因此,它将无符号值与有符号值进行比较。

在其他情况下(if(len - len2 < ptr -ptr2)),lenlen2总是小于64位,因此始终可以提升结果或减法以匹配64位{ {1}}。由于我们正在添加位,因此结果的“signed-ness”无关紧要(无符号32位可以在64位中舒适地坐着,无论它是否有符号),因此可以选择匹配另一侧比较。因此,不会发出错误或警告。