- C variable types and declarations
The C programming language has an extensive system for declaring variables of different types. The rules for the more complex types can be confusing at times, due to the decisions taken over their design. The principal decision is that the declaration of a variable should be similar, syntactically, to its use (declaration reflects use). This article presents a collection of variable declarations, starting at simple types, and proceeding to more complex types. No attempt is made to present code which actually uses the variables declared.
There are four basic types of variable in C; they are:
To declare a variable of any of these basic types, the name of the type is given first, then the name of the new variable second.
Various qualifiers can be placed on these basic types, in order to further describe their type.
If signed, the most significant bit designates a positive or negative value leaving the remaining bits to be used to hold a designated value. Unsigned integers can only take positive numbers, while signed integers (default) can take both positive and negative numbers. The advantage of unsigned integers is to allow a greater range of positive values (e.g. 0 → +65535 depending on the size of the integer), whereas signed integers allow only up to half the same number as positive integers and the other half as negative integers (e.g. −32768 → +32767).
An unsigned character, depending on the code page, might access an extended range of characters from 0 → +255, instead of that accessible by a signed char from −128 → +127, or it might simply be used as a small integer. The standard requires
unsigned charto be different types. Since most standardized string functions take pointers to plain
char, many C compilers correctly complain if one of the other character types is used for strings passed to these functions.
inttype can also be given a size qualifier, to specify more precisely the range of values (and memory size requirements) of the value stored.
When declaring a
long int, it is permissible to omit the
int, as this is implied. The following two declarations are equivalent.
There is some confusion in novice C programmers as to how big these types are. The standard is specifically vague in this area:
short intmust not be larger than an
intmust not be larger than a
short intmust be at least 16 bits long.
intmust be at least 16 bits long.
long intmust be at least 32 bits long.
long long intmust be at least 64 bits long.
The standard does not require that any of these sizes are necessarily different. It is perfectly valid, for example, that all four types be 64 bits long. In order to allow a simple and concise description of the sizes a compiler will apply to each of the four types (and the size of a pointer type; see below), a simple naming scheme has been devised; see [http://archive.opengroup.org/public/tech/aspen/lp64_wp.htm 64-Bit Programming Models] . Two popular schemes are
ILP32, in which
long intand pointer types are 32 bits long; and
LP64, in which
long intand pointers are 64 bits, and
intare 32 bits. Most implementations under these schemes use 16-bit
doublevariable can be marked as being a
long double, which the compiler may use to select a larger floating point representation than a plain
double. Again, the standard is unspecific on the relative sizes of the floating point values, and only requires a
floatnot to be larger than a
double, which should not be larger than a
To help promote safety in programs, values can be marked as being constant with the
consttype qualifier. Compilers must diagnose, usually with an error, attempts to modify such variables. Since
constvariables cannot be assigned to, they must be initialized at the point of declaration.
The C standard permits arbitrary ordering of type qualifiers, such as
const, and type specifiers, such as
int. Both the following declarations are therefore equivalent:While the former more closely reflects the use of
constmarking when used in pointer types, the latter form is more natural and almost ubiquitous.
Variables can be declared as being pointers to values of various types, by means of the "*" type declarator. To declare a variable as a pointer, immediately precede its name with an asterisk.
K&R gives a good explanation for the slightly odd use of asterisks in this way, as well as a motivation for why they attach the asterisk onto the name of the variable, when it might seem to make more sense being attached to the name of the type. This is, that when you
dereferencethe pointer, it has the type of the thing it points at. In this case,
*circleis a value of type
long. While this may be a subtle point to raise in this case, it starts to show its worth when more complex types are used. This is the reason for C's slightly odd way of declaring more complex types, when the name of the actual variable gets hidden within the type declaration, as further examples will show. However, the standard also allows you to attach the asterisk to the name of the type such as
long* circle. This form is usually discouraged since it can confuse the novice when multiple pointers are declared on the same line.
There is a special type of value which cannot be directly used as a variable type, but only as pointed type in the case of pointer declarations.
The pointed value here cannot be used directly; attempts to
dereferencethis pointer will result in a compiler error. The utility here is that this is a "generic" pointer; useful when the pointed type does not matter, simply the pointer address is needed. It is usually used to store pointers in utility types, such as linked lists, or hash tables, where the code using the utility will typecast it to a pointer of some specific type.
The pointed type can take all of the usual markings given above; the following are all valid pointer declarations.
Note specifically the use of
constin this last case. Here,
kiteis a (non-
const) pointer to a
const char. The value of
kiteitself is not a constant, only the value of the
charto which it points. The placement of
constbefore the type, as noted above, gives motivation for the way a constant pointer is declared. As it is constant, it must be initialised when it is declared.
pentagonis a constant pointer, which points at a
char. The value at which it points is not a constant; it will not be an error to modify the pointed character; only to modify the pointer itself. It is also possible to declare both the pointer and the pointed value as being constant. The following two declarations are equivalent.
Pointers to pointers
Because, for example,
char *is itself a type, pointer variables can be declared which point at values of such a type. These are pointers to pointers.
As before, the usual type qualifiers and
constmarking can be applied.
octagonas a pointer to a constant pointer to a constant
unsigned longinteger. Pointer types can be arbitrarily nested below this, but their use is increasingly harder to think clearly about, the more levels of indirectness are involved. Any code using more than two levels of pointer probably requires a redesign, in terms of
See also [http://c2.com/cgi/wiki?ThreeStarProgrammer Three Star Programmer] at the
However, as noted above, C's declaration syntax aims to make declarations resemble use. Because an access into this array would look like
cat [i], it is declared in a different syntax in C.
Arrays of arrays
As with pointers, array types can be nested. Because the array notation, using square brackets (
), is a postfix notation, the size of the inner nested array types is given after the outer type.
This declares that
dogis an array containing 5 elements. Each element is an array of 12
Arrays of pointers
Because the element type of an array is itself a C type, arrays of pointers can of course be constructed.
miceto be a 10 element array, where each element is a pointer to a
Pointers to arrays
The array name on its own evaluates to a pointer and can be passed around as such for many applications:
To declare a variable as being a pointer to an array, we must make use of parentheses. This is because in C brackets (  ) have higher precedence than the asterisk (*). So if we wish to declare a pointer to an array, we need to supply parentheses to override this:
This declares that
elephantis a pointer, and the type it points at is an array of 20
To declare a pointer to an array of pointers, simply combine the notations.
A function is an example of a
derived type. The type of each parameter to a function is ordinarily specified, although strictly speaking it is not required for most functions. Specifying the name of each parameter is optional in a function declaration without a function body. The following declarations are equivalent:
While both forms are syntactically correct, it is usually considered bad form to omit the names of the parameters when writing function declarations in
header files. These names can provide valuable clues to readers of such files, as to their meaning and operation.
Functions can take and return pointer types using the usual notation for a pointer:
The special type
voidis useful for declaring functions which do not take any parameters at all:
This is quite different from the empty set of parentheses used in C to declare a function without information on its parameter types:
This declaration declares a function called
umpirewhich returns a
double, but says nothing about the parameters the function takes. (In
C++, however, this declaration means that
umpiretakes no parameters, the same as the declaration that uses
In C, functions cannot directly take other functions as parameters, or return functions as results. However, they can take or return pointers to them. To declare that a function take a function pointer as an argument, use the standard notation as given above:
Here, we have a function which takes two arguments. Its first argument,
p1, is a plain
char. Its second argument,
p2is a pointer to a function. This pointed-to function should be given no arguments, and will return an
As a special case, C implementations treat function parameters declared with a function type as pointer-to-function types. Thus, the following declaration and the preceding declaration are equivalent:
To declare a function returning a function pointer (a so-called functional) again requires parentheses, to properly apply the function markings:
As there are two sets of argument lists, this declaration should be read carefully, as it is quite subtle. Here, we are defining a function called
boundary. This function takes two integer parameters,
width, and returns a function pointer. The returned pointer points at a function that itself takes two integer parameters,
y, and returns a
This type of marking can be arbitrarily extended, to make functions that return pointers to functions that return pointers to functions, and so on, but it quickly gets very unreadable, and prone to bugs. Use of a
typedefimproves readability, as shown by the following declarations that are equivalent to the previous declaration:
Wikimedia Foundation. 2010.
Look at other dictionaries:
Comparison of Pascal and C — Programming language comparisons General comparison Basic syntax Basic instructions Arrays Associative arrays String operations … Wikipedia
Comparison of Object Pascal and C — Programming language comparisons General comparison Basic syntax Basic instructions Arrays Associative arrays String operations … Wikipedia
Compatibility of C and C++ — Programming language comparisons General comparison Basic syntax Basic instructions Arrays Associative arrays String operations … Wikipedia
C data types — C Standard Library Data types Character classification Strings Mathematics File input/output Date/time Memory allocation … Wikipedia
Operators in C and C++ — This is a list of operators in the C and C++ programming languages. All the operators listed exist in C++; the fourth column Included in C , dictates whether an operator is also present in C. Note that C does not support operator overloading.… … Wikipedia
Comparison of C Sharp and Java — The correct title of this article is Comparison of C# and Java. The substitution or omission of the # sign is because of technical restrictions. Programming language comparisons General comparison Basic syntax Basic instructions … Wikipedia
Comparison of Java and C++ — Programming language comparisons General comparison Basic syntax Basic instructions Arrays Associative arrays String operations … Wikipedia
C++ structures and classes — The C++ programming language allows programmers to define program specific datatypes through the use of structures and classes. Instances of these datatypes are known as objects and can contain member variables, constants, member functions, and… … Wikipedia
Comparison of ALGOL 68 and C++ — Programming language comparisons General comparison Basic syntax Basic instructions Arrays Associative arrays String operations … Wikipedia
Comparison of C Sharp and Visual Basic .NET — The correct title of this article is Comparison of C# and Visual Basic .NET. The substitution or omission of the # sign is because of technical restrictions. Programming language comparisons General comparison Basic syntax Basic instructions … Wikipedia