Чи за замовчуванням підписано чи непідписане 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.