Rozmiar znaku („a”) w C / C ++

298

Jaka jest wielkość znaków w C i C ++? O ile mi wiadomo rozmiar char wynosi 1 bajt zarówno w C, jak i C ++.

W C:

#include <stdio.h>
int main()
{
    printf("Size of char : %d\n", sizeof(char));
    return 0;
}

W C ++:

#include <iostream>
int main()
{
    std::cout << "Size of char : " << sizeof(char) << "\n";
    return 0;
}

Żadnych niespodzianek, oba dają wynik: Size of char : 1

Teraz wiemy, że znaki są reprezentowane 'a', 'b', 'c', '|', ... Więc po prostu zmodyfikowany powyższe kody do nich:

W C:

#include <stdio.h>
int main()
{
    char a = 'a';
    printf("Size of char : %d\n", sizeof(a));
    printf("Size of char : %d\n", sizeof('a'));
    return 0;
}

Wynik:

Size of char : 1
Size of char : 4

W C ++:

#include <iostream>
int main()
{
    char a = 'a';
    std::cout << "Size of char : " << sizeof(a) << "\n";
    std::cout << "Size of char : " << sizeof('a') << "\n";
    return 0;
}

Wynik:

Size of char : 1
Size of char : 1

Dlaczego sizeof('a')zwraca różne wartości w C i C ++?

whacko__Cracko
źródło
8
"%|"Format wymaga intargumentu (lub coś, co promuje się int). sizeofdaje wynik typu size_t. Przekształć na intużycie rzutowania lub, jeśli twoja implementacja to obsługuje, użyj "%zu".
Keith Thompson,

Odpowiedzi:

348

W C, typ postaci stałej jak 'a'jest w rzeczywistości int, o rozmiarze 4 (lub inną wartość zależna od implementacji). W C ++ typ ma charrozmiar 1. Jest to jedna z wielu małych różnic między tymi dwoma językami.

Eric Postpischil
źródło
12
W standardzie C ++ jest to sekcja 2.13.2 / 1, w C 6.4.4.4, przynajmniej w dokumencie, który mam.
14
+1 (z wyjątkiem tego, że chociaż „rozmiar 4” oczywiście dotyczy platformy nthrgeek, niekoniecznie dotyczy wszystkich platform).
sbi
28
@nthrgeek: Jestem zbyt leniwy, aby zacytować oba standardy, ale standard C ++ zawiera dodatek poświęcony niezgodnościom z C. W dodatku C.1.1 wspomniano, że „Rodzaj literału znaku zmienia się z intna char, co wyjaśnia zachowanie. :)
jalf
3
@nthrgeek: §6.4.4.4, akapit 10: „Stała znakowa liczby całkowitej ma typ int. Wartość stałej znakowej liczby całkowitej zawierającej pojedynczy znak odwzorowany na jednobajtowy znak wykonania jest wartością liczbową reprezentacji odwzorowanego odwzorowania znak interpretowany jako liczba całkowita. ”
Stephen Canon
7
@nthrgeek: Nie powinieneś prosić o standardowe odniesienie, chyba że spierasz się o konkretny punkt i chcesz zrozumieć, dlaczego inna osoba ma inne zdanie. Jeśli wszyscy się zgadzają, po prostu to zaakceptuj. Ty (jako programista) powinieneś być dość inteligentny, aby szybko samemu znaleźć wspólną odpowiedź na to pytanie.
Martin York
26

Jak stwierdził Paul, to dlatego, że 'a'jest intw C, ale charw C ++.

Omawiam tę konkretną różnicę między C i C ++ w czymś, co napisałem kilka lat temu, pod adresem : http://david.tribble.com/text/cdiffs.htm

David R. Tribble
źródło
4
Ciekawe, ale czy pracujesz nad aktualizacją tego (bardzo szczegółowego) dokumentu, aby uwzględnić nowe zmiany w C ++ 11 i C11?
Adam Rosenfield,
Nie teraz. Moje zainteresowanie C i C ++ znacznie zmalało w ciągu ostatnich pięciu lat.
David R Tribble,
3
Użyłem twojej pracy, żeby to napisać i tutaj jesteś na SO. Taki mały świat!
17

W C typ literałów znakowych to int i char w C ++. Jest to w C ++ wymagane do obsługi przeładowania funkcji . Zobacz ten przykład:

void foo(char c)
{
    puts("char");
}
void foo(int i)
{
    puts("int");
}
int main()
{
    foo('i');
    return 0;
}

Wynik:

char
Kowal
źródło
5

W języku C dosłowność znaków nie jest chartypem. C uważa literał literowy za liczbę całkowitą. Tak więc nie ma różnicy między sizeof('a')i sizeof(1).

Wielkość literału znaków jest więc równa rozmiarowi liczby całkowitej w C.

W języku C ++ literał znaków jest rodzajem char. Cppreference Saya:

1) dosłowne wąski charakter lub zwykły charakter dosłowny, np 'a'albo '\n'albo '\13'. Taki literał ma typchar i wartość równą reprezentacji c-char w zestawie znaków wykonania. Jeśli c-char nie jest reprezentowalny jako pojedynczy bajt w zestawie znaków wykonania, literał ma typ int i wartość zdefiniowaną przez implementację.

Tak więc w języku C ++ literał jest rodzajem char. więc rozmiar literału znaków w C ++ to jeden bajt.

Alos, W swoich programach użyłeś niewłaściwego specyfikatora formatu dla sizeofoperatora.

C11 §7.21.6.1 (P9):

Jeśli specyfikacja konwersji jest nieprawidłowa, zachowanie jest niezdefiniowane.275) Jeśli jakikolwiek argument nie jest poprawnym typem dla odpowiedniej specyfikacji konwersji, zachowanie jest niezdefiniowane.

Tak więc powinieneś użyć %zuspecyfikatora formatu zamiast %d, w przeciwnym razie jest to niezdefiniowane zachowanie w C.

msc
źródło
%zunie jest obsługiwany na wielu platformach, ale lepsza przenośność, użycie (int)sizeof(char)i format%d
chqrlie,
Wartość literałów znakowych niekoniecznie odpowiada kodowi ASCII. Zależy to od zestawu znaków źródłowych i wykonawczych oraz od tego, czy chartyp jest domyślnie podpisany czy niepodpisany.
chqrlie,