Apakah char ditandatangani atau tidak ditandatangani secara default?

158

Dalam buku "Referensi Lengkap C" disebutkan bahwa charsecara default tidak ditandatangani.

Tetapi saya mencoba memverifikasi ini dengan GCC serta Visual Studio. Itu diambil sebagai ditandatangani secara default.

Yang mana yang benar?

C Pelajar
sumber
5
Satu buku referensi C yang saya percayai adalah "C: A Reference Manual" milik Harbison & Steele ( careferencemanual.com ). Tentu saja standar adalah kata terakhir, tetapi itu tidak terlalu mudah dibaca dan hanya memberikan sedikit informasi tentang penggunaan pra-standar dan umum (mis., POSIX) yang berada di luar standar. Harbison & Steele cukup mudah dibaca, terperinci dan mungkin lebih benar daripada kebanyakan referensi. Namun, ini juga bukan tutorial, jadi jika Anda berada di tahap awal pembelajaran, mungkin bukan hal yang baik untuk dilakukan.
Michael Burr
15
Saya pikir buku yang Anda baca adalah C: The Complete Reference , oleh Herbert Schildt. Dari ulasan buku ini ( accu.informika.ru/accu/bookreviews/public/reviews/c/c002173.htm ): Saya tidak akan merekomendasikan buku ini (terlalu banyak dari Anda memberikan terlalu banyak pendapat pada pendapat saya) tetapi Saya tidak berpikir itu layak atas kelemahan yang sama yang telah dilemparkan secara sah pada beberapa karyanya yang lain. Seperti kata Michael, referensi yang jauh lebih baik adalah Harbison & Steele .
Alok Singhal
Dua sen saya di sini: Karena chardapat ditandatangani, sebagai aturan praktis gunakan a intuntuk membaca nilai menggunakan getchar(), yang mungkin kembali EOF. EOFbiasanya didefinisikan sebagai -1atau nilai negatif lainnya, yang menyimpan dalam unsignedbukan apa yang Anda inginkan. Inilah deklarasi: extern int getchar();BTW, rekomendasi ini juga berasal dari buku "C: A Reference Manual".
Maxim Chetrusca
6
Satu referensi C yang saya percayai adalah ISO / IEC 9899: 2011 :-)
Jeff
3
@MaxChetrusca saran yang baik tetapi alasan yang buruk: bahkan pada charkasus yang ditandatangani , Anda harus menggunakan intuntuk menyimpan nilai pengembalian.
Antti Haapala

Jawaban:

204

Buku itu salah. Standar tidak menentukan apakah dataran charditandatangani atau tidak ditandatangani.

Bahkan, standar mendefinisikan tiga jenis yang berbeda: char, signed char, dan unsigned char. Jika Anda #include <limits.h>dan kemudian melihat CHAR_MIN, Anda dapat mengetahui apakah dataran charadalah signedatau unsigned(jika CHAR_MINkurang dari 0 atau sama dengan 0), tetapi bahkan kemudian, ketiga jenis berbeda sejauh standar yang bersangkutan.

Perhatikan bahwa charini istimewa dengan cara ini. Jika Anda mendeklarasikan variabel karena int100% setara dengan mendeklarasikannya sebagai signed int. Ini selalu berlaku untuk semua kompiler dan arsitektur.

Alok Singhal
sumber
1
@Lok: yang sama tidak benar untuk beberapa tipe data lainnya, misalnya intberarti signed intselalu, kan? Selain itu char, tipe data apa yang memiliki kebingungan yang sama C?
Lazer
8
@ eSKay: ya, charadalah satu-satunya jenis yang bisa ditandatangani atau tidak ditandatangani. intsetara dengan signed intmisalnya.
Alok Singhal
28
Ada alasan histeris, er, historis untuk ini - di awal kehidupan C "standar" terbalik dua kali, dan beberapa kompiler awal populer berakhir dengan satu cara dan lain-lain yang lain.
Hot Licks
9
@ AlokSinghal: Ini juga implementatin-defined apakah jenis bidang bit intditandatangani atau tidak.
Keith Thompson
@KeithThompson terima kasih atas koreksinya. Saya cenderung lupa beberapa detail tentang tipe bidang bit karena saya tidak banyak menggunakannya.
Alok Singhal
67

Seperti yang Alok tunjukkan , standar membiarkan implementasi.

Untuk gcc, standarnya sudah ditandatangani, tetapi Anda dapat memodifikasinya dengan -funsigned-char. Catatan: untuk gcc di Android NDK, defaultnya tidak ditandai . Anda juga dapat secara eksplisit meminta karakter yang ditandatangani dengan-fsigned-char .

Pada MSVC, defaultnya sudah ditandatangani tetapi Anda bisa memodifikasinya dengan /J.

R Samuel Klatchko
sumber
2
Menarik bahwa deskripsi Schildt tidak cocok dengan perilaku MSVC karena bukunya biasanya ditujukan untuk pengguna MSVC. Saya ingin tahu apakah MS mengubah default di beberapa titik?
Michael Burr
1
Saya pikir itu tidak tergantung pada kompiler, tetapi pada platform. Saya pikir char dibiarkan sebagai tipe ketiga dari "datatype karakter" agar sesuai dengan apa yang digunakan sistem saat itu sebagai karakter yang dapat dicetak.
Spidey
10
Dokumen GCC mengatakan itu bergantung pada mesin: " Setiap jenis mesin memiliki default untuk karakter apa yang seharusnya. Ini seperti char yang tidak ditandai secara default atau seperti char yang ditandatangani secara default. "
Deduplicator
1
Bisakah Anda memberikan sumber untuk catatan Anda bahwa di Android defaultnya adalah tanda unsigned?
phlipsy
1
@Spidey standar C tidak membuat perbedaan nyata antara kompiler, platform dan arsitektur CPU. Itu hanya benjolan mereka semua di bawah "implementasi".
plugwash
35

C99 N1256 konsep 6.2.5 / 15 "Jenis" memiliki ini untuk mengatakan tentang jenis char:

Implementasi harus mendefinisikan char untuk memiliki jangkauan, representasi, dan perilaku yang sama seperti char yang ditandatangani atau char yang tidak ditandatangani.

dan dalam catatan kaki:

CHAR_MIN, didefinisikan dalam <limits.h>, akan memiliki salah satu nilai 0atau SCHAR_MIN, dan ini dapat digunakan untuk membedakan dua opsi. Terlepas dari pilihan yang dibuat, charadalah jenis yang terpisah dari dua lainnya dan tidak kompatibel dengan keduanya.

Michael Burr
sumber
7

Menurut buku Bahasa Pemrograman C oleh Dennis Ritchie yang merupakan buku standar de-facto untuk ANSI C, karakter sederhana yang ditandatangani atau tidak ditandatangani bergantung pada mesin, tetapi karakter yang dapat dicetak selalu positif.

Ravi Rathi
sumber
9
Ini tidak selalu berarti bahwa karakter yang dapat dicetak selalu positif. Standar C menjamin bahwa semua anggota set karakter eksekusi dasar memiliki nilai non-negatif.
Keith Thompson
7

Menurut standar C, penandatanganan char biasa adalah "implementasi didefinisikan".

Secara umum implementor memilih mana yang lebih efisien untuk diimplementasikan pada arsitektur mereka. Pada sistem x86, char biasanya ditandatangani. Pada sistem lengan umumnya tidak ditandatangani (Apple iOS adalah pengecualian).

plugwash
sumber
2
@plugwash Jawaban Anda mungkin diturunkan karena Tim Post kehilangan kuncinya . Serius, Anda tidak perlu khawatir tentang satu downvote selama Anda yakin jawaban Anda benar (yang dalam hal ini). Itu terjadi pada saya beberapa kali agar postingan saya downvoted tanpa alasan yang sah. Jangan khawatir tentang itu, kadang-kadang orang hanya melakukan hal-hal aneh.
Donald Duck
1
Mengapa char yang ditandatangani lebih efisien di x86? Ada sumber?
martinkunev
2

Menurut "Bahasa Pemrograman C ++" oleh Bjarne Stroustrup, charadalah "implementasi yang ditentukan". Itu bisa signed charatau unsigned chartergantung pada implementasi. Anda dapat memeriksa apakah charditandatangani atau tidak dengan menggunakan std::numeric_limits<char>::is_signed.

BoQ
sumber
9
Ini adalah pertanyaan C. C ++ adalah bahasa yang berbeda, dan referensi C ++ tidak memiliki relevansi dengan C.
MM
1

Sekarang, kita tahu standar membiarkan implementasi.

Tetapi bagaimana cara memeriksa suatu tipe signedatau unsigned, sepertichar ?

Saya menulis makro untuk melakukan ini:

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

dan mengujinya dengan gcc, clang, dan cl. Tapi saya tidak yakin itu selalu aman untuk kasus lain.

南山 竹
sumber
Apa yang salah dengan CHAR_MIN biasa <0 (atau WCHAR_MIN <0 untuk wchar_t)?
Öö Tiib