Почему это условие всегда верно?(pktNum! = invPktNum) - PullRequest
6 голосов
/ 23 ноября 2010

Когда я компилирую следующий код, мой компилятор жалуется, что следующая строка всегда верна.Я думаю, что у меня может быть ошибочное понимание оператора != ...

if (pktNum != ~invPktNum) {
    return 1;
}

Я пытаюсь проверить, что invPktNum действительно является обратным к pktNum.Если нет, немедленно выйдите, в противном случае действуйте как обычно.

Я проверил и pktNum неподписанный символ 0x01, а invPktNum - неподписанный символ 0xFE на момент сравнения.

Кто-нибудь может меня просветить?Заранее спасибо!

Ответы [ 4 ]

10 голосов
/ 23 ноября 2010

В C значения в большинстве выражений, которые имеют тип, более узкий, чем int, переводятся в более широкий тип до выполнения вычисления. Если int достаточно широк, чтобы вместить все значения более узкого типа, то оно повышается до int; в противном случае он повышается до unsigned int.

В этом случае int достаточно широк, чтобы вместить все значения вашего unsigned char, поэтому ваши значения повышаются до int.

pktNum (и, следовательно, повышенный pktNum) может иметь значение от 0 до 255 включительно. Это значение, которое будет использоваться в левой части оператора !=.

invPktNum также может иметь значение от 0 до 255 включительно. Это значение будет повышено до int, а затем будет поразрядно отрицаться. Результатом этого побитового отрицания всегда будет отрицательное число, поскольку знаковый бит будет отрицаться. Это значение, которое будет использоваться в правой части оператора !=.

Никакое отрицательное число не может быть равным повышенному pktNum, поэтому условие всегда выполняется.

Чтобы выполнить вычисление, которое вы на самом деле хотите, вам нужно замаскировать младшие восемь бит после отрицания:

if (pktNum != (~invPktNum & 0xff)) {
    return 1;
}

Или же вы можете просто отменить интересующие вас биты:

if (pktNum != (invPktNum ^ 0xff)) {
    return 1;
}
0 голосов
/ 23 ноября 2010

Возможно, простой тип независимого теста:

if (0 == (pktNum & pkNum)) {

Что равно:

if (0 == (0xfe & 0x01)) {

Быстро протестировано с http://codepad.org/nziOGYJG, кажется, работает с несколькими типами long / int со знаком и без знака.

У кого-нибудь есть комментарии?

0 голосов
/ 23 ноября 2010

Если предположить следующее:

invPktNum = ~pktNum

, тогда ваше сравнение эквивалентно:

if (pktNum != ~(~pktNum)) {

или

if (pktNum != pktNum) {

, что всегда ложноЕсли у invPktNum нет другого определения в вашем коде, которое не отображается.

0 голосов
/ 23 ноября 2010

Вы смотрите на 8-битные значения.Могу поспорить, что pktNum и invPktNum являются 32-битными значениями, поэтому вы сравниваете 0x000000fe с 0xfffffffe.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...