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 per char van de CHAR_BIT wordt geleverd door de macro CHAR_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. */
C99
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
C99
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 .

C99

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.

C99
/* only two narrow or two wide string literals may be concatenated */
char* s = "Hello, " "World";
C99
/* 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";
C11
/* 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)

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 die void en terugkeert naar int ;
  • ptr : een pointer naar een int ;
  • fp : een pointer naar een functie die int en int terugkeert;
  • arr : een reeks met grootte 10 van een reeks met grootte 20 van int ;
  • 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];


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow