1. | Welcome | ToC | FAQ
| Resources | Courses
| Projects | Mail
Lists | Members | Misc |
2. | Fundamentals | Languages | Tools
| Net | Core
| Advanced |
3. | EoC | Java |
4. | Lessons |
5. | 01 | 02 | 03
| 04 | 05 | 06 | 07 | 08
| 09 | 10 | 11 |
There are five basic data types in C. These are:
| Data Type | Keyword | Size |
|---|---|---|
| character | char | Generally one byte |
| integer | int | Generally four bytes |
| floating point | float | Generally four bytes |
| double floating point | double | Generally eight bytes |
| valueless | void |
The type void either explicitly declares a function as returning no value or creates generic pointers.
The first four basic data type keywords may be preceded by modifiers. The four modifiers are:
| Modifier | Applied To |
|---|---|
| long | int and double |
| short | int |
| signed | char and int |
| unsigned | char and int |
The use of signed on integers is redundant.
Sign Bits. In general, negative numbers are represented using two's complement, which reverses all bits in the number except the sign bit. If the sign bit is zero, the number is positive.
ANSI calls the names of variables, functions, labels and various other user-defined objects identifiers. The additional term external names refers to function names and global variables shared between files.
Significant Characters. If an identifier is not used in an external link process, the first 31 characters are significant, otherwise (in ANSI) at least the first six will be significant.
In C, upper and lowercase are treated as distinct. Hence count, Count, and COUNT are three separate identifiers.
Variables are declared in three basic places:
Local variables are not "known" outside the code
block in which they are declared. (A code block is a block of code beginning
and terminating with curly braces.) They are created only when the code
block in which they are declared is entered and are destroyed upon exit
from that block. For this reason, they cannot retain their values between
calls to that code block. (However, as will be seen, the compiler may be
directed to retain their values through the use of the static
storage class specifier (see below).)
Unless otherwise specified, local variables are stored in the stack.
Initialization. Local variables may be initialized with some known value, which will be assigned to the variable each time the block of code in which they are declared is entered.
The keyword auto is virtually never used since
all non-global variables are, by default, assumed to be auto.
The variables which accept the values passed to a function are called formal parameters. Formal parameters behave like any other local variables. As with local variables, assignments may be made to formal parameters.
Function Prototypes. The ANSI standard provides for function prototypes which help verify that the arguments used to call the function are compatible with its formal parameters.
Global variables are "known" by the whole program and hold their value throughout program execution. They are created by being declared outside of any function.
If a global and local variable share the same name, the local variable holds sway inside the function in which it is declared and the global variable will not be affected.
Global variables are stored in a fixed region of memory set aside by the compiler. They should be used only where necessary because, apart from memory considerations, unnecessary use of global variables is inconsistent with the main characteristic of structured languages, namely, the compartmentalization of code and data.
Storage class specifiers, of which there are four in C, tell the compiler how to store the subsequent variable. One of these specifiers (auto) is virtually never used since, as previously stated, all non-global variables are, by default, assumed to be auto. The remaining three specifiers are as follows:
externBecause C allows separately compiled modules, and because a global variable must be declared in only one of those files, there must be some way of telling all the files about the existence of that global variable. The extern specifier tells the compiler that the variables that follow have been declared in another module. When the linker links the two modules, all references to the external variables are resolved.
staticstatic are not "known"outside their function or file; however, they differ from normal variables variables in that they maintain their value between calls. The effect of static differs depending on whether it is applied to a local variable or a global variable:
static specifier is applied to a local
variable, the compiler creates permanent storage for it, as it does for
global variables. The difference is that a static local variable is still
"known" only to the code block in which it is declared. Prior to the ANSI standard, the register specifier only applied to types int and char. It caused the value of the variable to be kept in a CPU register rather than in memory, meaning that operations on the variable would be much faster. ANSI broadened the definition of register so that it may now be applied to any variable. In addition, ANSI simply states that "access to the object be as fast as possible". In practice, char and int variables are still stored in CPU registers, whereas larger objects like arrays (which cannot, of course, be stored in registers) may still receive preferential treatment.
The register specifier may only be applied to local variables and formal parameters. register variables are ideal for loop control and other places where many references will be made to the same variable.
The compiler automatically transforms register variables into non-register variables when the limit is reached.
Because register variables do not have addresses, the & operator cannot be used on them as it can with variables located in memory.
The ANSI standard introduced two new type modifiers. These modifiers (const and volatile) control how variables may be accessed or modified. Usage is as follows:
Variables of type const may be given an initial value; however, that value cannot be changed by the program. Such a variable receives its value from explicit initialization or by some hardware-dependent means.
Many functions in the C standard library use const in their parameter declaration.
const Pointers. As will be seen, functions can modify a variable pointed to by a pointer. However, if the pointer is specified as const in the formal parameter declaration, the function's code will not be able to modify what it points to.
The value of variables of type volatile may be changed in ways not explicitly specified in the program (eg, a variable used to hold the real time of the system). The contents of the variable are altered without any explicit assignment statements.
In C, constants refer to fixed values which the program may not alter, and which can be any of the basic data types.
Character constants are enclosed between single quotes, eg, 'a'.
The use of scientific notation for floating point numbers is allowed.
Specific types of numeric constants may be specified by using suffixes. F and L following a floating point type cause the number to be treated as, respectively, a float and a long double. U and L following an integer type cause the number to be treated as, respectively, an unsigned and a long.
Hexadecimal constants begin with an 0x. Octal constants begin with a 0.
C allows the definition ofstring constants even though it does not formally have a string data type. A string is a set of characters, or a character, enclosed in double quotes.
Backslash Character Constants. Some characters, however, cannot be entered into a string from the keyboard. For this reason, C includes the following special "backslash" characters:
| Chara | Meaning |
|---|---|
| \b | Backspace |
| \0 | Null |
| \f | Form feed |
| \\ | Backslash |
| \n | New line |
| \v | Vertical tab |
| \r | Carriage return |
| \a | Alert |
| \t | Horizontal tab |
| \N | Octal constant |
| \" | Double quote |
| \xN | Hexadecimal constant |
| \' | Single quote |
C is very rich in operators and defines four classes, viz, arithmetic, relational, logical and bitwise.
The assignment operator is a single equals sign (=).
The main arithmetic operators are:
+ - * / %
The modulus operator (%) cannot be used on floating-point types. The unary minus multiplies its single operand by -1, i.e., any number preceded by a minus sign switches its sign.
Two additional operators (the increment and decrement operators) are available. These are:
++ --
++ and -- produce faster code for increment and decrement operations. As an example of usage, ++x is the same as x = x + 1 and --x is the same as x = x - 1. ++x can also be written as x++. When the operator follows the operand in this way, C uses the value of the operand before incrementing (or decrementing) it. On the other hand, if the operator precedes the operand in an expression, C performs the operation before using the value of the operand. For example:
x = 10; y = ++x;
sets y to 11. However, if the operand had preceded the operator (i.e., x++), y is set to 10. Either way, x is set to 11.
The relational and logical operators are as follows:
| Operator | Meaning |
|---|---|
| > | Greater than |
| >= | Greater than or equal to |
| < | Less than |
| <= | Less than or equal to |
| == | Equal |
| != | Not equal |
| && | logical AND |
| || | logical OR |
| ! | logical NOT |
The idea of true and false underlies the concepts of relational and logical operators. In C, true is any value other than zero and false is zero. All relational and logical operations produce a result of either 1 or 0.
Although C does not contain an exclusive OR (XOR) operator, a function can easily be created to perform that task.
Since C was designed to take the place of assembly language for most programming tasks, it needed to be able to support assembler-like operations. Bitwise operations refer to testing, setting or shifting the actual bits in a byte or word (byte and word corresponding to the types char and int and their variants). C's bitwise operators are:
| Operator | Meaning |
|---|---|
| & | AND |
| | | OR |
| >> | Shift right |
| << | Shift left |
| ^ | Exclusive OR |
| ~ | One's complement |
The following is an example of a binary number representing 100 decimal:
0 1 1 0 0 1 0 0 0 64 32 16 8 4 2 1 64 + 32 + 4 =100
Negative numbers are handled somewhat differently. Most computers choose to represent such numbers using two's complement notation. Using such notation, the left-most bit represents the sign bit. 1 means negative and 0 means positive. The remaining bits represent the value of the number. In two's complement notation, the value -1 is represented by:
1 1 1 1 1 1 1 1
A convenient way to convert a negative decimal number to binary is to add 1 to the value, express the absolute value in binary, then complement all the bits. For example, to convert -5 to binary:
add 1: -4 result in binary: 0 0 0 0 0 1 0 0 complement: 1 1 1 1 1 0 1 1
To convert the binary number back to decimal:
complement: 0 0 0 0 0 1 0 0 convert to decimal: 4 change sign: -4 subtract 1: -5
Bitwise operators may be used on any integer value in C.
AND, OR, XOR, Shift Left and Shift Right bitwise operators take two operands; however, One's Complement is a unary operator and takes one argument only.
Bitwise ANDing is frequently used for "masking"operations, i.e., the operator may be used to set specific bits to zero. Any bit that is 0 in either operand causes the corresponding bit to be set to 0. For example, the following resets a parity bit to 0:
return (ch & 127);
Note that the number 127 has bit 8 set to 0. Here is what happens:
parity bit set parity bit unset 1 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1 ch 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 127 0 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1 result
Similarly, the bitwise OR may be used to set a bit. Any bit which is set to 1 in either operand causes the outcome to be set to 1. For example, the following is 128 | 3:
0 0 0 0 0 0 1 1 3 in binary 1 0 0 0 0 0 0 0 128 in binary 1 0 0 0 0 0 1 1 result
Exclusive OR (XOR) sets a bit only if the bits being compared are different. One interesting property of XOR is that any value XOR'd with itself produces 0. This is useful in assembly programming.
Swapping Values. An interesting application of XOR is that it can be used to exchange two values without the need for an extra memory location, e.g.:
a ^= b; b ^= a; a ^= b;
Shift operators move all bits left or right as specified. As bits are shifted off one end, zeroes are brought in at the other. A shift is not a rotate; the bits shifted off one end are lost.
Left shifting has the effect of multiplying the shifted value by two. For right shifts, what is shifted in on the left depends on the sign of the value being shifted and also on how the operation is implemented on the particular machine. If the sign is 0 (positive), then zeroes will be shifted in. If the sign is 1 (negative), on some machines 1s will be shifted in and on others, 0s. The former is known as an arithmetic right shift; the latter is known as a logical right shift.
C does not guarantee a defined result if a value is shifted by an amount greater or less than the number of bits in the data item.
The One's Complement operator reverses the state of each bit in the specified variable. Note that two complements in a row return the byte to its original value.
As with all binary arithmetic operators in C (see C Shorthand, below), the bitwise operators can be used as assignment operators by tacking on an equal sign. For example:
word &= 15;
would perform the same function as:
word = word & 15;
When using constants in bitwise operations it is usually more convenient to express the constants in hexadecimal.
When bitwise operations are performed between two values of different sizes, the system aligns the operands on the right.
If the shorter of the two items is a signed quantity, and the value is negative, then the sign is extended to the left to match the number of bits in the larger-sized value. So if the value is negative, 1s are filled in on the left; if positive, 0s are filled in.
If the smaller item is unsigned, it is filled in from the left with 0s.
The ternary operator ? replaces certain statements of the if-then-else form. In the following:
y = x >10 ? 100 : 200
the first expression is evaluated. If it evaluates to true, y is made equal to 100. If it evaluates to false, y is made equal to 200.
Preamble. A pointer is the memory address of a variable. A pointer variable is a variable specifically declared to hold a pointer. Pointers:
A pointer is of sufficient size to hold an address as defined by the architecture of the computer.
Pointer Operators. The following operators are used to manipulate pointers:
The & operator returns the memory address of its operand. For example:
m = &count;
places the address of count into m. & can be thought of as "address of".
The * operator is the complement of &. It returns the value of the variable at the address which follows it. For example, in the following extension of the preceding code fragment:
q = *count;
the value of count is placed in q. * can be thought of as "address".
sizeof is a unary compile time operator which returns the length, in bytes, of the variable or parenthesized type specifier that precedes it. Usage is illustrated in the following:
printf("%f", sizeof f); printf("%d", sizeof(int));
The comma operator may be used to string together several expressions. For example, in:
x - (y = 3, y + 1);
the left side of the comma operator is evaluated as void, which means that y is first assigned the value 3 and then x is assigned the value 4.
The . and -> operators reference individual elements in structures and unions. The . operator is used when working with the actual structure or union, e.g.:
employee.wage = 123.23;
The -> is used when working with a pointer to the structure or union, e.g.:
emp_ptr->wage = 123.23;
An expression can be forced to be of a particular type by using a cast. Casts are often considered to be operators. As an operator, casts are unary, and have the same precedence as other unary operators. An example of a cast which ensures that an expression evaluates to type float is as follows:
x = (float) x / 2;
In the following example, a fractional number is truncated to a whole number:
double x = 3.141592654; double y; y = (short) x; // resulting value of y is 3.0
In the following example, casting is used to round to the nearest integer:
double x, y; x = 4.67; y = (short) (x + 0.5); // resulting value of y is 5.0 x = 4.45; y = (short) (x +.05); // resulting value of y is 4.0
C has a special shorthand which simplifies the coding of certain assignments. For example:
x = x + 10; can be written as x += 10; x = x * 10; can be written as x *= 10;
Some further examples using the bitwise operators are as follows:
| Operator | Usage | Result in a After Operation |
|---|---|---|
| >>= | a >>= b | a shifted right by b bits |
| <<=< | a <<= b | a shifted left by b bits |
| &= | a &= b | a ANDed with b |
| ^= | a ^= b | a exclusive ORed with b |
| |= | a |= b | a ORed with b |
The following lists the precedence of all C operators:
() [] -> . ! ~ ++ -- -(type) * & sizeof * / % + - << >> < <= > >= == != & ^ | && || ? = += -= *= /= ,
In an assignment statement, the type conversion rule is that the value on the right side of the assignment is converted to the type on the left side. When converting from integers to characters, and from long integers to integers, the appropriate amount of high-order bits will be removed.
Type Conversion in Expressions. Operators, constants and variables are the constituents of expressions. An expression in C is any valid combination of these elements. When constants and variables of different types are mixed in an expression, they are converted to the same type. The compiler converts all operands up to the type of the largest operand, a process known as type promotion. This is done operation by operation.
The assignment of a value to many variables is possible using multiple assignment, eg:
x = y = z = 0;
![]()
Prior Chapter · Index · Next Chapter
Copyright
© 1996, 1997, 1998. Last Update to This Page:
1998/10/24
This Page Maintained by: radar
pangaean * * * Original Author: K.J.Bricknell
The MOST web site is built
and maintained by the voluntary efforts/donations of our members.