LINUX.ORG.RU

Left arithmetic shift & UB

 ,


0

2
/* turn on all bits before word */
const unsigned short ones_mask = 0xFFFF << ws;
warning: The result of the '<<' expression is undefined
const unsigned short ones_mask = 0xFFFF << ws;
                                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~
1 warning generated.

Нужно городить switch-case или for?

★★★★★

Последнее исправление: CYB3R (всего исправлений: 1)

Можешь показать минимальный кусок кода, на котором это воспроизводится?

У меня не воспроизводится:

$ cat test.c 
#include <stdio.h>

int main()
{
	const int ws = 2;
	const unsigned short ones_mask = 0xFFFF << ws;
	printf("%04X\n", ones_mask);
	return 0;
}

$ clang -Wall -Wextra -ansi test.c -o test

$ ./test 
FFFC

$ clang --version
clang version 3.3 (tags/RELEASE_33/rc2)
Target: x86_64-redhat-linux-gnu
Thread model: posix

Deleted
()
Ответ на: комментарий от Deleted

пытаюсь.

Да, забыл написать, это получается через scan-build, если компилировать просто clang'ом, варнинга нет...

Stil ★★★★★
() автор топика
Ответ на: комментарий от Deleted

Как анонимус выше уже подметил, scan-build ожидает, что ws будет <= 32, иначе он ругается, хотя unsigned short всё равно же 16-битный. Хм, даже на 64-битный unsigned long ругается - вот тут уже что-то явно не то.

gag ★★★★★
()
Последнее исправление: gag (всего исправлений: 1)
Ответ на: комментарий от anonymous

по обстоятельствам, от 6 до 12

Stil ★★★★★
() автор топика
Ответ на: комментарий от Stil

Посмотри с какими опциями у тебя запускается сам компилятор и почитай про них повнимательней.

Странно, это что же он будет на каждый битшифт ругаться?

anonymous
()

я, честно говоря, ничего не понимаю, блок кода с этой строкой используется дважды в пределах функции, но один раз все ок, на второй раз - предупреждение

Stil ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Странно, это что же он будет на каждый битшифт ругаться?

не на каждый

Посмотри с какими опциями у тебя запускается сам компилятор и почитай про них повнимательней.

ок

Stil ★★★★★
() автор топика

код был вроде такого:

    unsigned char words[] = { 0x25, 0x26};
    const unsigned int ws = 6;

    const unsigned short test_zeros_word = (*words) >> 1;
    /* turn on all bits before word */
    const unsigned short ones_mask = 0xFFFF << (ws - 1);
    const unsigned short test_word = test_zeros_word | ones_mask;
    /* test all zeros */
    if (test_zeros_word == 0) {
        *words |= 1;
    }
    /* test for all ones */
    if (test_word == 0xFFFF) {
        *words &= 0xFFFE;
    }

вынес общий кусок в функцию - предупреждение исчезло. WTF?

Stil ★★★★★
() автор топика
Ответ на: комментарий от Stil

В стандарте написано для E1 << E2

If E1 has a signed type and nonnegative value, and E1*2**E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

Надо написать 0xFFFFu (беззнаковое)

anonymous
()
Ответ на: комментарий от gag

Вот так

	const unsigned short ones_mask = (unsigned long)0xFFFF << ws;
нормально. Значит, перед тем как двигать 0xFFFF (вне зависимости от того, переменной какого типа будет присваиваться результат), необходимо явное приведение типа, чтобы результат сдвига помещался. А неявно 0xFFFF приводится, похоже, к (unsigned?) int.

gag ★★★★★
()
Ответ на: комментарий от anonymous

В стандарте написано для E1 << E2
If E1 has a signed type and nonnegative value, and E1*2**E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
Надо написать 0xFFFFu (беззнаковое)

Спасибо, доброанон

Stil ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.