Чи за замовчуванням підписано чи непідписане char


158

У книзі "Повна довідка C" згадується, що charза замовчуванням не підписано.

Але я намагаюся перевірити це за допомогою GCC, а також Visual Studio. Він приймає його як підписане за замовчуванням.

Який з них правильний?


5
Єдиний довідник C, якому я довіряю, - це "С: Довідковий посібник" Harbison & Steele (довідник по роботі ) ( careferencemanual.com ). Звичайно, стандарт є заключним словом, але він не дуже читабельний і дає лише найменшу інформацію про передстандартні та поширені (наприклад, POSIX) використання, які знаходяться поза стандартом. Harbison & Steele є досить читабельним, детальним і, ймовірно, більш правильним, ніж більшість посилань. Однак це також не підручник, тому якщо ви перебуваєте на початкових стадіях навчання, то, мабуть, не дуже важливо вступати.
— Майкл Берр

15
Я думаю, що ви читаєте книгу С: Повна довідка Герберта Шильдта. З огляду на цю книгу ( accu.informika.ru/accu/bookreviews/public/reviews/c/c002173.htm ): Я не збираюся рекомендувати цю книгу (занадто багато з вас надають занадто велику вагу моїм думкам), але Я не думаю, що він заслуговує того самого опробріуму, який був законно кинутий на якусь іншу його роботу. Як каже Майкл, набагато краща довідка - Harbison & Steele .
— Алок Сінгал

Мої два центи тут: Оскільки charможе бути без підписання, як правило, використовуйте a, intщоб прочитати значення з використанням getchar(), яке може повернутися EOF. EOFзазвичай визначається як -1або інше від'ємне значення, яке зберігання в значенні unsignedне є тим, що потрібно. Ось декларація: extern int getchar();BTW, ця рекомендація також походить з книги "C: Довідковий посібник".
— Максим Четруска

6
Єдиною посиланням на C, якій я довіряю, є ISO / IEC 9899: 2011 :-)
— Jeff

3
@MaxChetrusca хороша порада, але погана аргументація: навіть у підписаному charвипадку вам доведеться використовувати intдля зберігання повернутого значення.
— Антті Хаапала

Відповіді:


204

Книга неправильна. Стандарт не вказує, чи charє звичайний підпис або без підпису.

Насправді, стандарт визначає три різних типи: char, signed char, і unsigned char. Якщо ви , #include <limits.h>а потім подивитися на CHAR_MIN, ви можете дізнатися, якщо ясно , charє signedчи unsigned(якщо CHAR_MINменше 0 або дорівнює 0), але навіть тоді три типи різні , наскільки стандарт стосується.

Зверніть увагу, що charособливе в цьому способі. Якщо ви оголошуєте змінну, оскільки intвона на 100% еквівалентна оголошенню її як signed int. Це завжди справедливо для всіх компіляторів та архітектур.


1
@Alok: те ж саме не стосується інших типів даних, наприклад, intозначає signed intзавжди, правда? Крім того char, в яких інших типах даних є така ж плутанина C?
— Лазер

8
@eSKay: так, charце єдиний тип, який можна підписати або не підписати. intеквівалентний, signed intнаприклад,
— Алок Сінгал

28
Для цього є істерична, е, історична причина - на початку життя C "стандарт" був перевернутий щонайменше двічі, а деякі популярні ранні компілятори закінчилися так, а інші - іншим.
— Гарячі лизання

9
@AlokSinghal: Це також визначено впровадженням, чи є бітове поле типу intпідписане чи без підпису.
— Кіт Томпсон

@KeithThompson дякую за виправлення. Я, як правило, забуваю деякі подробиці про типи бітових полів, оскільки я їх мало використовую.
— Алок Сінгал

67

Як зазначає Alok , стандарт залишає це до впровадження.

Для gcc за замовчуванням підписано, але ви можете змінити це за допомогою -funsigned-char. Примітка: для gcc в Android NDK за замовчуванням не підписано . Ви також можете чітко запитати підписані символи -fsigned-char.

У MSVC за замовчуванням підписано, але ви можете змінити це за допомогою /J.


2
Цікаво, що опис Шильдта не відповідає поведінці MSVC, оскільки його книги зазвичай орієнтовані на користувачів MSVC. Цікаво, чи змінив MS в якийсь момент за замовчуванням?
— Майкл Берр

1
Я думав, що це залежить не від компілятора, а від платформи. Я думав, що char залишається як третій тип "типу даних символів", щоб відповідати тому, що системи на той час використовували як символи для друку.
— Спайдей

10
НКА документи говорять , що машинно-залежний: « Кожен вид машини має значення по замовчуванням для того, що символ повинен бути Це або як непідписаний символ за замовчуванням або як підписаний напівкокс за замовчуванням .. »
— Deduplicator

1
Чи можете ви надати джерело для своєї замітки, що для андроїда типовий знак не має підпису?
— філіпсія

1
@Spidey Стандарт C не робить реального розмежування між компіляторами, платформами та архітектурами процесора. Це просто згуртовує їх усіх разом під "реалізацією".
— підключення

35

Проект 6.2.5 / 15 проекту "Типи" C99 N1256 говорить про підпис типу char:

Реалізація повинна визначати, щоб char мав той самий діапазон, представлення та поведінку, що і підписаний, або неподписаний.

і у виносці:

CHAR_MIN, визначене в <limits.h>, матиме одне із значень 0або SCHAR_MIN, і це можна використовувати для розрізнення двох варіантів. Незалежно від зробленого вибору, charце окремий тип від двох інших і не сумісний ні з одним.


7

Згідно з книгою мови програмування С Деніса Річі, яка є фактично стандартною книгою для ANSI C, звичайні символи, підписані або без підпису, залежать від машини, але символи для друку завжди позитивні.


9
Не обов’язково так, що символи для друку завжди позитивні. Стандарт C гарантує, що всі члени основного набору символів виконання мають негативні значення.
— Кіт Томпсон

7

Відповідно до стандарту C, підписаність простої символіки "визначено реалізацією".

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



2
@plugwash Ваша відповідь, ймовірно, була оскаржена, оскільки Тім Пост втратив ключі . Якщо серйозно, то вам не слід турбуватися про єдиний потік, доки ви впевнені, що ваша відповідь правильна (що це в цьому випадку). Мені траплялося кілька разів, щоб мої публікації були відхилені без поважних причин. Не хвилюйтеся з цього приводу, іноді люди просто роблять дивні речі.
— Дональд Дак

1
Чому підписаний знак char є більш ефективним на x86? Будь-які джерела?
— мартінкунев

2

Відповідно до "Мова програмування на C ++" від Bjarne Stroustrup, charце "визначення визначено". Це може бути signed charабо unsigned charзалежно від реалізації. Ви можете перевірити char, підписано це чи ні, скориставшись std::numeric_limits<char>::is_signed.


9
Це питання С. C ++ - це інша мова, і посилання на C ++ не мають відношення до C.
— ММ

1

Тепер ми знали стандартні листи, які залежать від впровадження.

Але як перевірити тип є, signedабо unsigned, як char?

Я написав макрос для цього:

#define IS_UNSIGNED(t) ((t)~1 > 0)

і перевірити його gcc, clangі cl. Але я не впевнений, що це завжди безпечно для інших випадків.


Що не так із звичайним CHAR_MIN <0 (або WCHAR_MIN <0 для wchar_t)?
— Öö Tiib
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.