Вы правы, конечно. Одного из приведений должно быть достаточно. Особенно, если приведен указатель, приведение извлеченного значения не допускается.
Вот x86-64, скомпилированный с gcc -O3
для ненужного приведения:
STRCMP:
.L4:
addq $1, %rdi
movzbl -1(%rdi), %eax
addq $1, %rsi
movzbl -1(%rsi), %edx
testb %al, %al
je .L7
cmpb %dl, %al
je .L4
subl %edx, %eax
ret
.L7:
movzbl %dl, %eax
negl %eax
ret
и вот тот, без лишнего приведения:
STRCMP:
.L4:
addq $1, %rdi
movzbl -1(%rdi), %eax
addq $1, %rsi
movzbl -1(%rsi), %edx
testb %al, %al
je .L7
cmpb %dl, %al
je .L4
subl %edx, %eax
ret
.L7:
movzbl %dl, %eax
negl %eax
ret
Они идентичны
Однако есть одна ошибка, которая в настоящее время в основном представляет исторический интерес. Если char
это со знаком и подписанное представление будет не дополнением до двух,
*(const unsigned char *)p1
и
(unsigned char)*p1
не эквивалент. Первая интерпретирует битовую комбинацию, а вторая преобразует значение, используя арифметику по модулю. Это представляет исторический интерес, так как даже GCC не поддерживает любую архитектуру , которая не имеет представления со знаком 2 дополнения. И это компилятор с большинством портов.