This article has multiple issues. Please helpimprove it or discuss these issues on thetalk page.(Learn how and when to remove these messages) (Learn how and when to remove this message)
|

C syntax is theform that text must have in order to beC programming languagecode. The language syntax rules are designed to allow for code that is terse, has a close relationship with the resultingobject code, and yet provides relatively high-leveldata abstraction. C was the first widely successful high-level language for portableoperating-system development.C syntax makes use of themaximal munch principle.As afree-form language, C code can beformatted different ways without affecting its syntactic nature. C syntax influenced the syntax of succeeding languages, includingC++,Java, andC#.
C code consists ofpreprocessordirectives, and core-languagetypes,variables andfunctions; organized as one or more source files. Building the code typically involves preprocessing and thencompiling each source file into anobject file. Then, the object files arelinked to create anexecutable image.
Variables and functions can be declared separately from their definition. Adeclaration identifies the name of a user-defined element and some if not all of the information about how the element can be used at run-time. Adefinition is a complete description of an element that includes the declaration aspect as well as additional information that completes the element. For example, a function declaration indicates the name and optionally the type and number of arguments that it accepts. A function definition includes the same information (argument information is not optional), plus code that implements the function logic.

For ahosted environment, a program starts at anentry point function namedmain. The function is passed two arguments although an implementation of the function can ignore them. The function must be declared per one of the following prototypes (parameter names shown are typical but can be anything):
intmain();intmain(void);intmain(intargc,char*argv[]);intmain(intargc,char**argv);
The first two definitions are equivalent; meaning that the function does not use the two arguments. The second two are also equivalent; allowing the function to access the two arguments.
The return value, typed asint, serves as a status indicator to the host environment. Defined in<stdlib.h>, the standard library provides macros for standard status values:EXIT_SUCCESS andEXIT_FAILURE. Regardless, a program can indicate status using any values. For example, thekill command returns the numerical value of the signal plus 128.
A minimal program consists of a parameterless, emptymain function, like:
intmain(){}
Unlike other functions, the language[a] requires that a program act as if it returns 0 even if it does not end with areturn statement.[1]
In afree-standing (non-hosted) environment, such as a system without anoperating system, the standard allows for different startup handling. It need not require amain function.
Arguments included in thecommand line to start a program are passed to a program as two values – the number of arguments (customarily namedargc) and an array ofnull-terminated strings (customarily namedargv) with the program name as the first item.
The following code prints the value of the command-line parameters.
#include<stdio.h>intmain(intargc,char*argv[]){printf("argc\t= %d\n",argc);for(inti=0;i<argc;++i){printf("argv[%i]\t= %s\n",i,argv[i]);}}
$./a.outabcdefargc = 3argv[0] = ./a.outargv[1] = abcargv[2] = def
The following words arereserved – not allowed as identifiers, of which there are 43.
alignasalignofautoboolbreakcasecharconstconstexprcontinuedefaultdodoubleelseenumexternfloatforgotoifinlineintlongregisterrestrictreturnshortsignedsizeofstaticstatic_assertstructswitchthread_localtypedeftypeoftypeof_unqualunionunsignedvoidvolatilewhileThe following keywords are often substituted for a macro or an appropriate keyword from the above list, of which there are 14. Some of the following keywords are deprecated since C23.
_Alignas (deprecated)_Alignof (deprecated)_Atomic_BitInt_Bool (deprecated)_Complex_Countof_Decimal32_Decimal64_Decimal128_Generic_Noreturn (deprecated)_Static_assert (deprecated)_Thread_local (deprecated)The keyword_Imaginary was removed inC2Y.
The following words refer to literal values used by the language, of which there are 2.
nullptrtruefalseImplementations may reserve other keywords, although implementations typically provide non-standard keywords that begin with one or two underscores. The following keywords are classified as extensions and conditionally-supported, of which there are 2.
The following are directives to thepreprocessor, of which there are 19.
#if#elif#else#endif#ifdef#ifndef#elifdef#elifndef#define#undef#include#embed#line#error#warning#pragma#__has_include#__has_embed#__has_c_attributeThe_Pragma operator provides an alternative syntax for the functionality provided by#pragma.
Acomment – informative text to a programmer that is ignored by a language translator – can be included in code either as the line or block comment syntax. A line comment starts with// and ends at the end of the same line. A block comment starts with/* and ends with*/ – spanning any number of lines (or just one).
In some situations, comment markers are ignored. The text of a string literal is exempt from being considered a comment start. And, comments cannot be nested. For example,/* in a line comment is not as treated as the start of a block comment. And,// in a block comment is not treated as the start of a line comment.
The line comment syntax, sometimes calledC++ style originated inBCPL and became valid syntax inC99. It is not available in the original K&R version nor inANSI C.
The following code demonstrates comments. Line 1 contains a line comment and lines 3-4 contain a block comment. Line 4 demonstrates that a block comment can be embedded in a line with code both before and after it.
inti;// line comment/* block comment */intii=/* always zero */0;
The following demonstrates a potential problem with the comment syntax. What is intended to be the divide operator/ and then the dereference operator*, is evaluated as the start of a block comment.
x=*p/*q;
The following text is not valid C syntax since comments do not nest. It seems that lines 3-5 are a comment nested inside the comment block spanning lines 1-7. But, actually line 5 ends the comment started on line 1. This leaves line 6 to be interpreted as code which is clearly not valid C syntax.
/*First of comment block/*First line of what is intended to be an inner block*/Compilertreatsthislineascodebutit'snotvalid!*/
The syntax supports user-defined identifiers. An identifier must start with a letter (A-Z, a-z) or an underscore (_), subsequent characters can be letters, numbers (0-9), or underscores and it mustnot be a reserved word. Identifiers are case sensitive; makingfoo,FOO, andFoo distinct.
There can be multiple ways to evaluate an expression consistent with the mathematical notation. For example,(1+1)+(3+3) may be evaluated in the order(1+1)+(3+3),(2)+(3+3),(2)+(6),(8), or in the order(1+1)+(3+3),(1+1)+(6),(2)+(6),(8).
To reduce run-time issues with evaluation order yet afford some optimizations, the standard states that expressions may be evaluated in any order betweensequence points which are defined as any of the following:
&&, which can be readand then) and logicalor (||, which can be reador else)?:): This operator evaluates its first sub-expression first, and then its second or third (never both of them) based on the value of the firstExpressions before a sequence point are always evaluated before those after a sequence point. In the case of short-circuit evaluation, the second expression may not be evaluated depending on the result of the first expression. For example, in the expression(a() || b()), if the first argument evaluates to nonzero (true), the result of the entire expression cannot be anything else than true, sob() is not evaluated. Similarly, in the expression(a()&&b()), if the first argument evaluates to zero (false), the result of the entire expression cannot be anything else than false, sob() is not evaluated.
The arguments to a function call may be evaluated in any order, as long as they are all evaluated by the time the function is entered. The following expression, for example, has undefined behavior:
printf("%s %s\n",argv[i=0],argv[++i]);
Code is included from other files by using the#include directive, which textually copies the contents of the file in-place. Traditionally, C code is divided between a header file (with extension.h) and a source file (with extension.c). The header contains the declarations of symbols, while the source file contains the full implementation. This separation is enforced to prevent the compiler from recompiling the same source code repeatedly every time a library is included, causing bloat to compile times. Headers and separatetranslation units have no sense ofnamespaces, meaning all symbol names are global and will clash if the same name for multiple objects exist in the same translation unit.
To prevent a header from being included into a file more than once,#include guards or#pragma once can be used.
C headers can be compiled intoprecompiled headers which are faster to process by the compiler. Typically, libraries that infrequently change (such as C standard library headers) could be precompiled for faster compilation in a project.
To distinguish between searching in a include directory and searching a relative path, use angle brackets for include directories and quotation marks for relative paths.
#pragma once// standard library includes#include<stdio.h>#include<stdlib.h>// local#include"Personalities.h"#include"Math/SpecialFunctions.h"// external libraries#include<sqlite3.h>
Clang offers a non-standard feature, calledmodules, which are similar toC++ modules but different semantically. Both are used to increase compile time by compiling a translation unit once.
The#embed directive can be used to embed binary content into a file, even if it is not valid C code.
constunsignedchariconDisplayData[]={#embed "art.png"};// specify any type which can be initialized form integer constant expressions will doconstcharresetBlob[]={#embed "data.bin"};// attributes work just as wellalignas(8)constsignedcharalignedDataString[]={#embed "attributes.xml"};intmain(){return#embed </dev/urandom> limit(1);}
The language supports primitive numeric types forinteger andreal values which typically map directly to theinstruction set architecture of acentral processing unit (CPU). Integer data types store values in a subset ofintegers, and real data types store values in a subset ofreal numbers infloating-point. Acomplex data type stores two real values.
Integer types havesigned andunsigned variants. If neither is specified,signed is assumed, in most circumstances. However, for historic reasons,char is a type distinct from bothsigned char andunsigned char. It may be signed or unsigned, depending on the compiler and the character set (the standard requires that members of the basic character set have positive values). Also,bit field types specified asint may be signed or unsigned, depending on the compiler.
The integer types come in different fixed sizes, capable of representing various ranges of numbers. The typechar occupies exactly onebyte (the smallest addressable storage unit), which is typically 8 bits wide. (Althoughchar can represent any "basic" character, a wider type may be required for international character sets.) Most integer types have bothsigned and unsigned varieties, designated by thesigned andunsigned keywords. Signed integer types always use thetwo's complementrepresentation, sinceC23[2] (and in practice before; in versions before C23 the representation might alternatively have beenones' complement, orsign-and-magnitude, but in practice that has not been the case for decades on modern hardware). In many cases, there are multiple equivalent ways to designate the type; for example,signed short int andshort are synonymous.
The representation of some types may include unused "padding" bits, which occupy storage but are not included in the width. The following table lists the integer types using the shortest possible name and indicating the minimum width in bits.
| Name | Minimum width (bits) |
|---|---|
bool[citation needed] | 1 |
char | 8 |
signed char | 8 |
unsigned char | 8 |
short | 16 |
unsigned short | 16 |
int | 16 |
unsigned int | 16 |
long | 32 |
unsigned long | 32 |
long long[note 1] | 64 |
unsigned long long[note 1] | 64 |
Thechar type is distinct from bothsigned char andunsigned char, but is guaranteed to have the same representation as one of them. The_Bool andlong long types are standardized since 1999, and may not be supported by older compilers. Type_Bool is usually accessed via thetypedef namebool defined by the standard header<stdbool.h>, however since C23 the_Bool type has been renamedbool, and<stdbool.h> has been deprecated.
In general, the widths and representation scheme implemented for any given platform are chosen based on the machine architecture, with some consideration given to the ease of importing source code developed for other platforms. The width of theint type varies especially between translators; often corresponds to the most "natural" word size for a platform. The standard header<limits.h> defines macros for the minimum and maximum representable values of the standard integer types as implemented on any specific platform.
In addition to the standard integer types, there may be other "extended" integer types, which can be used fortypedefs in standard headers. For more precise specification of width, programmers can and should usetypedefs from the standard header<stdint.h>.
Integer constants may be specified in source code in several ways. Numeric values can be specified asdecimal (example:1022),octal with zero (0) as a prefix (01776), orhexadecimal with0x (zero x) as a prefix (0x3FE). A character in single quotes (example:'R'), called a "character constant," represents the value of that character in the execution character set, with typeint. Except for character constants, the type of an integer constant is determined by the width required to represent the specified value, but is always at least as wide asint. This can be overridden by appending an explicit length and/or signedness modifier; for example,12lu has typeunsigned long. There are no negative integer constants, but the same effect can often be obtained by using a unary negation operator "-".
Theenumerated type, specified with theenum keyword, and often just called an "enum" (usually pronounced/ˈiːnʌm/EE-num or/ˈiːnuːm/EE-noom), is a type designed to represent values across a series of named constants. Each of the enumerated constants has typeint. Eachenum type itself is compatible withchar or a signed or unsigned integer type, but each implementation defines its own rules for choosing a type.
Some compilers warn if an object with enumerated type is assigned a value that is not one of its constants. However, such an object can be assigned any values in the range of their compatible type, andenum constants can be used anywhere an integer is expected. For this reason,enum values are often used in place of preprocessor#define directives to create named constants. Such constants are generally safer to use than macros, since they reside within a specific identifier namespace.
An enumerated type is declared with theenum specifier and an optional name (ortag) for the enum, followed by a list of one or more constants contained within curly braces and separated by commas, and an optional list of variable names. Subsequent references to a specific enumerated type use theenum keyword and the name of the enum. By default, the first constant in an enumeration is assigned the value zero, and each subsequent value is incremented by one over the previous constant. Specific values may also be assigned to constants in the declaration, and any subsequent constants without specific values will be given incremented values from that point onward.For example, consider the following declaration:
enumColor{RED,GREEN,BLUE=5,YELLOW}paint_color;
This declares theenum Color type; theint constantsRED (whose value is 0),GREEN (whose value is one greater thanRED, 1),BLUE (whose value is the given value, 5), andYELLOW (whose value is one greater thanBLUE, 6); and theenum Color variablepaint_color. The constants may be used outside of the context of theenum (where any integer value is allowed), and values other than the constants may be assigned topaint_color, or any other variable of typeenum Color.
Unlike C++, C enums are not scoped, as C has no concept of namespacing. In C,enums can be implicitly converted to numeric types, which is type-unsafe.
typedefenumColor{RED,ORANGE,YELLOW,GREEN,BLUE,INDIGO,VIOLET}Color;Colorc=RED;// in CColord=Color::RED;// in C++, but not in C
Since C23, it is possible to manually specify the underlying type for theenum, like in C++.
enumCardSuit:char{HEARTS,CLUBS,SPADES,DIAMONDS};
A floating-point form is used to represent numbers with a fractional component. They do not, however, represent most rational numbers exactly; they are instead a close approximation. There are three standard types of real values, denoted by their specifiers (and sinceC23 three more decimal types): single precision (float), double precision (double), and double extended precision (long double). Each of these may represent values in a different form, often one of theIEEE floating-point formats.
| Type specifiers | Precision (decimal digits) | Exponent range | ||
|---|---|---|---|---|
| Minimum | IEEE 754 | Minimum | IEEE 754 | |
float | 6 | 7.2 (24 bits) | ±37 | ±38 (8 bits) |
double | 10 | 15.9 (53 bits) | ±37 | ±307 (11 bits) |
long double | 10 | 34.0 (113 bits) | ±37 | ±4931 (15 bits) |
Floating-point constants may be written indecimal notation, e.g.1.23.Decimal scientific notation may be used by addinge orE followed by a decimal exponent, also known asE notation, e.g.1.23e2 (which has the value 1.23 × 102 = 123.0). Either a decimal point or an exponent is required (otherwise, the number is parsed as an integer constant).Hexadecimal floating-point constants follow similar rules, except that they must be prefixed by0x and usep orP to specify a binary exponent, e.g.0xAp-2 (which has the value 2.5, since Ah × 2−2 = 10 × 2−2 = 10 ÷ 4). Both decimal and hexadecimal floating-point constants may be suffixed byf orF to indicate a constant of typefloat, byl (letterl) orL to indicate typelong double, or left unsuffixed for adouble constant.
The standard header file<float.h> defines the minimum and maximum values of the implementation's floating-point typesfloat,double, andlong double. It also defines other limits that are relevant to the processing of floating-point numbers.
C23 introduces three additionaldecimal (as opposed to binary) real floating-point types: _Decimal32, _Decimal64, and _Decimal128.
Despite that, the radix has historically been binary (base 2), meaning numbers like 1/2 or 1/4 are exact, but not 1/10, 1/100 or 1/3. With decimal floating point all the same numbers are exact plus numbers like 1/10 and 1/100, but still not e.g. 1/3. No known implementation does opt into the decimal radix for the previously known to be binary types. Since most computers do not even have the hardware for the decimal types, and those few that do (e.g. IBM mainframes sinceIBM System z10), can use the explicitly decimal types.
The following table describes the specifiers that define various storage attributes including duration – static (default for global), automatic (default for local), or dynamic (allocated).[citation needed]
| Specifier | Lifetime | Scope | Default initializer |
|---|---|---|---|
auto | Block (stack) | Block | Uninitialized |
register | Block (stack or CPU register) | Block | Uninitialized |
static | Program | Block or compilation unit | Zero |
extern | Program | Global (entire program) | Zero |
thread_local | Thread | ||
| (none)1 | Dynamic (heap) | Uninitialized (initialized to0 if usingcalloc()) |
malloc() andfree() library functions.Variables declared within ablock by default have automatic storage, as do those explicitly declared with theauto[note 2] orregister storage class specifiers. Theauto andregister specifiers may only be used within functions and function argument declarations;[citation needed] as such, theauto specifier is always redundant. Objects declared outside of all blocks and those explicitly declared with thestatic storage class specifier have static storage duration. Static variables are initialized to zero by default by the compiler.[citation needed]
Objects with automatic storage are local to the block in which they were declared and are discarded when the block is exited. Additionally, objects declared with theregister storage class may be given higher priority by the compiler for access toregisters; although the compiler may choose not to actually store any of them in a register. Objects with this storage class may not be used with the address-of (&) unary operator. Objects with static storage persist for the program's entire duration. In this way, the same object can be accessed by a function across multiple calls. Objects with allocated storage duration are created and destroyed explicitly withmalloc,free, and related functions.
Theextern storage class specifier indicates that the storage for an object has been defined elsewhere. When used inside a block, it indicates that the storage has been defined by a declaration outside of that block. When used outside of all blocks, it indicates that the storage has been defined outside of the compilation unit. Theextern storage class specifier is redundant when used on a function declaration. It indicates that the declared function has been defined outside of the compilation unit.
Thethread_local (_Thread_local beforeC23,[citation needed] and in earlier versions of C if the header<threads.h> is included) storage class specifier, introduced inC11, is used to declare a thread-local variable. It can be combined withstatic orextern to determine linkage.[further explanation needed]
Note that storage specifiers apply only to functions and objects; other things such as type and enum declarations are private to the compilation unit in which they appear.[citation needed] Types, on the other hand, have qualifiers (see below).
Since C23, C can useauto to declare atype-inferred variable.
Types can be qualified to indicate special properties of their data. The type qualifierconst indicates that a value does not change once it has been initialized. Attempting to modify aconst qualified value yields undefined behavior, so some compilers store them inrodata or (for embedded systems) inread-only memory (ROM). Similarly,constexpr can be thought of as a "stronger" form ofconst, where the value must be known at compile time (making it a type-safe replacement for macro constants). Aconstexpr function, similarly, must also be able to be evaluated at compile time. The type qualifiervolatile indicates to anoptimizing compiler that it may not remove apparently redundant reads or writes, as the value may change even if it was not modified by any expression or statement, or multiple writes may be necessary, such as formemory-mapped I/O.
An incomplete type is astructure or union type whose members have not yet been specified, anarray type whose dimension has not yet been specified, or thevoid type (thevoid type cannot be completed). Such a type may not be instantiated (its size is not known), nor may its members be accessed (they, too, are unknown); however, the derived pointer type may be used (but not dereferenced).
They are often used with pointers, either as forward or external declarations. For instance, code could declare an incomplete type like this:
structInteger*pt;
This declarespt as a pointer tostruct Integer (as well as the incomplete struct type). As all pointers have the same size (regardless of what they point to), code can usept as a pointer although it cannot access the fields ofstruct Integer.
An incomplete type can be completed later in the same scope by redeclaring it. For example:
structInteger{intnum;};
Incomplete types are used to implementrecursive structures; the body of the type declaration may be deferred to later in the translation unit:
typedefstructBertBert;typedefstructWilmaWilma;structBert{Wilma*wilma;};structWilma{Bert*bert;};
Incomplete types are also used fordata hiding. The incomplete type is defined in aheader file, and the full definition is hidden in a single body file.
In a variable declaration, the asterisk (*) can be considered to mean "pointer-to". For example,int x defines a variable of type int, andint* px defines a variablepx that is a pointer to integer. Some[who?] contend that based on the language definition, the* is more closly related to the variable than the type[how?] and therefore format the code asint *px or evenint * px.
A pointer value associates two pieces of information: a memory address and a data type.
When a non-static pointer is declared, it has an unspecified value. Dereferencing it without first assigning it, results in undefined behavior.
The& operator specifies the address of the data object after it. In the following example,ptr is assigned the address ofa:
inta=0;int*ptr=&a;
An asterisk before a variable name (when not in a declaration or a mathematical expression)dereferences a pointer to allow access to the value it points to. In the following example, the integer variableb is set to the value of integer variablea, which is10:
inta=10;int*p;p=&a;intb=*p;
Arrays store consecutive elements of the same type. The following code declares an array of 100 elements, nameda, of typeint.
inta[100];
If declared outside of a function (globally), the size must be a constant value. If declared in a function, the array size may be a non-constant expression.
The number of elements is available assizeof(a)/sizeof(int), but if the value is passed to another function, the number of elements is not available via the formal parameter variable.
The primary facility for accessing array elements is the array subscript operator. For example,a[i] accesses the element at indexi of arraya. Array indexingbegins at 0; making last array index equal to the number of elements minus 1. As the standard does not provide for array indexingbounds checking, specifying an index that is out of range, results in undefined behavior.
Due to arrays and pointers being interchangeable, the address of each elements can be expressed inpointer arithmetic. The following table illustrates both methods for the existing the same array:
| Element | First | Second | Third | nth |
|---|---|---|---|---|
| Array subscript | a[0] | a[1] | a[2] | a[n-1] |
| Dereferenced pointer | *a | *(a+1) | *(a+2) | *(a+n-1) |
Since the expressiona[i] is semantically equivalent to*(a + i), which in turn is equivalent to*(i + a), the expression can also be written asi[a], although this form is rarely used.
C99 standardized thevariable-length array (VLA) in block scope that produced an array sized by runtime information (not a constant value) but with fixed size until the end of the block.[1] As ofC11, this feature is no longer required to be implemented by the compiler.
intn=20;// n can be any arbitrary valueinta[n];a[3]=10;
The language supports arrays of multiple dimensions – stored inrow-major order which is essentially a one-dimensional array with elements that are arrays. Given thatROWS andCOLUMNS are constants, the following declares a two-dimensional array of lengthROWS; each element of which is an array ofCOLUMNS integers.
intarray2d[ROWS][COLUMNS];
The following is an example of accessing an integer element:
array2d[4][3]
Reading from left to right, this accesses the 5th row, and the 4th element in that row. The expressionarray2d[4] is an array, which is then subscripting with [3] to access the fourth integer.
| Element | First | Second row, second column | ith row,jth column |
|---|---|---|---|
| Array subscript | array[0][0] | array[1][1] | array[i-1][j-1] |
| Dereferenced pointer | *(*(array+0)+0) | *(*(array+1)+1) | *(*(array+i-1)+j-1) |
Higher-dimensional arrays can be declared in a similar manner.
A multidimensional array should not be confused with an array of pointers to arrays (also known as anIliffe vector or sometimes anarray of arrays). The former is always rectangular (all subarrays must be the same size), and occupies a contiguous region of memory. The latter is a one-dimensional array of pointers, each of which may point to the first element of a subarray in a different place in memory, and the sub-arrays do not have to be the same size.
Although the language provides types for textual character data, neither the language nor the standard library defines a string type, but thenull terminated string is commonly used. A string value is a contiguous series of characters with the end denoted by a zero value. The standard library contains manystring handling functions for null-terminated strings, but string manipulation can and often is handled via custom code.
Astring literal is code text surrounded by double quotes; for example"Hello world!". A literal compiles to an array of the specifiedchar values with a terminatingnull terminating character to mark the end of the string.
The language supportsstring literal concatenation – adjacent string literals are treated as joined at compile time. This allows long strings to be split over multiple lines, and also allows string literals from preprocessor macros to be appended to strings at compile time. For example, the source code:
printf(__FILE__": %d: Hello ""world\n");
becomes the following after the preprocessor expands__FILE__:
printf("helloworld.c"": %d: Hello ""world\n");
which is equivalent to:
printf("helloworld.c: %d: Hello world\n");
The character literal, called character constant, is single-quoted, e.g.'A', and has typeint. To illustrate the difference between a string literal and a character constant, consider that"A" is two characters, 'A' and '\0', whereas'A' represents a single character (65 in ASCII).
A character constant cannot be empty (i.e.'' is invalid syntax). Multi-character constants (e.g.'xy') are valid, although rarely useful — they let one store several characters in an integer (e.g. 4 ASCII characters can fit in a 32-bit integer, 8 in a 64-bit one). Since the order in which the characters are packed into anint is not specified (left to the implementation to define), portable use of multi-character constants is difficult.
Nevertheless, in situations limited to a specific platform and the compiler implementation, multicharacter constants do find their use in specifying signatures. One common use case is theOSType, where the combination of Classic Mac OS compilers and its inherent big-endianness means that bytes in the integer appear in the exact order of characters defined in the literal. The definition by popular "implementations" are in fact consistent: in GCC, Clang, andVisual C++,'1234' yields0x31323334 under ASCII.[5][6]
Like string literals, character constants can also be modified by prefixes, for exampleL'A' has typewchar_t and represents the character value of "A" in the wide character encoding.
Control characters cannot be included in a string or character literal directly. Instead they can be encoded via an escape sequence starting with a backslash (\). For example, the backslashes in"This string contains \"double quotes\"." indicate that the inner pair of quotes are intended as an actual part of the string, rather than the default reading as a delimiter (endpoint) of the string.
Escape sequences include:
| Sequence | Meaning |
|---|---|
\\ | Literal backslash |
\" | Double quote |
\' | Single quote |
\n | Newline (line feed) |
\r | Carriage return |
\b | Backspace |
\t | Horizontal tab |
\f | Form feed |
\a | Alert (bell) |
\v | Vertical tab |
\? | Question mark (used to escapetrigraphs, obsolete feature dropped in C23) |
\OOO | Character with octal valueOOO (whereOOO is 1-3 octal digits, '0'-'7') |
\xhh | Character with hexadecimal valuehh (wherehh is 1 or more hex digits, '0'-'9','A'-'F','a'-'f') |
\uhhhh | Unicodecode point below 10000 hexadecimal (added in C99) |
\Uhhhhhhhh | Unicode code point wherehhhhhhhh is eight hexadecimal digits (added in C99) |
The use of other backslash escapes is not defined by the standard, although compilers often provide additional escape codes as language extensions. For example, the escape sequence\e for theescape character with ASCII hex value 1B which was not added to the standard due to lacking representation in othercharacter sets (such asEBCDIC). It is available inGCC,clang andtcc.
Note that the standard library functionprintf() uses%% to represent the literal% character.
Since typechar is 1 byte wide, a singlechar value typically can represent at most 255 distinct character codes, not nearly enough for all the different characters in use worldwide. To provide better support for international characters, the first standard (C89) introducedwide characters (encoded in typewchar_t) and wide character strings, which are written asL"Hello world!"
Wide characters are most commonly either 2 bytes (using a 2-byte encoding such asUTF-16) or 4 bytes (usuallyUTF-32), but Standard C does not specify the width forwchar_t, leaving the choice to the implementor.Microsoft Windows generally uses UTF-16, thus the above string would be 26 bytes long for a Microsoft compiler; theUnix world prefers UTF-32, thus compilers such as GCC would generate a 52-byte string. A 2-byte widewchar_t suffers the same limitation aschar, in that certain characters (those outside theBMP) cannot be represented in a singlewchar_t; but must be represented usingsurrogate pairs.
The original standard specified only minimal functions for operating with wide character strings; in 1995 the standard was modified to include much more extensive support, comparable to that forchar strings. The relevant functions are mostly named after theirchar equivalents, with the addition of a "w" or the replacement of "str" with "wcs"; they are specified in<wchar.h>, with<wctype.h> containing wide-character classification and mapping functions.
The now generally recommended method[note 3] of supporting international characters is throughUTF-8, which is stored inchar arrays, and can be written directly in the source code if using a UTF-8 editor, because UTF-8 is a directASCII extension.
A common alternative towchar_t is to use avariable-width encoding, whereby a logical character may extend over multiple positions of the string. Variable-width strings may be encoded into literals verbatim, at the risk of confusing the compiler, or using numerical backslash escapes (e.g."\xc3\xa9" for "é" in UTF-8). TheUTF-8 encoding was specifically designed (underPlan 9) for compatibility with the standard library string functions; supporting features of the encoding include a lack of embedded nulls, no valid interpretations for subsequences, and trivial resynchronisation. Encodings lacking these features are likely to prove incompatible with the standard library functions; encoding-aware string functions are often used in such cases.
A structure is a container consisting of a sequence of named members of heterogeneous types; similar to a record in other languages. The first field starts at the address of the structure and the members are stored in consecutive locations in memory, but the compiler can insert padding between or after members for efficiency or as padding required for properalignment by the target architecture. The size of a structure includes padding.
A structure is declared with thestruct keyword followed by an optional identifier name, which is used to identify the form of the structure. The body follows with field declarations that each consist of a type name, a field name and terminated with a semi-colon.
The following declares a structure namedMyStruct that contains three members. It also declares an instance namedtee:
structMyStruct{intx;floaty;char*z;}tee;
Structure members cannot have an incomplete or function type. Thus members cannot be an instance of the structure being declared (because it is incomplete at that point) but a field can be a pointer to the type being declared.
Once declared, a variable can be declared of the structure type.The following declares a new instance of the structureMyStruct namedr:
structMyStructr;
Although some prefer to declare a struct variable using thestruct keyword, some usetypedef to alias the struct type into the main type namespace. The following declares a type asInteger which can then be used likeInteger n.
typedefstruct{inti;}Integer;
A member is accessed using dot notation. For example, given the declaration oftee from above, the membery can be accessed astee.y.
A structure is commonly accessed via a pointer. ConsiderstructMyStruct*ptee=&tee that defines a pointer totee, namedptee. Membery oftee can be accessed by dereferencingptee and using the result as the left operand as(*ptee).y.[b] Because this operation is common, the language provides anabbreviated syntax for accessing a member directly from a pointer; using->. For example,ptee->y.
Assigning a value to a member is like assigning a value to a variable. The only difference is that thelvalue (left side value) of the assignment is the name of the member; per above syntax.
A structure can also be assigned as a whole to another structure of the same type; passed by copy as a function argument or return value. For example,tee.x = 74 assigns the value 74 to the member namedx in the structuretee, And,ptee->x = 74 does the same forptee.
The operations supported for a structure are: initialize, copy, get address and access a field. Of note, the language does not support comparing the value of two structures other than via custom code to compare each field.
The language provides a special type of member known as abit field, which is an integer with a specified size in bits. A bit field is declared as a member of type (signed/unsigned)int, or_Bool,[note 4] plus a suffix after the member name consisting of a colon and a number of bits. The total number of bits in a single bit field must not exceed the total number of bits of its base type. Contrary to the usual C syntax rules, it is implementation-defined whether a bit field is signed or unsigned if not explicitly specified. Therefore, best practice is to specifysigned orunsigned.
Unnamed fields indicatepadding and consist of just a colon followed by a number of bits. Specifying a width of zero for an unnamed field is used to forcealignment to a new word.[7] Since all members of a union occupy the same memory, unnamed bit-fields of width zero do nothing in unions, however unnamed bit-fields of non zero width can change the size of the union since they have to fit in it.
Bit fields are limited compared to normal fields in that the address-of (&) andsizeof operators are not supported.
The following declares a structure type namedFlagStatus and an instance of it namedg. The first field, flag, is a single bit flag; can physically be only 1 or 0. The second field, num, is a signed 4-bit field; range -7...7 or -8...7. The last field adds 3 bits of padding to round out the structure to 8 bits.
structFlagStatus{unsignedintflag:1;signedintnum:4;signedint:3;}g;
C itself has no native support fornamespaces unlike C++ and Java. This makes C symbol names prone to name clashes. However, it is possible to use anonymous structs to emulate namespaces.
Math.h:
#pragma onceconststruct{doublePI;double(*sin)(double);}Math;
Math.c:
#include<math.h>staticdouble_sin(doublearg){returnsin(arg);}conststruct{doublePI;double(*sin)(double);}Math={M_PI,_sin};
Main.c:
#include<stdio.h>#include"Math.h"intmain(){printf("sin(0) = %d\n",Math.sin(0));printf("pi is %f\n",Math.PI);}
For the most part, a union is like a structure except that fields overlap in memory to allow storing values of different type although not at the same time. The union is like the variant record of other languages. Each field refers to the same location in memory. The size of a union is equal to the size of its largest component type plus any padding.
A union is declared with theunion keyword. The following declares a union namedMyUnion and an instance of it namedn:
unionMyUnion{intx;floaty;char*z;}n;
Initializing a variable along with declaring it involves appending an equals sign and then a construct that is compatible with the data type. The following initializes an int:
intx=12;
Because of the language's grammar, a scalar initializer may be enclosed in any number of curly brace pairs. Most compilers issue a warning if there is more than one such pair. The following are legal although arguably unusual:
inty={23};intz={{34}};
Structures, unions and arrays can be initialized after a declaration via an initializer list.
Since unmatched elements are set to 0, an empty list sets all elements to 0. For example, the following sets all elements of array a and all fields of s to 0:
inta[10]={};structMyStructs={};
If an array is declared without an explicit size, the array is anincomplete type. The number of initializers determines the size of the array and completes the type. For example:
intx[]={0,1,2};
By default, the items of an initializer list correspond with the elements in the order they are defined. Including too many values yields an error. The following statement initializes an instance of the structureMySteuct namedpi:
structMyStruct{intx;floaty;char*z;};structMyStructpi={3,3.1415,"Pi"};
Designated initializers allow members to be initialized by name, in any order, and without explicitly providing preceding values. The following initialization is functionally equivalent to the previous:
structMyStructpi={.z="Pi",.x=3,.y=3.1415};
Using a designator in an initializer moves the initialization "cursor". In the example below, ifMAX is greater than 10, there will be some zero-valued elements in the middle ofa; if it is less than 10, some of the values provided by the first five initializers will be overridden by the second five. IfMAX is less than 5, there will be a compilation error:
inta[MAX]={1,3,5,7,9,[MAX-5]=8,6,4,2,0};
InC89, a union was initialized with a single value applied to its first member. That is, the unionMyUnion defined above could only have itsx member initialized:
unionMyUnionvalue={3};
Using a designated initializer, the member to be initialized does not have to be the first member:
unionMyUnionvalue={.y=3.1415};
Compound designators can be used to provide explicit initialization when unadorned initializer lists might be misunderstood. In the example below,w is declared as an array of structures, each structure consisting of a membera (an array of 3int) and a memberb (anint). The initializer sets the size ofw to 2 and sets the values of the first element of eacha:
struct{inta[3],b;}w[]={[0].a={1},[1].a[0]=2};
This is equivalent to:
struct{inta[3],b;}w[]={{{1,0,0},0},{{2,0,0},0}};
It is possible to borrow the initialization methodology to generate compound structure and array literals:
// pointer created from array literal.int*ptr=(int[]){10,20,30,40};// pointer to array.float(*foo)[3]=&(float[]){0.5f,1.f,-0.5f};structMyStructpi=(structMyStruct){3,3.1415,"Pi"};
Compound literals are often combined with designated initializers to make the declaration more readable:[1]
pi=(structMyStruct){.z="Pi",.x=3,.y=3.1415};
Apointer to a function can be declared like:
type-name (*function-name)(parameter-list);
The following program code demonstrates the use of a function pointer for selecting between addition and subtraction.Line 12 defines a function pointer variable namedoperation that supports the same interface as both theadd andsubtract functions. Based on the conditional (argc),operation is assigned to the address of eitheradd orsubtract. Online 14, the function thatoperation points to is called.
[[nodiscard]]constexprintadd(intx,inty){returnx+y;}[[nodiscard]]constexprintsubtract(intx,inty){returnx-y;}intmain(intargc,char*argv[]){int(*operation)(intx,inty);operation=argc?add:subtract;intresult=operation(1,1);returnresult;}
This is a list ofoperators in theC andC++programming languages.
All listed operators are in C++ and lacking indication otherwise, in C as well. Some tables include a "In C" column that indicates whether an operator is also in C. Note that C does not supportoperator overloading.
When not overloaded, for the operators&&,||, and, (thecomma operator), there is asequence point after the evaluation of the first operand.
Most of the operators available in C and C++ are also available in otherC-family languages such asC#,D,Java,Perl, andPHP with the same precedence, associativity, and semantics.
Many operators specified by a sequence of symbols are commonly referred to by a name that consists of the name of each symbol. For example,+= and-= are often called "plus equal(s)" and "minus equal(s)", instead of the more verbose "assignment by addition" and "assignment by subtraction".Acompound statement, a.k.a. statement block, is a matched pair of curly braces with any number of statements between, like:
{ {statement}}As a compound statement is a type of statement, whenstatement is used, it could be a single statement (without enclosing braces) or a compound statement (with enclosing braces). A compound statement is required for a function body and for a control structure branch that is not one statement.
A variable declared in a block can be referenced by code in that block (and inner blocks) below the declaration. Access to memory used for a block-declared variable after the block close (i.e. via a pointer) results in undefined behavior.
Theifconditional statement is like:
if(expression) {statement} else {statement}If theexpression is not zero, control passes to the first statement. Otherwise, control passes to the second statement. If theelse part is absent, then when the expression evaluates to zero, the first statement is simply skipped. Anelse always matches the nearest previous unmatchedif. Braces may be used to override this when necessary, or for clarity.
Notably, the second statement can be anotherif statement. For example:
if(i==1){printf("it's 1");}elseif(i==2){printf("it's 2");}else{printf("it's something else");}
Theswitch transfers control to the case label that has a value matching theintegral type expression or otherwise to thedefault label (if any). Control continues to the statements that follow thecase label until abreak statement or until the end of theswitch statement. The syntax is like:
switch(expression) {caselabel-name: statementcaselabel-name: statement . . .default: statement}Eachcase value must be unique within the statement. There may be at most onedefault label.
Execution continues from onecase label to the next if nobreak statement is encounters. This is known asfalling through which is useful in some circumstances, but often is not not desired.
It is possible, although unusual, to locatecase labels in the sub-blocks of inner control structures. Examples includeDuff's device andSimon Tatham's implementation ofcoroutines inPutty.[8]
There are three forms ofiteration statement:
while (expression) {statement}do {statement} while (expression)for (init;test;next) {statement}For thewhile anddo statements, the sub-statement is executed repeatedly so long as the value of theexpression is non-zero. Forwhile, the test, including any side effects, occurs before each iteration. Fordo, the test occurs after each iteration. Thus, ado statement always executes its sub-statement at least once, whereaswhile might not execute the sub-statement at all.
The logic offor can be described in terms ofwhile in that this:
for(e1;e2;e3){s;}
is equivalent to:
e1;while(e2){s;cont:e3;}
except for the behavior of acontinue; statement (which in thefor loop jumps toe3 instead ofe2). Ife2 is blank, it would have to be replaced with a1.
Any of the three expressions in thefor loop may be omitted. A missing second expression makes thewhile test always non-zero; describing an infinite loop.
Since C99, the first expression may take the form of a declaration with scope limited to the sub-statement For example:
for(inti=0;i<limit;++i){// ...}
Theforeach loop does not exist in C, like it does in Java and C++. However, it can be emulated using macros.
There are fourjump statements (transfer control unconditionally):goto,continue,break, andreturn.
Thegoto statement passes program control to a labeled statement. It has the following syntax:
gotolabel-name
Acontinue statement which is simply the wordcontinue, transfers control to the loop-continuation point of the innermost, enclosing iteration statement. It must be enclosed within an iteration statement. For example:
while(true){// ...continue;}do{// ...continue;}while(true);for(;;){// ...continue;}
Thebreak statement which is simply the wordbreak ends afor,while,do, orswitch statement. Control passes to the statement following the enclosing control statement.
Thereturn statement transfers control the function caller. Whenreturn is followed by an expression, the value is returned to the caller. Encountering the end of the function is equivalent to areturn with no expression. In that case, if the function is declared as returning a value and the caller tries to use the returned value, the behavior is undefined.
A label marks a point in the code to which control can be transferred. A label is an identifier followed by a colon. For example:
if(i==1){gotoEND;}// other codeEND:
The standard does not define a method to retrieve the address of a label, butGCC extends the language with a unary&& operator that returns the address of a label. The address can be stored in avoid* variable and may be used later with agoto. This feature can be used to implement ajump table.
For example, the following printshi repeatedly:
void*ptr=&&J1;J1:printf("hi");goto*ptr;
SinceC2Y, C has labelled loops, similar to Java. This allows for attaching labels tofor, and transferring control throughbreak andcontinue with labels (multi-level breaks).[9]
// using break:outer:for(inti=0;i<n;++i){switch(i){case1:break;// jumps to 1case2:breakouter;// jumps to 2default:continue;}// 1}// 2// using continue:outer:for(inti=0;i<m;++i){for(intj=0;j<n;++j){continue;// jumps to 1continueouter;// jumps to 2// 1}// 2}
For a function that returns a value, a definition consists of areturn type name, a function name that is unique in the codebase, a list of parameters in parentheses, and a statement block that ends with areturn statement. The block can contain areturn statement to exit the function before the end of the block. The syntax is like:
type-namefunction-name(parameter-list){statement-listreturnvalue;}A function that returns no value is declared withvoid instead of a type name, like:
voidfunction-name(parameter-list){statement-list}The standard does not includelambda functions, butsome translators do.
Aparameter-list is a comma-separated list of formal parameter declarations; each item a type name followed by a variable name:
type-namevariable-name{,type-namevariable-name}The return type cannot be an array or a function. For example:
intf()[3];// Error: function returning an arrayint(*g())[3];// OK: function returning a pointer to an arrayvoidh()();// Error: function returning a functionvoid(*k())();// OK: function returning a function pointer
If the function accepts no parameters, theparameter-list may be the keywordvoid or blank, but these have different implications. Calling a function with arguments when it is declared withvoid for theparameter-list is invalid syntax. Calling a function with arguments when it is declared with a blankparameter-list is not invalid syntax, but may result in undefined behavior. Usingvoid, is therefore, best practice.
A function can accept a variable number of arguments by including... at the end of the argument list. A commonly used function with this declaration is the standard library functionprintf which has prototype:
intprintf(constchar*,...);
Consuming variable length arguments can be accomplished via standard library functions declared in<stdarg.h>.
Code can access a function of alibrary if it is both declared and defined. Often a declaration is provided for a library function via a header file that the consuming code uses via the#include directive. Alternatively, the consuming code can declare the function in its own file. The function definition is associated with the consuming code at link-time. Thestandard library is generally linked by default whereas other libraries require link-time configuration.
Accessing a user-defined function that is defined in a different file is similar to using a library function. The consuming code declares the function either by including a header file or directly in its file. Linking to the definition in the other file is handled when the object files are linked.
Calling a function that is defined in the same file is relatively simple. The definition or a declaration of it must be above the call.
An argument is passed to a functionby value which means that a called function receives a copy of the argument and cannot alter the argument variable. For a function to alter the value of a variable, the caller passes the variable's address (a pointer) which simulates what other languages provide asby reference. The called function can modify the variable by dereferencing the passed address.
In the following code, the address ofx is passed by specifing&x in the call. The called function receives the address asy and accessesx as*y.
voidincInt(int*y){(*y)++;}intmain(void){intx=7;incInt(&x);return0;}
The following code demonstrates a more advanced use of pointers – passing a pointer to a pointer. An int pointer nameda is defined on line 9 and its address is passed to the function on line 10. The function receives a pointer to pointer to int nameda_p. It assignsa (as*a_p). After the call, on line 11, the memory allocated and assigned to addressa is freed.
#include<stdio.h>#include<stdlib.h>voidallocate_array(int**consta_p,constintcount){*a_p=malloc(sizeof(int)*count);}intmain(void){int*a;allocate_array(&a,42);free(a);return0;}
Function parameters of array type may at first glance appear to be an exception to the pass-by-value rule as demonstrated by the following program that prints 123; not 1:
#include<stdio.h>voidsetArray(intarray[],intindex){array[index]=123;}intmain(void){inta[1]={1};setArray(a,0);printf("a[0]=%d\n",a[0]);return0;}
However, there is a different reason for this behavior. An array parameter is treated as a pointer. The following prototype is equivalent to the function prototype above:
voidsetArray(int*array,intindex);
At the same time, rules for the use of arrays in expressions cause the value ofa to be treated as a pointer to the first element. Thus, this is still pass-by-value, with the caveat that it is the address of the first element of the array being passed by value; not the contents of the array.
Since C99, the programmer can specify that a function takes an array of a certain size by using the keywordstatic. InvoidsetArray(intarray[static4],intindex) the first parameter must be a pointer to the first element of an array of length at least 4. It is also possible to use qualifiers (const,volatile andrestrict) to the pointer type that the array is converted to.
Added in C23 and originating from C++11, C supports attribute specifier sequences.[10] Attributes can be applied to any symbol that supports them, including functions and variables, and any symbol marked with an attribute will be specifically treated by the compiler as necessary. These can be thought of as similar toJava annotations for providing additional information to the compiler, however they differ in that attributes in C are not metadata that is meant to be accessed using reflection. Furthermore, one cannot create custom attributes in C, unlike in Java where one may define custom annotations in addition to the standard ones. However, C does have implementation/vendor-specific attributes which are non-standard. These typically have a namespace associated with them. For instance, GCC and Clang have attributes under thegnu:: namespace, and all such attributes are of the form[[gnu::*]], though C does not have support for namespacing in the language.
The syntax of using an attribute on a function is like so:
[[nodiscard]]boolsatisfiesProperty(conststructMyStruct*s);
The standard defines the following attributes:
| Name | Description |
|---|---|
[[noreturn]] | Indicates that the specified function will not return to its caller. |
[[deprecated]][[deprecated("reason")]] | Indicates that the use of the marked symbol is allowed but discouraged/deprecated for the reason specified (if given). |
[[fallthrough]] | Indicates that the fall through from the previous case label is intentional. |
[[maybe_unused]] | Suppresses compiler warnings on an unused entity. |
[[nodiscard]][[nodiscard("reason")]] | Issues a compiler warning if the return value of the marked symbol is discarded or ignored for the reason specified (if given). |
[[unsequenced]] | Indicates that a function is stateless, effectless, idempotent and independent. |
[[reproducible]] | Indicates that a function is effectless and idempotent. |
C dynamic memory allocation refers to performingmanual memory management fordynamic memory allocation in theC programming language via a group of functions in theC standard library, namelymalloc,realloc,calloc,aligned_alloc andfree.[11][12][13]
TheC++ programming language includes these functions; however, the operatorsnew anddelete provide similar functionality and are recommended by that language's authors.[14] Still, there are several situations in which usingnew/delete is not applicable, such as garbage collection code or performance-sensitive code, and a combination ofmalloc andnew may be required instead of the higher-levelnew operator.
*ptee.y is not correct; instead being parsed as*(ptee.y) and thus the parentheses are necessary.