Яка перевага використання uint8_tнад unsigned charC?
Я знаю, що майже в кожній системі uint8_tє просто typedef для unsigned char, так навіщо це використовувати?
Яка перевага використання uint8_tнад unsigned charC?
Я знаю, що майже в кожній системі uint8_tє просто typedef для unsigned char, так навіщо це використовувати?
Відповіді:
Це документує ваш намір - ви будете зберігати невеликі числа, а не символ.
Крім того, це виглядає приємніше, якщо ви використовуєте інші typedefs, такі як uint16_tабо int32_t.
unsigned charабо signed charдокументуючи наміри теж, оскільки без реклами char- це те, що показує, що ви працюєте з персонажами.
unsignedбув unsigned intза визначенням?
charсхоже, йдеться про символ, тоді як у контексті рядка UTF8 це може бути лише один байт багатобайтового символу. Використання uint8_t може дати зрозуміти, що не слід очікувати символу в кожній позиції - іншими словами, кожен елемент рядка / масиву є довільним цілим числом, про яке не слід робити жодних семантичних припущень. Звичайно, це знають усі програмісти на C, але це може підштовхнути новачків до правильних питань.
Деякі системи, щоб бути педантичними, можуть не мати 8-бітового типу. Згідно Вікіпедії :
Потрібна реалізація для визначення цілочисельних типів точної ширини для N = 8, 16, 32 або 64, якщо і лише тоді, коли вона має будь-який тип, який відповідає вимогам. Не потрібно їх визначати для будь-яких інших N, навіть якщо вони підтримують відповідні типи.
Тому uint8_tне гарантовано існування, хоча це буде для всіх платформ, де 8 біт = 1 байт. Деякі вбудовані платформи можуть бути різними, але це стає дуже рідко. Деякі системи можуть визначати charтипи, що мають 16 біт, і в цьому випадку, ймовірно, не буде 8-бітового типу.
Окрім цього (другорядного) питання, на мою думку , відповідь @Mark Ransom - найкраща. Використовуйте той, який найбільш чітко показує, для чого ви використовуєте дані.
Крім того, я припускаю, що ви мали на увазі uint8_t(стандартний typedef від C99, наданий у stdint.hзаголовку), а не uint_8(не є частиною будь-якого стандарту).
uint8_t(або вводити до цього). Це тому, що тип 8 біт мав би невикористані біти у представленні сховища, яких uint8_tне повинно бути.
typedef unsigned integer type uint8_t; // optional Отже, по суті, бібліотека, що відповідає стандарту C ++, взагалі не потрібна для визначення uint8_t (див. Коментар // необов'язково )
Вся справа в тому, щоб написати незалежний від реалізації код. unsigned charне гарантується, що це 8-бітний тип. uint8_tє (якщо є).
sizeof(unsigned char)повернеться 1за 1 байт. але якщо системні char та int мають однаковий розмір, наприклад, 16-бітові, то sizeof(int)також повернуться1
Як ви сказали, " майже кожна система".
charце, мабуть, одна з менших шансів змінити, але як тільки ви почнете використовувати uint16_tта дружити, uint8_tкраще використовуйте суміші, і навіть може бути частиною стандарту кодування.
На мій досвід, є два місця, де ми хочемо використовувати uint8_t, щоб означати 8 біт (і uint16_t тощо), і де ми можемо мати поля менше 8 біт. В обох місцях є місце, де важливий простір, і нам часто потрібно дивитися на неочищений дамп даних при налагодженні, і потрібно мати можливість швидко визначити, що це таке.
Перший - у протоколах РФ, особливо у вузькосмугових системах. У цьому середовищі нам може знадобитися запакувати якомога більше інформації в одне повідомлення. Друга - у флеш-пам’яті, де у нас може бути дуже обмежений простір (наприклад, у вбудованих системах). В обох випадках ми можемо використовувати структуру упакованих даних, в якій компілятор подбає про упаковку та розпакування для нас:
#pragma pack(1)
typedef struct {
uint8_t flag1:1;
uint8_t flag2:1;
padding1 reserved:6; /* not necessary but makes this struct more readable */
uint32_t sequence_no;
uint8_t data[8];
uint32_t crc32;
} s_mypacket __attribute__((packed));
#pragma pack()
Який метод ви використовуєте, залежить від вашого компілятора. Також вам може знадобитися підтримка декількох різних компіляторів з однаковими файлами заголовків. Це відбувається у вбудованих системах, де пристрої та сервери можуть бути абсолютно різними - наприклад, у вас може бути пристрій ARM, який спілкується з сервером x86 Linux.
Існує кілька застережень із використанням упакованих структур. Найбільша проблема полягає в тому, що ви повинні уникати перенаправлення адреси члена. У системах з мутибайтовими вирівняними словами це може призвести до вирівнювання, яке не вирівнюється, - і коридору.
Деякі люди також будуть турбуватися про продуктивність і стверджують, що використання цих упакованих структур уповільнить вашу систему. Це правда, що поза кадром компілятор додає код для доступу до неприєднаних членів даних. Ви можете це бачити, дивлячись на код складання у вашому IDE.
Але оскільки упаковані структури є найбільш корисними для зв'язку та зберігання даних, то дані можуть бути вилучені в непакетоване представлення під час роботи з ним у пам'яті. Зазвичай нам не потрібно працювати з усім пакетом даних у пам'яті.
Ось відповідна дискусія:
pragma pack (1) ні __attribute__ ((вирівняний (1))) працює
Чи небезпечний __attribute __attribute __ ((упакований)) gcc / #pragma?
http://solidsmoke.blogspot.ca/2010/07/woes-of-structure-packing-pragma-pack.html
Тут мало. З точки зору портативності, вона charне може бути меншою ніж 8 біт, і нічого не може бути меншим char, тому, якщо дана реалізація C має непідписаний 8-бітний цілочисельний тип, це буде char. Крім того, він може не мати його взагалі, і в цей момент будь-які typedefтрюки суперечать.
Це можна використовувати для кращого документування вашого коду в сенсі, що зрозуміло, що вам потрібні 8-бітні байти та нічого іншого. Але на практиці це вже розумне очікування практично в будь-якому місці (є платформи DSP, на яких це неправда, але шанси вашого коду там невисокі, і ви можете так само помилитися, використовуючи статичне затвердження у верхній частині вашої програми на така платформа).
unsigned charщоб можна було утримувати значення між 0 і 255. Якщо ви можете це зробити в 4 біти, моя шапка знімається до вас.
uint8_tдо реалізації. Цікаво, чи компілятори для DSP з 16-бітовими символами зазвичай реалізують uint8_t, чи ні?
#include <stdint.h>і використовувати uint8_t. Якщо платформа має її, вона передасть її вам. Якщо на платформі її немає, ваша програма не збиратиметься, а причина буде зрозумілою та зрозумілою.
Це дуже важливо, наприклад, коли ви пишете мережевий аналізатор. заголовки пакетів визначаються специфікацією протоколу, а не тим, як працює компілятор C певної платформи.
Практично в кожній системі, з якою я зустрічався, не підписаний знак uint8_t ==, але це не гарантується стандартом C. Якщо ви намагаєтеся написати портативний код і має значення саме того, який розмір пам'яті, використовуйте uint8_t. В іншому випадку використовуйте неподписані знаки.
uint8_t завжди відповідає діапазону та розміру unsigned charта прокладці (немає), коли unsigned char 8-бітний. Коли unsigned charне є 8-бітовим, uint8_tне існує.
unsigned charце 8-біт, буде uint8_tгарантовано буде typedefїх , а не typedefз розширеного цілого числа без знака типу ?
unsigned char/signed char/charі найменший тип - не менше 8 біт. unsigned charне має прокладки. Щоб uint8_tце було, воно повинно бути 8-бітним, без прокладки, щоб існувати через цілий цілий тип, що відповідає: відповідає мінімальним вимогам unsigned char. Щодо "... гарантовано, що буде typedef ..." виглядає як хороше запитання для публікації.