2016-01-19 18 views
3

Я получаю сообщение об ошибке с помощью программы на C++ на 64-битной машине. Ошибка ниже. Чтобы полностью понять ошибку, я попробовал несколько вариантов программы, чтобы увидеть, когда ошибка/предупреждение не появляется. С вариантами я надеюсь лучше понять это.Сравнение обычной арифметики с арифметикой указателя

программы составляются с

gcc -Wall -Werror -Wextra 

error: comparison between signed and unsigned integer expressions


Эта программа дает мне ошибку. Это картина, которую я вижу.

  • sizeof возвращает size_t, который является беззнаковым длинным int.
  • Len повышен до беззнакового долгого 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; 
} 

Этот код компилировать файлы с из приведенной выше ошибки. Узора я вижу от этого

  • они одного и того же типа
  • Там нет продвижения целого, потому что все они Интс.
  • вычитание указателя должно возвращать неподписанный тип 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, который знаковых целочисленного типа? Если это так, 2 программы, которые работают правильно, имеют типы левой стороны, продвигаемые к подписанному int, потому что они являются uint16 и uint8, и их значения могут помещаться внутри подписанного int. поэтому 2 программы, которые работают, сравниваются как подписанный int < подписанный int?Но программа 2 не делает правильный ответ, потому что все переменные - uint32. Если указатели вернули знаковое целое с правой стороны, а uint32 с левой стороны вернули unsigned int, они были бы другой, так что программа 2 имела бы ту же ошибку.
  • Когда целочисленное продвижение происходит, если результат не присваивается какой-либо вещи, берет ли он тип того, к чему они были продвинуты? Как знаковое целое выше в левой части сравнения?

спасибо за любую помощь

+4

Если у вас есть программа на C++, не помещайте свой вопрос как C. Это разные языки. –

+5

'ptr - ptr2' подписан (это тип' ptrdiff_t'). Но это также неопределенное поведение, поэтому компилятор может делать все, что он хочет, и вы не можете в значительной степени вывести результат. –

+0

"sizeof возвращает size_t, который является беззнаковым длинным int." -> на вашей платформе. 'size_t' является _some unsigned type_ с _at наименьшим значением - 16-битным диапазоном. – chux

ответ

3

Я думаю, что это время кто-то положил, что мы узнали в комментариях в ответ, так что здесь идет.

В этой реализации size_t представляет собой 64-битовое целое без знака, а ptrdiff_t - это подписанное 64-битовое целое число.

В первом сравнении, if(len - sizeof(uint32_t) < ptr -ptr2), len повышается до 64 бит, но все же без знака, чтобы соответствовать sizeof, результат арифметики указателей, однако, подписан (ptrdiff_t). Поэтому он сравнивает значение без знака с подписанным значением.

В других случаях (if(len - len2 < ptr -ptr2)), len и len2 всегда меньше, чем 64 бит, так что результат или вычитание всегда может быть произведен в соответствии с 64-битной ptrdiff_t. Поскольку мы добавляем биты, «подписанность» результата не имеет значения (32-разрядный без знака может удобно размещаться в 64-битном, независимо от того, подписан он или нет) и, следовательно, может быть выбран в соответствии с другой стороной сравнения. Поэтому никаких ошибок и предупреждений не выдается.

+0

спасибо. ok, поэтому результат левой стороны должен быть увеличен до 64 бит, чтобы соответствовать ptrdiff_t. Я думал, что продвижение произошло только для + и -.Не знал, что это было повышено за < and > –

Смежные вопросы