Suche…


Bemerkungen

  • Während char 1 Byte lang sein muss, muss 1 Byte nicht 8 Bit sein (oft auch als Oktett bezeichnet ), obwohl die meisten modernen Computerplattformen es als 8 Bit definieren. Die Implementierung der Anzahl von Bits pro char wird durch die vorgesehenen CHAR_BIT Makro, definiert in <limits.h> . POSIX erfordert, dass 1 Byte aus 8 Bit besteht.
  • Typen mit fester Breite sollten nur spärlich verwendet werden. Die integrierten Typen von C sind so konzipiert, dass sie in jeder Architektur selbstverständlich sind. Die Typen mit fester Breite sollten nur verwendet werden, wenn Sie explizit eine ganzzahlige Größe benötigen (zum Beispiel für Netzwerke).

Integer-Typen und Konstanten

Signed Integer kann dieser Typen sein (der int nach short oder long ist optional):

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 */

Jeder dieser vorzeichenbehafteten Integer-Typen hat eine vorzeichenlose Version.

unsigned int i = 65535;
unsigned short = 2767;
unsigned char = 255;

Bei allen Typen außer char die signed Version angenommen, wenn der signed oder unsigned Teil ausgelassen wird. Der Typ char stellt einen dritten Zeichentyp dar, der sich von signed char und unsigned char und die Signiertheit (oder nicht) hängt von der Plattform ab.

Verschiedene Typen von Integer-Konstanten (im C-Jargon als Literale bezeichnet) können auf der Grundlage ihres Präfixes oder Suffixes mit unterschiedlichen Basen und unterschiedlicher Breite geschrieben werden.

/* 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) */

Dezimalkonstanten sind immer signed . Hexadezimale Konstanten beginnen mit 0x oder 0X und 0X beginnen nur mit einer 0 . Die beiden letzteren sind signed oder unsigned abhängig davon, ob der Wert in den signierten Typ passt oder nicht.

/* 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 */

Ohne Suffix hat die Konstante den ersten Typ, der zu ihrem Wert passt, d. INT_MAX Eine Dezimalkonstante, die größer ist als INT_MAX wenn möglich vom Typ long oder ansonsten long long .

Die Header-Datei <limits.h> beschreibt die Grenzen von Ganzzahlen wie folgt. Ihre implementierungsdefinierten Werte müssen gleich oder größer sein als die unten gezeigten, mit demselben Vorzeichen.

Makro Art Wert
CHAR_BIT kleinstes Objekt, das kein Bitfeld (Byte) ist 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 siehe unten
CHAR_MAX char siehe unten
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
Makro Art Wert
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

Wenn der Wert von einem Objekt vom Typ char Zeichen erstreckt , wenn in einem Ausdruck verwendet, der Wert von CHAR_MIN soll das gleiche sein wie die der SCHAR_MIN und der Wert von CHAR_MAX ist die gleich wie das sein SCHAR_MAX . Wenn der Wert eines Objekt vom Typ char nicht Vorzeichen erweitern , wenn in einem Ausdruck verwendet, der Wert von CHAR_MIN sein soll 0 und der Wert von CHAR_MAX ist die gleich wie das sein UCHAR_MAX .

C99

Der C99-Standard fügte einen neuen Header <stdint.h> , der Definitionen für Ganzzahlen mit fester Breite enthält. Eine ausführlichere Erklärung finden Sie im Beispiel für die Ganzzahl mit fester Breite.

String Literals

Ein String-Literal in C ist eine Folge von Zeichen, die durch eine Literal-Null abgeschlossen wird.

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' */

String-Literale sind nicht modifizierbar (und können tatsächlich in einen Nur-Lese-Speicher gestellt werden, z. B. .rodata). Der Versuch, ihre Werte zu ändern, führt zu undefiniertem Verhalten.

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! */

Mehrere String-Literale werden zur Kompilierzeit verkettet, sodass Sie Konstrukte wie diese schreiben können.

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 */

Zeichenkettenliterale unterstützen wie Zeichenkonstanten verschiedene Zeichensätze.

/* 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";

Integer-Typen mit fester Breite (seit C99)

C99

Der Header <stdint.h> enthält mehrere Integer-Typdefinitionen mit fester Breite. Diese Typen sind optional und werden nur bereitgestellt, wenn die Plattform über einen ganzzahligen Typ mit der entsprechenden Breite verfügt und der entsprechende vorzeichenbehaftete Typ eine Zweierkomplement-Darstellung mit negativen Werten hat.

In den Anmerkungen finden Sie Verwendungshinweise für Typen mit fester Breite.

/* 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 */

Fließkommakonstanten

