Коли використовувати непідписані значення над підписаними?


82

Коли доцільно використовувати непідписану змінну над підписаною? Як щодо forциклу?

Я чую багато думок з цього приводу, і я хотів перевірити, чи не було чогось подібного до консенсусу.

for (unsigned int i = 0; i < someThing.length(); i++) {  
    SomeThing var = someThing.at(i);  
    // You get the idea.  
}

Я знаю, що Java не має беззнакових значень, і це, мабуть, було свідомим рішенням з боку Sun Microsystems .


1
Я знайшов це корисним: codemines.blogspot.ca/2007/10 / ...
Mk12

Я думаю, що це питання цілком засноване на думках. Представлений код працюватиме в обох випадках просто чудово, тому ви можете використовувати обидва. За винятком причин ефективності (поки жодна відповідь фактично не стосується продуктивності), це лише особистий смак.
Триларіон

Відповіді:


69

Я був радий знайти хорошу розмову на цю тему, оскільки раніше я не надто роздумував над цим.

Підводячи підсумок, підпис - це хороший загальний вибір - навіть якщо ви мертві впевнені, що всі цифри позитивні - якщо ви збираєтеся робити арифметику змінної (як у типовому випадку для циклу).

Якщо ви збираєтеся робити побітові речі, такі як маски, підпис починає мати більше сенсу. Або, якщо ви відчайдушно бажаєте отримати цей додатковий позитивний діапазон, скориставшись знаковим бітом.

Особисто мені подобається підписувати, бо я не довіряю собі залишатися послідовним та уникати змішування цих двох типів (як у статті застерігає).


3
Пізніше в цьому потоці показано, що unsignedвін значно перевершує виявлення переповнення ненадійних входів. На жаль, запропоновані "відповіді" на загадку не такі вже й чудові. Моє - template<size_t limit> bool range_check_sum( unsigned a, unsigned b ) { return (a < limit) && (b < limit - a); } якщо хтось має таку саму просту і зрозумілу відповідь із використанням підписаних типів, я хотів би це побачити.
Ben Voigt

10

У наведеному вище прикладі, коли „i” завжди буде позитивним і вищий діапазон буде корисним, буде корисним unsigned. Наприклад, якщо ви використовуєте оператори 'declare', такі як:

#declare BIT1 (unsigned int 1)
#declare BIT32 (unsigned int reallybignumber)

Особливо, коли ці значення ніколи не зміняться.

Однак, якщо ви робите програму бухгалтерського обліку, де люди безвідповідально ставляться до своїх грошей і постійно перебувають у мінусі, ви, безумовно, захочете скористатися підписом.

Однак я погоджуюсь зі святим, що хорошим емпіричним правилом є використання підписаного, який, насправді, за замовчуванням C, так що ви покриті.


9

Я вважаю, що якщо ваша ділова справа диктує, що від’ємне число недійсне, ви хочете, щоб помилка відображалася або видавалась.

Маючи це на увазі, я нещодавно дізнався про цілі числа без підпису під час роботи над проектом, який обробляє дані у двійковому файлі та зберігає дані у базі даних. Я навмисно "псував" двійкові дані і в підсумку отримував негативні значення замість очікуваної помилки. Я виявив, що, незважаючи на те, що вартість перетворена, вона не є дійсною для мого бізнесу
Моя програма не помилилася, і в підсумку я потрапив неправильні дані в базу даних. Було б краще, якби я скористався uintпрограмою і провалився.


8

Компілятори C та C ++ генеруватимуть попередження, коли ви порівнюєте підписані та непідписані типи; у вашому прикладі коду ви не можете зробити свою змінну циклу неподписаною, а компілятор генерує код без попереджень (за умови, що зазначені попередження були ввімкнені).

Звичайно, ви складаєтеся з попередженнями, повернутими до кінця, так?

І, чи замислювались ви над тим, щоб скласти "попередження як помилку", щоб зробити ще один крок далі?

Недоліком використання підписаних чисел є те, що існує спокуса перевантажити їх так, що, наприклад, значення 0-> n є вибором меню, а -1 означає, що нічого не вибрано - замість створення класу, який має дві змінні, одну до вкажіть, чи вибрано щось, а інше для зберігання того, що це вибір. Перш ніж ви це зрозумієте, ви всюди тестуєте на мінус, і компілятор скаржиться на те, як ви хочете порівняти виділення меню з кількістю вибраних вами меню - але це небезпечно, оскільки вони різних типів . Тож не робіть цього.


6

size_tчасто є гарним вибором для цього, або size_typeякщо ви використовуєте клас STL.


Тільки коли ви маєте справу з розміром чогось у байтах.
mk12

Контейнери стандартної бібліотеки @ mk12 виставляють size_typeчлена для підрахунку елементів, а не лише байтів. Його слід використовувати замість того, std::size_tде він є, але невірно означати, що будь-що, що починається з, size_tможе означати лише байти.
underscore_d
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.