Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
C syntax
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
===Primitive data types=== The C programming language represents numbers in three forms: ''[[Integer (computer science)|integral]]'', ''[[Real data type|real]]'' and ''[[Complex data type|complex]]''. This distinction reflects similar distinctions in the [[instruction set]] architecture of most [[central processing unit]]s. ''Integral'' data types store numbers in the set of [[integer]]s, while ''real'' and ''complex'' numbers represent numbers (or pair of numbers) in the set of [[real number]]s in [[floating-point arithmetic|floating-point]] form. All C integer types have {{code|signed}} and {{code|unsigned}} variants. If {{code|signed}} or {{code|unsigned}} is not specified explicitly, in most circumstances, {{code|signed}} is assumed. However, for historic reasons, plain {{code|char}} is a type distinct from both {{code|signed char}} and {{code|unsigned char}}. It may be a signed type or an unsigned type, depending on the compiler and the character set (C guarantees that members of the C basic character set have positive values). Also, [[bit field]] types specified as plain {{code|int}} may be signed or unsigned, depending on the compiler. ====Integer types==== C's integer types come in different fixed sizes, capable of representing various ranges of numbers. The type {{code|char}} occupies exactly one [[byte]] (the smallest addressable storage unit), which is typically 8 bits wide. (Although {{code|char}} can represent any of C's "basic" characters, a wider type may be required for international character sets.) Most integer types have both [[signedness|signed and unsigned]] varieties, designated by the {{code|signed}} and {{code|unsigned}} keywords. Signed integer types always use the [[two's complement]] [[Signed number representations|representation]], since [[C23 (C standard revision)|C23]]<ref name="N2412">{{cite web |title=WG14-N2412: Two's complement sign representation |url=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2412.pdf |website=open-std.org |archive-url=https://web.archive.org/web/20221227174224/https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2412.pdf |archive-date=December 27, 2022 |date=August 11, 2019 |url-status=live}}</ref> (and in practice before; in older C versions before C23 the representation might alternatively have been [[ones' complement]], or [[sign-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, {{code|signed short int}} and {{code|short}} 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 provides a complete list of the standard integer types and their ''minimum'' allowed widths (including any sign bit). {| class="wikitable" |+ Specifications for standard integer types |- ! Shortest form of specifier !! Minimum width (bits) |- | {{code|bool}} | style="text-align: center" | 1 |- | {{code|char}} | style="text-align: center" | 8 |- | {{code|signed char}} | style="text-align: center" | 8 |- | {{code|unsigned char}} | style="text-align: center" | 8 |- | {{code|short}} | style="text-align: center" | 16 |- | {{code|unsigned short}} | style="text-align: center" | 16 |- | {{code|int}} | style="text-align: center" | 16 |- | {{code|unsigned int}} | style="text-align: center" | 16 |- | {{code|long}} | style="text-align: center" | 32 |- | {{code|unsigned long}} | style="text-align: center" | 32 |- | {{code|long long}}<ref group="note" name="long long">The {{code|long long}} modifier was introduced in the [[C99]] standard.</ref> | style="text-align: center" | 64 |- | {{code|unsigned long long}}<ref group="note" name="long long"/> | style="text-align: center" | 64 |} The {{code|char}} type is distinct from both {{code|signed char}} and {{code|unsigned char}}, but is guaranteed to have the same representation as one of them. The {{code|_Bool}} and {{code|long long}} types are standardized since 1999, and may not be supported by older C compilers. Type {{code|_Bool}} is usually accessed via the <code>[[typedef]]</code> name {{code|bool}} defined by the standard header <code><[[stdbool.h]]></code>, however since C23 the {{code|_Bool}} type has been renamed {{code|bool}}, and <code><stdbool.h></code> 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 the {{code|int}} type varies especially widely among C implementations; it often corresponds to the most "natural" word size for the specific 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 for {{code|typedef}}s in standard headers. For more precise specification of width, programmers can and should use {{code|typedef}}s from the standard header [[stdint.h]]. Integer constants may be specified in source code in several ways. Numeric values can be specified as [[decimal]] (example: {{code|1022}}), [[octal]] with zero ({{code|0}}) as a prefix ({{code|01776}}), or [[hexadecimal]] with {{code|0x}} (zero x) as a prefix ({{code|0x3FE}}). A character in single quotes (example: {{code|'R'}}), called a "character constant," represents the value of that character in the execution character set, with type {{code|int}}. 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 as {{code|int}}. This can be overridden by appending an explicit length and/or signedness modifier; for example, {{code|12lu}} has type {{code|unsigned long}}. There are no negative integer constants, but the same effect can often be obtained by using a unary negation operator "{{code|-}}". ====Enumerated type==== The [[enumerated type]] in C, specified with the {{code|enum}} keyword, and often just called an "enum" (usually pronounced {{IPAc-en|'|i:|n|V|m}} {{respell|EE|num}} or {{IPAc-en|'|i:|n|u:|m}} {{respell|EE|noom}}), is a type designed to represent values across a series of named constants. Each of the enumerated constants has type {{code|int}}. Each {{code|enum}} type itself is compatible with {{code|char}} 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, and {{code|enum}} constants can be used anywhere an integer is expected. For this reason, {{code|enum}} values are often used in place of preprocessor {{code|#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 the {{code|enum}} specifier and an optional name (or ''tag'') 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 the {{code|enum}} 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: <syntaxhighlight lang=C>enum colors { RED, GREEN, BLUE = 5, YELLOW } paint_color;</syntaxhighlight> This declares the {{code|enum colors}} type; the {{code|int}} constants {{code|RED}} (whose value is 0), {{code|GREEN}} (whose value is one greater than {{code|RED}}, 1), {{code|BLUE}} (whose value is the given value, 5), and {{code|YELLOW}} (whose value is one greater than {{code|BLUE}}, 6); and the {{code|enum colors}} variable {{code|paint_color}}. The constants may be used outside of the context of the {{code|enum}} (where any integer value is allowed), and values other than the constants may be assigned to {{code|paint_color}}, or any other variable of type {{code|enum colors}}. ====Floating-point types==== 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 since [[C23 (C standard revision)|C23]] three more decimal types): single precision ({{code|float}}), double precision ({{code|double}}), and double extended precision ({{code|long double}}). Each of these may represent values in a different form, often one of the [[IEEE floating-point]] formats. {| class="wikitable" width="80%" |+ Floating-point types |- ! rowspan="2" | Type specifiers ! colspan="2" | Precision (decimal digits) ! colspan="2" | Exponent range |- ! Minimum ! IEEE 754 ! Minimum ! IEEE 754 |- | {{code|float}} | align="center" | 6 | align="center" | 7.2 (24 bits) | align="center" | Β±37 | align="center" | Β±38 (8 bits) |- | {{code|double}} | align="center" | 10 | align="center" | 15.9 (53 bits) | align="center" | Β±37 | align="center" | Β±307 (11 bits) |- | {{code|long double}} | align="center" | 10 | align="center" | 34.0 (113 bits) | align="center" | Β±37 | align="center" | Β±4931 (15 bits) |} Floating-point constants may be written in [[decimal notation]], e.g. {{code|1.23}}. [[Decimal scientific notation]] may be used by adding {{code|e}} or {{code|E}} followed by a decimal exponent, also known as [[E notation]], e.g. {{code|1.23e2}} (which has the value 1.23 Γ 10<sup>2</sup> = 123.0). Either a decimal point or an exponent is required (otherwise, the number is parsed as an integer constant). [[Hexadecimal floating-point constant]]s follow similar rules, except that they must be prefixed by {{code|0x}} and use {{code|p}} or {{code|P}} to specify a binary exponent, e.g. {{code|0xAp-2}} (which has the value 2.5, since A<sub>h</sub> Γ 2<sup>β2</sup> = 10 Γ 2<sup>β2</sup> = 10 Γ· 4). Both decimal and hexadecimal floating-point constants may be suffixed by {{code|f}} or {{code|F}} to indicate a constant of type {{code|float}}, by {{code|l}} (letter {{code|l}}) or {{code|L}} to indicate type {{code|long double}}, or left unsuffixed for a {{code|double}} constant. The standard header file [[float.h|{{code|float.h}}]] defines the minimum and maximum values of the implementation's floating-point types {{code|float}}, {{code|double}}, and {{code|long double}}. It also defines other limits that are relevant to the processing of floating-point numbers. [[C23 (C standard revision)|C23]] introduces three additional ''decimal'' (as opposed to binary) real floating-point types: _Decimal32, _Decimal64, and _Decimal128. <!-- It's unclear if decimal is optional as keywords, or just in library: Support for the ISO/IEC 60559:2020, the current version of the [[IEEE 754|IEEE 754 standard]] for floating-point arithmetic, with extended binary floating-point arithmetic and (optional) decimal floating-point arithmetic.<ref name="N2341">{{cite web |title=WG14-N2341: ISO/IEC TS 18661-2 - Floating-point extensions for C - Part 2: Decimal floating-point arithmetic |url=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2341.pdf |website=open-std.org |archive-url=https://web.archive.org/web/20221121122559/https://open-std.org/JTC1/SC22/WG14/www/docs/n2341.pdf |archive-date=November 21, 2022 |date=February 26, 2019 |url-status=live}}</ref><ref name="N2601">{{cite web |title=WG14-N2601: Annex X - IEC 60559 interchange and extended types |url=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2601.pdf |website=open-std.org |archive-url=https://web.archive.org/web/20221014221322/https://open-std.org/JTC1/SC22/WG14/www/docs/n2601.pdf |archive-date=October 14, 2022 |date=October 15, 2020 |url-status=live}}</ref> --> : NOTE C does not specify a radix for '''float''', '''double''', and '''long double'''. An implementation can choose the representation of '''float''', '''double''', and '''long double''' to be the same as the decimal floating types.<ref name="N2341">{{cite web |title=WG14-N2341: ISO/IEC TS 18661-2 - Floating-point extensions for C - Part 2: Decimal floating-point arithmetic |url=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2341.pdf |website=open-std.org |archive-url=https://web.archive.org/web/20221121122559/https://open-std.org/JTC1/SC22/WG14/www/docs/n2341.pdf |archive-date=November 21, 2022 |date=February 26, 2019 |url-status=live}}</ref> 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 since [[IBM System z10]]), can use the explicitly decimal types. <!-- Lots more keywords added in C23 (also for the preprocessor), see at https://en.cppreference.com/w/c/keyword such as _BitInt, typeof and thread_local as opposed to older _Thread_local. NOT mentioned there, only at https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2601.pdf (and note C23 is not yet finalized): X.5.1 Keywords _Float32x _Float64x _Float128x .. X.5.2 Constants [1] This subclause specifies constants of interchange and extended floating types. [2] This subclause expands floating-suffix (6.4.4.2) to also include: fN FN fNx FNx dN DN dNx DNx .. The type specifiers _FloatN (where N is 16, 32, 64, or β₯ 128 and a multiple of 32), _Float32x, _Float64x, _Float128x, _DecimalN (where N is 96 or > 128 and a multiple of 32), _Decimal64x, and _Decimal128x shall not be used if the implementation does not support the corresponding types (see 6.10.8.3 and X.2). .. β _DecimalN, where N is 96 or > 128 and a multiple of 32 β _Decimal64x β _Decimal128x β _FloatN _Complex, where N is 16, 32, 64, or β₯ 128 and a multiple of 32 --> ====Storage class specifiers==== Every object has a storage class.{{cn|date=April 2025}} This specifies most basically the storage ''duration,'' which may be static (default for global), automatic (default for local), or dynamic (allocated), together with other features (linkage and register hint).{{cn|date=April 2025}} {| class="wikitable" |+ Storage classes |- ! Specifiers ! Lifetime ! Scope ! Default initializer |- | {{code|auto}} | Block (stack) | Block | Uninitialized |- | {{code|register}} | Block (stack or CPU register) | Block | Uninitialized |- | {{code|static}} | Program | Block or compilation unit | Zero |- | {{code|extern}} | Program | Global (entire program) | Zero |- | {{code|_Thread_local}} | Thread | | |- | ''(none)''<sup>1</sup> | Dynamic (heap) | | Uninitialized (initialized to {{code|0}} if using {{code|calloc()}}) |} :<sup>1</sup> Allocated and deallocated using the {{code|malloc()}} and {{code|free()}} library functions. Variables declared within a [[block (programming)|block]] by default have automatic storage, as do those explicitly declared with the [[Automatic variable|{{code|auto}}]]<ref group="note">The meaning of auto is a type specifier rather than a storage class specifier in C++0x</ref> or [[Register (keyword)|{{code|register}}]] storage class specifiers. The {{code|auto}} and {{code|register}} specifiers may only be used within functions and function argument declarations;{{cn|date=April 2025}} as such, the {{code|auto}} specifier is always redundant. Objects declared outside of all blocks and those explicitly declared with the [[Static variable|{{code|static}}]] storage class specifier have static storage duration. Static variables are initialized to zero by default by the [[compiler]].{{cn|date=April 2025}} 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 the {{code|register}} storage class may be given higher priority by the compiler for access to [[Register (computing)|registers]]; 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 ({{code|&}}) 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 with [[malloc|{{code|malloc}}]], {{code|free}}, and related functions. The [[External variable|{{code|extern}}]] 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. The {{code|extern}} 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. The [[Thread-local storage|{{code|_Thread_local}}]] (<code>thread_local</code> in [[C++]], and in C since [[C23 (C standard revision)|C23]],{{cn|date=April 2025}} and in earlier versions of C if the header <code><threads.h></code> is included) storage class specifier, introduced in [[C11 (C standard revision)|C11]], is used to declare a thread-local variable. It can be combined with {{code|static}} or {{code|extern}} to determine linkage.{{explain|reason=probably should link to, or otherwise explain, threads before discussing thread local storage|date=April 2025}} 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.{{cn|date=April 2025}} Types, on the other hand, have qualifiers (see below). ====Type qualifiers==== {{main|Type qualifier}} Types can be qualified to indicate special properties of their data. The type qualifier <code>[[const (computer programming)|const]]</code> indicates that a value does not change once it has been initialized. Attempting to modify a <code>const</code> qualified value yields undefined behavior, so some C compilers store them in [[rodata]] or (for embedded systems) in [[read-only memory]] (ROM). The type qualifier <code>[[volatile (computer programming)|volatile]]</code> indicates to an [[optimizing 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 for [[memory-mapped I/O]].
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)