Die C-Sprache hat drei obligatorische reelle Fließkommatypen: float , double und 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 */

Der Header <float.h> definiert verschiedene Grenzwerte für Gleitkommaoperationen.

Gleitkomma-Arithmetik ist implementierungsdefiniert. Die meisten modernen Plattformen (Arm, x86, x86_64, MIPS) verwenden jedoch Fließkommaoperationen nach IEEE 754 .

C verfügt außerdem über drei optionale komplexe Fließkommatypen, die von den oben genannten abgeleitet werden.

Erklärungen interpretieren

Eine charakteristische syntaktische Besonderheit von C besteht darin, dass Deklarationen die Verwendung des deklarierten Objekts wie in einem normalen Ausdruck widerspiegeln.

Die folgenden Operatoren mit identischer Priorität und Assoziativität werden in Deklaratoren wiederverwendet, nämlich:

  • der unäre * "Dereferenzierungs" -Operator, der einen Zeiger bezeichnet;
  • der binäre [] "Array Subscription" -Operator, der ein Array bezeichnet;
  • der (1 + n) -ary () "Funktionsaufruf" -Operator, der eine Funktion bezeichnet;
  • die () Gruppierung Klammern, die den Vorrang und die Assoziativität der übrigen aufgelisteten Operatoren überschreiben.

Die obigen drei Operatoren haben die folgende Priorität und Assoziativität:

Operator Relativer Vorrang Assoziativität
[] (Array-Abonnement) 1 Links nach rechts
() (Funktionsaufruf) 1 Links nach rechts
* (Dereferenzierung) 2 Rechts nach links

Bei der Interpretation von Deklarationen muss man vom Bezeichner nach außen gehen und die benachbarten Operatoren in der richtigen Reihenfolge gemäß der obigen Tabelle anwenden. Jede Anwendung eines Operators kann durch die folgenden englischen Wörter ersetzt werden:

Ausdruck Deutung
thing[X] ein Array von Größe X von ...
thing(t1, t2, t3) eine Funktion, die t1 , t2 , t3 und zurückgibt ...
*thing ein Zeiger auf ...

Daraus folgt, dass der Beginn der englischen Interpretation immer mit dem Bezeichner beginnt und mit dem Typ endet, der auf der linken Seite der Deklaration steht.

Beispiele

char *names[20];

[] hat Vorrang vor * , die Interpretation lautet also: names ist ein Array der Größe 20 eines Zeigers auf char .

char (*place)[10];

Im Falle der Verwendung von Klammern zum Überschreiben der Rangfolge wird das * zuerst angewendet: place ist ein Zeiger auf ein Array der Größe 10 von char .

int fn(long, short);

Es gibt keinen Vorrang, über den Sie sich Gedanken machen müssen: fn ist eine Funktion, die long , short und int .

int *fn(void);

() Wird zuerst angewendet: fn ist eine Funktion, die void und einen Zeiger auf int .

int (*fp)(void);

Überschreiben der Priorität von () : fp ist ein Zeiger auf eine Funktion, die void und int .

int arr[5][8];

Mehrdimensionale Arrays bilden keine Ausnahme von der Regel. Die Operatoren [] werden in der Reihenfolge von links nach rechts entsprechend der Assoziativität in der Tabelle angewendet: arr ist ein Array der Größe 5 eines Arrays der Größe 8 von int .

int **ptr;

Die beiden Dereferenzierungsoperatoren haben gleiche Priorität, sodass die Assoziativität wirksam wird. Die Operatoren werden in einer Reihenfolge von rechts nach links angewendet: ptr ist ein Zeiger auf einen Zeiger auf ein int .

Mehrere Erklärungen

Das Komma kann als Trennzeichen verwendet werden (* nicht * wie der Komma-Operator), um mehrere Deklarationen innerhalb einer einzelnen Anweisung zu begrenzen. Die folgende Anweisung enthält fünf Deklarationen:
int fn(void), *ptr, (*fp)(int), arr[10][20], num;

Die deklarierten Objekte im obigen Beispiel sind:

  • fn : eine Funktion, die void und int ;
  • ptr : ein Zeiger auf ein int ;
  • fp : ein Zeiger auf eine Funktion, die int und int ;
  • arr : ein Array der Größe 10 eines Arrays der Größe 20 von int ;
  • num : int .

Alternative Interpretation

Da Deklarationen gespiegelt werden, kann eine Deklaration auch in Bezug auf die Operatoren, die auf das Objekt angewendet werden könnten, und den endgültigen resultierenden Typ dieses Ausdrucks interpretiert werden. Der Typ, der auf der linken Seite steht, ist das Endergebnis, das sich nach Anwendung aller Operatoren ergibt.

/*
 * 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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow