Да, использование int вместо char часто приводит к заметному харизу. Таким образом, использование int языком C, чтобы попытаться сопоставить собственный размер регистров в процессоре.
Рекомендуется использовать неподписанные ints везде, где это возможно, и только по редкому/конкретному случаю использовать что-то, отличное от unsigned int. Избегайте использования чего-то меньшего, чем int, если у вас нет действительно веской причины. Если вы пытаетесь использовать меньше, чем объекты int, чтобы получить некоторую производительность халявы по привычке программирования, вам нужно изменить свою привычку другим способом. То же самое касается unsigned, используйте unsigned что угодно, если у вас нет действительно веских оснований для использования подписанных.
В основном разобрать (или скомпилировать в asm), посмотреть на то, что генерируют ваши любимые и другие компиляторы, заметить неравномерную адресацию, вызванную символами, отметить маскировку верхних битов, расширение знака для подписанных символов и т. Д. Эти иногда свободны, а иногда и не зависят от того, откуда этот байт идет и на платформу. Также попробуйте как минимум x86 и руку, возможно, mips, gcc 3.x, 4.x и llvm. В частности, обратите внимание, как один символ, смешанный со списком int в строке деклараций, может привести к тому, что ints не будут выровнены, что отлично подходит для x86 с точки зрения адреса, но будет стоить в производительности (на x86 даже с кеш). Сначала поместите ваши выровненные переменные, а затем не выровнены последними. Другие платформы, которые не могут или не хотят делать неприсоединенные обращения, будут тратить лишние байты в качестве дополнения, так что вы не обязательно сохраняете память. Преждевременная оптимизация пытается настроить на переменную длину. Используйте простые привычки, такие как использование unsigned ints для всего, если у вас нет конкретной причины, сначала помещайте ваши большие, выровненные, переменные и структуры в список объявлений, а неглавные - последние (shorts then chars).
Умножает (и делит) делает эту привычку уродливой, избегая умножения и деления кода - лучшая привычка иметь. Если вы должны использовать один, достаточно хорошо осведомлены о его реализации. Гораздо лучше размножать два символа вместо двух ints, например (если номера поддерживают его), поэтому, если вы знаете, что ints действительно 7 бит или 5 бит или любые количества, приведите их в порядок для умножения и разрешите аппаратное умножение произойдет вместо мягкого умножения. (может быть спящий баг, если эти переменные размеры меняются !!). Несмотря на то, что многие процессоры имеют аппаратное умножение, очень редко можно использовать его напрямую. Если вы не поможете компилятору, он должен сделать вызов библиотеки, чтобы проверить переполнение между прочим, и может в конечном итоге сделать мягкое умножение в результате очень дорогостоящим. Разделения плохи, потому что большинство процессоров не включают разделение. И если они это сделают, вы можете попасть в ту же ловушку. с умножением бит N бит * N бит превращается в 2 * N бит результата, в котором возникает проблема с умножением. При делении числа остаются неизменными или уменьшаются. В обоих случаях isas не всегда обеспечивают достаточное количество бит для перекрытия переполнения, и требуется вызов библиотеки, чтобы обойти ограничения аппаратного обеспечения процессоров.
Плавающая точка - подобная история, просто будьте осторожны с плавающей точкой. Не используйте его, если это абсолютно необходимо.Большинство людей не помню, от руки, что
float a;
float b;
...
b = a * 1.0;
C предполагает двойную точность, если не указано иное, поэтому выше умножения требует, чтобы быть преобразованы в два раза, а затем умножается, то результат преобразуется обратно в сингл. Некоторые fpus могут преобразовывать точность в одну и ту же инструкцию за счет часов, некоторые не могут. Прецизионное преобразование - это то, где большинство ошибок вашего процессора с плавающей запятой живут (или делают). Так как использование удваивается за все, или быть осторожным с вашим кодированием, чтобы избежать этих ошибок:
float a;
float b;
...
b = a * 1.0F;
Кроме того, большинство ISAS не имеет FPU поэтому следует избегать точек математики с плавающей даже больше, чем избежать фиксированных умножают точки и водоразделы. Предположим, что у большинства fpus есть ошибки. Трудно написать хороший код с плавающей запятой (программист часто выбрасывает справедливую сумму точности, просто не зная, как его использовать и писать для него код).
Несколько простых привычек и ваш код работает заметно быстрее и чище, как халява. Кроме того, компилятор не должен работать так сильно, чтобы вы попадали в меньшее количество ошибок компилятора.
EDIT добавление точности с плавающей точкой пример:
float fun1 (float a)
{
return(a*7.1);
}
float fun2 (float a)
{
return(a*7.1F);
}
the first function contained:
mulsd .LC0(%rip), %xmm0
using a 64 bit floating point constant
.LC0
.long 1717986918
.long 1075603046
and the second function contains the desired single precision multiply
mulss .LC1(%rip), %xmm0
with a single precision constant
.LC1
.long 1088631603
char fun1 (char a)
{
return(a+7);
}
int fun2 (int a)
{
return(a+7);
}
fun1:
add r0, r0, #7
and r0, r0, #255
bx lr
fun2:
add r0, r0, #7
bx lr
Попробуйте использовать boost.cstdint вместо ваших определений типов – Abyx
Даже не используют TYPEDEF годов они просто в путь и ничего не спасать. – GManNickG
, а не uchar вы можете, t type unsigned char? Вы всегда можете измерить размер объекта с SizeOf() –