C Language
Gegevenstypen
Zoeken…
Opmerkingen
- Hoewel
char
1 byte moet zijn, hoeft 1 byte niet 8 bits te zijn (vaak ook een octet genoemd ), hoewel de meeste moderne computerplatforms het als 8 bits definiëren. Het aantal bits perchar
van deCHAR_BIT
wordt geleverd door de macroCHAR_BIT
, gedefinieerd in<limits.h>
.<limits.h>
. POSIX vereist 1 byte om 8 bits te zijn. - Typen met een vaste breedte moeten spaarzaam worden gebruikt, de ingebouwde typen van C zijn ontworpen om op elke architectuur natuurlijk te zijn, de typen met een vaste breedte mogen alleen worden gebruikt als u expliciet een specifiek formaat van een geheel getal nodig hebt (bijvoorbeeld voor netwerken).
Geheel getaltypen en constanten
Ondertekende gehele getallen kunnen van deze typen zijn (de int
na short
of long
is optioneel):
signed char c = 127; /* required to be 1 byte, see remarks for further information. */
signed short int si = 32767; /* required to be at least 16 bits. */
signed int i = 32767; /* required to be at least 16 bits */
signed long int li = 2147483647; /* required to be at least 32 bits. */
signed long long int li = 2147483647; /* required to be at least 64 bits */
Elk van deze ondertekende integertypen heeft een niet-ondertekende versie.
unsigned int i = 65535;
unsigned short = 2767;
unsigned char = 255;
Voor alle typen behalve char
de signed
versie aangenomen als het signed
of unsigned
deel wordt weggelaten. Het type char
vormt een derde karaktertype, anders dan het signed char
en het unsigned char
en de ondertekening hangt af van het platform.
Verschillende typen gehele getallen ( letterlijk genoemd in C-jargon) kunnen in verschillende bases en verschillende breedtes worden geschreven, op basis van hun voor- of achtervoegsel.
/* the following variables are initialized to the same value: */
int d = 42; /* decimal constant (base10) */
int o = 052; /* octal constant (base8) */
int x = 0xaf; /* hexadecimal constants (base16) */
int X = 0XAf; /* (letters 'a' through 'f' (case insensitive) represent 10 through 15) */
Decimale constanten worden altijd signed
. Hexadecimale constanten beginnen met 0x
of 0X
en octale constanten beginnen gewoon met een 0
. De laatste twee zijn signed
of unsigned
naargelang de waarde past in de getekende type of niet.
/* suffixes to describe width and signedness : */
long int i = 0x32; /* no suffix represent int, or long int */
unsigned int ui = 65535u; /* u or U represent unsigned int, or long int */
long int li = 65536l; /* l or L represent long int */
Zonder een achtervoegsel heeft de constante het eerste type dat bij zijn waarde past, dat is een decimale constante die groter is dan INT_MAX
van het type long
indien mogelijk, of anders long long
.
Het header-bestand <limits.h>
beschrijft de limieten van gehele getallen als volgt. Hun door de implementatie gedefinieerde waarden moeten gelijk of groter (absolute waarde) zijn aan die hieronder, met hetzelfde teken.
macro | Type | Waarde |
---|---|---|
CHAR_BIT | kleinste object dat geen bitveld is (byte) | 8 |
SCHAR_MIN | signed char | -127 / - (2 7 - 1) |
SCHAR_MAX | signed char | +127 / 2 7 - 1 |
UCHAR_MAX | unsigned char | 255/2 8 - 1 |
CHAR_MIN | char | zie hieronder |
CHAR_MAX | char | zie hieronder |
SHRT_MIN | short int | -32767 / - (2 15 - 1) |
SHRT_MAX | short int | +32767 / 2 15 - 1 |
USHRT_MAX | unsigned short int | 65535/2 16 - 1 |
INT_MIN | int | -32767 / - (2 15 - 1) |
INT_MAX | int | +32767 / 2 15 - 1 |
UINT_MAX | unsigned int | 65535/2 16 - 1 |
LONG_MIN | long int | -2147483647 / - (2 31 - 1) |
LONG_MAX | long int | +2147483647 / 2 31 - 1 |
ULONG_MAX | unsigned long int | 4294967295/2 32 - 1 |
macro | Type | Waarde |
---|---|---|
LLONG_MIN | long long int | -9223372036854775807 / - (2 63 - 1) |
LLONG_MAX | long long int | +9223372036854775807 / 2 63 - 1 |
ULLONG_MAX | unsigned long long int | 18446744073709551615/2 64 - 1 |
Als de waarde van een object van het type char
sign-uitbreiding bij gebruik in een expressie, is de waarde van CHAR_MIN
dezelfde als die van SCHAR_MIN
en is de waarde van CHAR_MAX
dezelfde als die van SCHAR_MAX
. Als de waarde van een object van het type char
niet wordt verlengd als deze in een expressie wordt gebruikt, moet de waarde van CHAR_MIN
0 zijn en moet de waarde van CHAR_MAX
dezelfde zijn als die van UCHAR_MAX
.
De C99-standaard heeft een nieuwe koptekst toegevoegd, <stdint.h>
, die definities voor gehele getallen met vaste breedte bevat. Zie het voorbeeld van een geheel getal met vaste breedte voor een meer diepgaande uitleg.
String Literals
Een tekenreeks letterlijk in C is een reeks tekens, afgesloten door een letterlijke nul.
char* str = "hello, world"; /* string literal */
/* string literals can be used to initialize arrays */
char a1[] = "abc"; /* a1 is char[4] holding {'a','b','c','\0'} */
char a2[4] = "abc"; /* same as a1 */
char a3[3] = "abc"; /* a1 is char[3] holding {'a','b','c'}, missing the '\0' */
Stringliteralen kunnen niet worden gewijzigd (en kunnen zelfs in alleen-lezen geheugen worden geplaatst, zoals .rodata). Als u probeert hun waarden te wijzigen, leidt dit tot ongedefinieerd gedrag.
char* s = "foobar";
s[0] = 'F'; /* undefined behaviour */
/* it's good practice to denote string literals as such, by using `const` */
char const* s1 = "foobar";
s1[0] = 'F'; /* compiler error! */
Tijdens het compileren worden meerdere stringliteralen aaneengeschakeld, wat betekent dat u een constructie als deze kunt schrijven.
/* only two narrow or two wide string literals may be concatenated */
char* s = "Hello, " "World";
/* since C99, more than two can be concatenated */
/* concatenation is implementation defined */
char* s1 = "Hello" ", " "World";
/* common usages are concatenations of format strings */
char* fmt = "%" PRId16; /* PRId16 macro since C99 */
Tekenreeksliteralen, hetzelfde als tekenconstanten, ondersteunen verschillende tekensets.
/* normal string literal, of type char[] */
char* s1 = "abc";
/* wide character string literal, of type wchar_t[] */
wchar_t* s2 = L"abc";
/* UTF-8 string literal, of type char[] */
char* s3 = u8"abc";
/* 16-bit wide string literal, of type char16_t[] */
char16_t* s4 = u"abc";
/* 32-bit wide string literal, of type char32_t[] */
char32_t* s5 = U"abc";
Vaste getallen met gehele breedte (sinds C99)
De kop <stdint.h>
biedt verschillende definities van het type integer type met vaste breedte. Deze typen zijn optioneel en worden alleen verstrekt als het platform een geheel getal van de overeenkomstige breedte heeft en als het overeenkomstige ondertekende type een tweevoudige complementrepresentatie van negatieve waarden heeft.
Zie het gedeelte met opmerkingen voor gebruikstips van typen met vaste breedte.
/* commonly used types include */
uint32_t u32 = 32; /* exactly 32-bits wide */
uint8_t u8 = 255; /* exactly 8-bits wide */
int64_t i64 = -65 /* exactly 64 bit in two's complement representation */
Zwevende puntconstanten
De C-taal heeft drie verplichte echte drijvende-kommatypes, float
, double
en long double
.
float f = 0.314f; /* suffix f or F denotes type float */
double d = 0.314; /* no suffix denotes double */
long double ld = 0.314l; /* suffix l or L denotes long double */
/* the different parts of a floating point definition are optional */
double x = 1.; /* valid, fractional part is optional */
double y = .1; /* valid, whole-number part is optional */
/* they can also defined in scientific notation */
double sd = 1.2e3; /* decimal fraction 1.2 is scaled by 10^3, that is 1200.0 */
De kop <float.h>
definieert verschillende limieten voor drijvende-kommabewerkingen.
Rekenpunt drijvende komma is implementatie gedefinieerd. De meeste moderne platforms (arm, x86, x86_64, MIPS) gebruiken echter IEEE 754 floating point-bewerkingen.
C heeft ook drie optionele complexe drijvende komma types die zijn afgeleid van het bovenstaande.
Verklaringen interpreteren
Een onderscheidende syntactische eigenaardigheid van C is dat verklaringen het gebruik van het aangegeven object weerspiegelen zoals het in een normale uitdrukking zou zijn.
De volgende reeks operators met identieke voorrang en associativiteit wordt hergebruikt in declarators, namelijk:
- de unaire
*
"dereference" -operator die een wijzer aangeeft; - de binaire
[]
"array-abonnement" -operator die een array aangeeft; - de (1 + n) -ary
()
"functieaanroep" -operator die een functie aangeeft; - de
()
groepering van haakjes die de prioriteit en associativiteit van de rest van de vermelde operatoren opheffen.
De bovenstaande drie operatoren hebben de volgende prioriteit en associativiteit:
operator | Relatieve voorrang | associativiteit |
---|---|---|
[] (array-abonnement) | 1 | Van links naar rechts |
() (functieaanroep) | 1 | Van links naar rechts |
* (dereferentie) | 2 | Rechts naar links |
Bij het interpreteren van aangiften moet men uitgaan van de identifier naar buiten en de aangrenzende operatoren in de juiste volgorde volgens bovenstaande tabel toepassen. Elke toepassing van een operator kan worden vervangen door de volgende Engelse woorden:
Uitdrukking | Interpretatie |
---|---|
thing[X] | een reeks van maat X van ... |
thing(t1, t2, t3) | een functie die t1 , t2 , t3 en terugkeert ... |
*thing | een aanwijzer naar ... |
Hieruit volgt dat het begin van de Engelse interpretatie altijd begint met het ID en eindigt met het type dat aan de linkerkant van de verklaring staat.
Voorbeelden
char *names[20];
[]
heeft voorrang op *
, dus de interpretatie is: names
is een array van grootte 20 van een pointer naar char
.
char (*place)[10];
In het geval dat haakjes worden gebruikt om de prioriteit te overschrijven, wordt de *
eerst toegepast: place
is een wijzer naar een reeks van grootte 10 van char
.
int fn(long, short);
Er is hier geen prioriteit om je zorgen over te maken: fn
is een functie die long
, short
en terugkerend int
.
int *fn(void);
De ()
wordt eerst toegepast: fn
is een functie die void
en een pointer terugzet naar int
.
int (*fp)(void);
De prioriteit van ()
fp
: fp
is een pointer naar een functie die void
en int
.
int arr[5][8];
Multidimensionale arrays zijn geen uitzondering op de regel; de []
operatoren worden in de volgorde van links naar rechts toegepast volgens de associativiteit in de tabel: arr
is een array van grootte 5 van een array van grootte 8 van int
.
int **ptr;
De twee dereferentie-operators hebben dezelfde prioriteit, dus de associativiteit wordt van kracht. De operatoren worden in de volgorde van rechts naar links toegepast: ptr
is een pointer naar een pointer naar een int
.
Meerdere verklaringen
De komma kan worden gebruikt als een scheidingsteken (* niet * dat werkt als de komma-operator) om meerdere aangiften binnen een enkele instructie af te bakenen. De volgende verklaring bevat vijf verklaringen:int fn(void), *ptr, (*fp)(int), arr[10][20], num;
De aangegeven objecten in het bovenstaande voorbeeld zijn:
-
fn
: een functie dievoid
en terugkeert naarint
; -
ptr
: een pointer naar eenint
; -
fp
: een pointer naar een functie dieint
enint
terugkeert; -
arr
: een reeks met grootte 10 van een reeks met grootte 20 vanint
; -
num
:int
.
Alternatieve interpretatie
Omdat verklaringen het gebruik weerspiegelen, kan een verklaring ook worden geïnterpreteerd in termen van de operatoren die kunnen worden toegepast op het object en het uiteindelijke resulterende type van die uitdrukking. Het type dat aan de linkerkant staat, is het uiteindelijke resultaat dat wordt verkregen na het toepassen van alle operators.
/*
* Subscripting "arr" and dereferencing it yields a "char" result.
* Particularly: *arr[5] is of type "char".
*/
char *arr[20];
/*
* Calling "fn" yields an "int" result.
* Particularly: fn('b') is of type "int".
*/
int fn(char);
/*
* Dereferencing "fp" and then calling it yields an "int" result.
* Particularly: (*fp)() is of type "int".
*/
int (*fp)(void);
/*
* Subscripting "strings" twice and dereferencing it yields a "char" result.
* Particularly: *strings[5][15] is of type "char"
*/
char *strings[10][20];