You can find nice HTML versions of C89, C99, and C11, as well as some of the official draft PDF files they're generated from, here: http://portnet/~nsz/c/. You can find nice HTML versions of C89, C99, and C11, as well as some of the official draft PDF files they're generated from, here. The older standards -- ANSI X (aka C89), ISO/IEC USD 65 for PDF and USD 82 for hard copy (printed).
|Language:||English, Spanish, Arabic|
|Distribution:||Free* [*Sign up for free]|
pdf searching through page speeded up. C90 was the first version of the C Standard, known as ISO/IEC (E) (Ritchie gives a. Publication as an International Standard requires approval by at least 75% of the national bodies casting a vote. 4. International Standard ISO/IEC was. ANSI C, ISO C and Standard C refer to the successive standards for the C programming to the original and best-supported version of the standard ( known as C89 or C90). Software .. Create a book · Download as PDF · Printable version.
If the first operand compares equal to 0, the second operand is not evaluated. The operator shall yield 1 if either of its operands compare unequal to 0, otherwise it yields 0. Unlike the bitwise operator, the operator guarantees left-to-right evaluation; there is a sequence point after the evaluation of the first operand.
If the first operand compares unequal to 0, the second operand is not evaluated. One of the following shall hold for the second and third operands: The first operand is evaluated; there is a sequence point after its evaluation. The second operand is evaluated only if the first compares unequal to 0; the third operand is evaluated only if the first compares equal to 0; the value of the second or third operand whichever is evaluated is the result.
If both the second and third operands have arithmetic type, the usual arithmetic conversions are performed to bring them to a common type and the result has that type. If both the operands have structure or union type, the result has that type. If both operands have void type, the result has void type.
If both the second and third operands are pointers or one is a null pointer constant and the other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers of the types pointed-to by both operands. Furthermore, if both operands are pointers to compatible types or differently qualified versions of a compatible type, the result has the composite type; if one operand is a null pointer constant, the result has the type of the other operand; otherwise, one operand is a pointer to void or a qualified version of void, in which case the other operand is converted to type pointer to void, and the result has that type.
An assignment operator shall have a modifiable lvalue as its left operand. An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue. The type of an assignment expression is the type of the left operand unless the left operand has qualified type, in which case it is the unqualified version of the type of the left operand.
The side effect of updating the stored value of the left operand shall occur between the previous and the next sequence point. One of the following shall hold: If the value being stored in an object is accessed from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have qualified or unqualified versions of a compatible type; otherwise the behavior is undefined.
Therefore, for full portability the variable c should be declared as int. For the other operators, each operand shall have arithmetic type consistent with those allowed by the corresponding binary operator.
The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its evaluation. Then the right operand is evaluated; the result has its type and value. As indicated by the syntax, in contexts where a comma is a punctuator in lists of arguments to functions and lists of initializers the comma operator as described in this section cannot appear.
On the other hand, it can be used within a parenthesized expression or within the second expression of a conditional operator in such contexts. In the function call. A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be. Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within the operand of a sizeof operator.
Each constant expression shall evaluate to a constant that is in the range of representable values for its type. An expression that evaluates to a constant is required in several contexts. An integral constant expression shall have integral type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions, and floating constants that are the immediate operands of casts.
Cast operators in an integral constant expression shall only convert arithmetic types to integral types, except as part of an operand to the sizeof operator. More latitude is permitted for constant expressions in initializers. Such a constant expression shall evaluate to one of the following: An arithmetic constant expression shall have arithmetic type and shall only have operands that are integer constants, floating constants, enumeration constants, character constants, and sizeof expressions.
Cast operators in an arithmetic constant expression shall only convert arithmetic types to arithmetic types, except as part of an operand to the sizeof operator.
The array-subscript  and member-access. The semantic rules for the evaluation of a constant expression are the same as for non-constant expressions. A declaration shall declare at least a declarator, a tag, or the members of an enumeration. If an identifier has no linkage, there shall be no more than one declaration of the identifier in a declarator or type specifier with the same scope and in the same name space, except for tags as specified in 3.
All declarations in the same scope that refer to the same object or function shall specify compatible types. A declaration specifies the interpretation and attributes of a set of identifiers. A declaration that also causes storage to be reserved for an object or function named by an identifier is a definition. The declaration specifiers consist of a sequence of specifiers that indicate the linkage, storage duration, and part of the type of the entities that the declarators denote. The init-declarator-list is a comma-separated sequence of declarators, each of which may have additional type information, or an initializer, or both.
The declarators contain the identifiers if any being declared. If an identifier for an object is declared with no linkage, the type for the object shall be complete by the end of its declarator, or by the end of its init-declarator if it has an initializer. At most one storage-class specifier may be given in the declaration specifiers in a declaration. A declaration of an identifier for an object with storage-class specifier register suggests that access to the object be as fast as possible.
The extent to which such suggestions are effective is implementation-defined. The declaration of an identifier for a function that has block scope shall have no explicit storage-class specifier other than extern.
Each list of type specifiers shall be one of the following sets; the type specifiers may occur in any order, possibly intermixed with the other declaration specifiers.
Specifiers for structures, unions, and enumerations are discussed in 3. Each of the above comma-separated lists designates the same type, except that for bit-field declarations, signed int or signed may differ from int or no type specifiers.
A structure or union shall not contain a member with incomplete or function type. Hence it shall not contain an instance of itself but may contain a pointer to an instance of itself. The expression that specifies the width of a bit-field shall be an integral constant expression that has nonnegative value that shall not exceed the number of bits in an ordinary object of compatible type.
If the value is zero, the declaration shall have no declarator. As discussed in 3. The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type, within a translation unit. The struct-declaration-list is a sequence of declarations for the members of the structure or union.
A member of a structure or union may have any object type. In addition, a member may be declared to consist of a specified number of bits including a sign bit, if any. Such a member is called a bit-field ; 50 its width is preceded by a colon. A bit-field may have type int , unsigned int , or signed int. A bit-field is interpreted as an integral type consisting of the specified number of bits. An implementation may allocate any addressable storage unit large enough to hold a bit-field.
If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined.
The order of allocation of bit-fields within a unit high-order to low-order or low-order to high-order is implementation-defined. The alignment of the addressable storage unit is unspecified.
A bit-field declaration with no declarator, but only a colon and a width, indicates an unnamed bit-field. Each non-bit-field member of a structure or union object is aligned in an implementation-defined manner appropriate to its type. Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared.
A pointer to a structure object, suitably cast, points to its initial member or if that member is a bit-field, then to the unit in which it resides , and vice versa. There may therefore be unnamed holes within a structure object, but not at its beginning, as necessary to achieve the appropriate alignment. The size of a union is sufficient to contain the largest of its members. The value of at most one of the members can be stored in a union object at any time.
A pointer to a union object, suitably cast, points to each of its members or if a member is a bit-field, then to the unit in which it resides , and vice versa.
There may also be unnamed padding at the end of a structure or union, as necessary to achieve the appropriate alignment were the structure or union to be a member of an array. The expression that defines the value of an enumeration constant shall be an integral constant expression that has a value representable as an int.
The identifiers in an enumerator list are declared as constants that have type int and may appear wherever such are permitted. A combination of both forms of enumerators may produce enumeration constants with values that duplicate other values in the same enumeration.
The enumerators of an enumeration are also known as its members. Each enumerated type shall be compatible with an integer type; the choice of type is implementation-defined. The list defines the structure content ,union content ,or enumeration content.
If this declaration of the tag is visible, a subsequent declaration that uses the tag and that omits the bracketed list specifies the declared structure, union, or enumerated type. Subsequent declarations in the same scope shall omit the bracketed list. A declaration of the form. It specifies a new type distinct from any type with the same tag in an enclosing scope if any. This mechanism allows declaration of a self-referential structure.
Once this declaration has been given, the declaration. The following alternative formulation uses the typedef mechanism: To illustrate the use of prior declaration of a tag to specify a pair of mutually-referential structures, the declarations.
Note, however, that if s2 were already declared as a tag in an enclosing scope, the declaration D1 would refer to it, not to the tag s2 declared in D2. To eliminate this context sensitivity, the otherwise vacuous declaration. This declares a new tag s2 in the inner scope; the declaration D2 then completes the specification of the new type.
The same type qualifier shall not appear more than once in the same specifier list or qualifier list, either directly or via one or more typedef s. The properties associated with qualified types are meaningful only for expressions that are lvalues. If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.
An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 2. If the specification of an array type includes any type qualifiers, the element type is so-qualified, not the array type.
If the specification of a function type includes any type qualifiers, the behavior is undefined. For two qualified types to be compatible, both shall have the identically qualified version of a compatible type; the order of type qualifiers within a list of specifiers or qualifiers does not affect the specified type.
The following declarations and expressions illustrate the behavior when type qualifiers modify an aggregate type: Each declarator declares one identifier, and asserts that when an operand of the same form as the declarator appears in an expression, it designates a function or object with the scope, storage duration, and type indicated by the declaration specifiers. The type specified for the identifier ident in the various forms of declarator is described inductively using this notation.
The implementation shall allow the specification of types that have at least 12 pointer, array, and function declarators in any valid combinations modifying an arithmetic, a structure, a union, or an incomplete type, either directly or via one or more typedef s. For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.
The expression that specifies the size of an array shall be an integral constant expression that has a value greater than zero. For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, they shall have the same value. The first declares x to be a pointer to int ; the second declares y to be an array of int of unspecified size an incomplete type , the storage for which is defined elsewhere.
A function declarator shall not specify a return type that is a function type or an array type. The only storage-class specifier that shall occur in a parameter declaration is register. An identifier list in a function declarator that is not part of a function definition shall be empty. A parameter type list specifies the types of, and may declare identifiers for, the parameters of the function.
If the list terminates with an ellipsis , In a parameter declaration, a single typedef name in parentheses is taken to be an abstract declarator that specifies a function with a single parameter, not as redundant parentheses around the identifier for a declarator. The storage-class specifier in the declaration specifiers for a parameter declaration, if present, is ignored unless the declared parameter is one of the members of the parameter type list for a function definition.
An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a function definition specifies that the function has no parameters. The empty list in a function declarator that is not part of a function definition specifies that no information about the number or types of the parameters is supplied.
For two function types to be compatible, both shall specify compatible return types. If one type has a parameter type list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, the parameter list shall not have an ellipsis terminator and the type of each parameter shall be compatible with the type that results from the application of the default argument promotions. If one type has a parameter type list and the other type is specified by a function definition that contains a possibly empty identifier list, both shall agree in the number of parameters, and the type of each prototype parameter shall be compatible with the type that results from the application of the default argument promotions to the type of the corresponding identifier.
For each parameter declared with function or array type, its type for these comparisons is the one that results from conversion to a pointer type, as in 3.
It is especially useful to compare the last two. If the declaration occurs outside of any function, the identifiers have file scope and external linkage. If the declaration occurs inside a function, the identifiers of the functions f and fip have block scope and external linkage, and the identifier of the pointer pfi has block scope and no linkage.
Each of these functions has two parameters that are pointers to int. The identifiers x and y are declared for descriptive purposes only and go out of scope at the end of the declaration of apfi. The declaration. The function fpfi has two parameters: The pointer returned by fpfi points to a function that has at least one parameter, which has type int. In several contexts it is desired to specify a type.
This is accomplished using a type name, which is syntactically a declaration for a function or an object of that type that omits the identifier. In a declaration whose storage-class specifier is typedef , each declarator defines an identifier to be a typedef name that specifies the type specified for the identifier in the way described in 3.
That is, in the following declarations: A typedef name shares the same name space as other identifiers declared in ordinary declarators. If the identifier is redeclared in an inner scope or is declared as a member of a structure or union in the same or an inner scope, the type specifiers shall not be omitted in the inner declaration.
The object distance has a type compatible with any other int object. Type t1 is also compatible with type struct s1 , but not compatible with the types struct s2 , t2 , the type pointed to by tp2 , and int. The choice of range is implementation-defined. If these declarations are followed in an inner scope by. There shall be no more initializers in an initializer list than there are objects to be initialized.
The type of the entity to be initialized shall be an object type or an array of unknown size. All the expressions in an initializer for an object that has static storage duration or in an initializer list for an object that has aggregate or union type shall be constant expressions.
If the declaration of an identifier has block scope, and the identifier has external or internal linkage, there shall be no initializer for the identifier. An initializer specifies the initial value stored in an object. All unnamed structure or union members are ignored during initialization. If an object that has static storage duration is not initialized explicitly, it is initialized implicitly as if every member that has arithmetic type were assigned 0 and every member that has pointer type were assigned a null pointer constant.
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. The initializer for a scalar shall be a single expression, optionally enclosed in braces.
The initial value of the object is that of the expression; the same type constraints and conversions as for simple assignment apply. A brace-enclosed initializer for a union object initializes the member that appears first in the declaration list of the union type.
The initializer for a structure or union object that has automatic storage duration either shall be an initializer list as described below, or shall be a single expression that has compatible structure or union type.
In the latter case, the initial value of the object is that of the expression. The rest of this section deals with initializers for objects that have aggregate or union type. An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal including the terminating null character if there is room or if the array is of unknown size initialize the members of the array. Successive codes of the wide string literal including the terminating zero-valued code if there is room or if the array is of unknown size initialize the members of the array.
Otherwise, the initializer for an object that has aggregate type shall be a brace-enclosed list of initializers for the members of the aggregate, written in increasing subscript or member order; and the initializer for an object that has union type shall be a brace-enclosed initializer for the first member of the union. If the aggregate contains members that are aggregates or unions, or if the first member of a union is an aggregate or union, the rules apply recursively to the subaggregates or contained unions.
If the initializer of a subaggregate or contained union begins with a left brace, the initializers enclosed by that brace and its matching right brace initialize the members of the subaggregate or the first member of the contained union. Otherwise, only enough initializers from the list are taken to account for the members of the first subaggregate or the first member of the contained union; any remaining initializers are left to initialize the next member of the aggregate of which the current subaggregate or contained union is a part.
If there are fewer initializers in a list than there are members of an aggregate, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration. If an array of unknown size is initialized, its size is determined by the number of initializers provided for its members. At the end of its initializer list, the array no longer has incomplete type.
Likewise the next two lines initialize y and y. The initializer ends early, so y is initialized with zeros. Precisely the same effect could have been achieved by.
The initializer for y does not begin with a left brace, so three items from the list are used. Likewise the next three are taken successively for y and y.
It defines an array with two member structures: It defines a three-dimensional array object: The initializer for q does not begin with a left brace, so up to six items from the current list may be used. There is only one, so the values for the remaining five members are initialized with zero.
Likewise, the initializers for q and q do not begin with a left brace, so each uses up to six items, initializing their respective two-dimensional subaggregates. If there had been more than six items in any of the lists, a diagnostic message would occur.
The same initialization result could have been achieved by: Note that the fully-bracketed and minimally-bracketed forms of initialization are, in general, less likely to cause confusion. This declaration is identical to. The contents of the arrays are modifiable. On the other hand, the declaration. If an attempt is made to use p to modify the contents of the array, the behavior is undefined. A statement specifies an action to be performed. Except as indicated, statements are executed in sequence.
A full expression is an expression that is not part of another expression. Each of the following is a full expression: The end of a full expression is a sequence point. A case or default label shall appear only in a switch statement.
Further constraints on such labels are discussed under the switch statement. Any statement may be preceded by a prefix that declares an identifier as a label name.
Labels in themselves do not alter the flow of control, which continues unimpeded across them. A compound statement also called a block allows a set of statements to be grouped into one syntactic unit, which may have its own set of declarations and initializations as discussed in 3. The initializers of objects that have automatic storage duration are evaluated and the values are stored in the objects in the order their declarators appear in the translation unit.
The expression in an expression statement is evaluated as a void expression for its side effects. A null statement consisting of just a semicolon performs no operations. If a function call is evaluated as an expression statement for its side effects only, the discarding of its value may be made explicit by converting the expression to a void expression by means of a cast: A selection statement selects among a set of statements depending on the value of a controlling expression.
The controlling expression of an if statement shall have scalar type. In both forms, the first substatement is executed if the expression compares unequal to 0.
In the else form, the second substatement is executed if the expression compares equal to 0. If the first substatement is reached via a label, the second substatement is not executed. An else is associated with the lexically immediately preceding else -less if that is in the same block but not in an enclosed block.
The controlling expression of a switch statement shall have integral type. The expression of each case label shall be an integral constant expression.
No two of the case constant expressions in the same switch statement shall have the same value after conversion. There may be at most one default label in a switch statement.
Any enclosed switch statement may have a default label or case constant expressions with values that duplicate case constant expressions in the enclosing switch statement. A switch statement causes control to jump to, into, or past the statement that is the switch body, depending on the value of a controlling expression, and on the presence of a default label and the values of any case labels on or in the switch body.
A case or default label is accessible only within the closest enclosing switch statement. The integral promotions are performed on the controlling expression. The constant expression in each case label is converted to the promoted type of the controlling expression.
If a converted value matches that of the promoted controlling expression, control jumps to the statement following the matched case label. Otherwise, if there is a default label, control jumps to the labeled statement. If no converted case constant expression matches and there is no default label, no part of the switch body is executed. As discussed previously 2. The controlling expression of an iteration statement shall have scalar type. An iteration statement causes a statement called the loop body to be executed repeatedly until the controlling expression compares equal to 0.
The evaluation of the controlling expression takes place before each execution of the loop body. The evaluation of the controlling expression takes place after each execution of the loop body. Except for the behavior of a continue statement in the loop body, the statement. Both expression-1 and expression-3 may be omitted. Each is evaluated as a void expression. An omitted expression-2 is replaced by a nonzero constant. A jump statement causes an unconditional jump to another place.
The identifier in a goto statement shall name a label located somewhere in the current function. A goto statement causes an unconditional jump to the statement prefixed by the named label in the current function.
A continue statement shall appear only in or as a loop body. A continue statement causes a jump to the loop-continuation portion of the smallest enclosing iteration statement; that is, to the end of the loop body.
More precisely, in each of the statements. A break statement shall appear only in or as a switch body or loop body. A break statement terminates execution of the smallest enclosing switch or iteration statement.
A return statement with an expression shall not appear in a function whose return type is void. A return statement terminates execution of the current function and returns control to its caller. A function may have any number of return statements, with and without expressions. If a return statement with an expression is executed, the value of the expression is returned to the caller as the value of the function call expression.
If the expression has a type different from that of the function in which it appears, it is converted as if it were assigned to an object of that type. If a return statement without an expression is executed, and the value of the function call is used by the caller, the behavior is undefined. The storage-class specifiers auto and register shall not appear in the declaration specifiers in an external declaration.
There shall be no more than one external definition for each identifier declared with internal linkage in a translation unit. Moreover, if an identifier declared with internal linkage is used in an expression other than as a part of the operand of a sizeof operator , there shall be exactly one external definition for the identifier in the translation unit.
As discussed in 2. An external definition is an external declaration that is also a definition of a function or an object. If an identifier declared with external linkage is used in an expression other than as part of the operand of a sizeof operator , somewhere in the entire program there shall be exactly one external definition for the identifier. The identifier declared in a function definition which is the name of the function shall have a function type, as specified by the declarator portion of the function definition.
The return type of a function shall be void or an object type other than array. The storage-class specifier, if any, in the declaration specifiers shall be either extern or static. If the declarator includes a parameter type list, the declaration of each parameter shall include an identifier except for the special case of a parameter list consisting of a single parameter of type void, in which there shall not be an identifier. No declaration list shall follow.
If the declarator includes an identifier list, only the identifiers it names shall be declared in the declaration list. An identifier declared as a typedef name shall not be redeclared as a parameter. The declarations in the declaration list shall contain no storage-class specifier other than register and no initializations. The declarator in a function definition specifies the name of the function being defined and the identifiers of its parameters. If the declarator includes a parameter type list, the list also specifies the types of all the parameters; such a declarator also serves as a function prototype for later calls to the same function in the same translation unit.
If the declarator includes an identifier list, 71 the types of the parameters may be declared in a following declaration list. Any parameter that is not declared has type int. If a function that accepts a variable number of arguments is defined without a parameter type list that ends with the ellipsis notation, the behavior is undefined. On entry to the function the value of each argument expression shall be converted to the type of its corresponding parameter, as if by assignment to the parameter.
Array expressions and function designators as arguments are converted to pointers before the call. Each parameter has automatic storage duration. Its identifier is an lvalue. Here extern is the storage-class specifier and int is the type specifier each of which may be omitted as those are the defaults ; max int a, int b is the function declarator; and. The following similar definition uses the identifier-list form for the parameter declarations: Here int a, b; is the declaration list for the parameters, which may be omitted because those are the defaults.
The difference between these two definitions is that the first form acts as a prototype declaration that forces conversion of the arguments of subsequent calls to the function, whereas the second form may not.
Note that f must be declared explicitly in the calling function, as its appearance in the expression g f was not followed by. Then the definition of g might read. If the declaration of an identifier for an object has file scope and an initializer, the declaration is an external definition for the identifier.
A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static , constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.
If the declaration of an identifier for an object is a tentative definition and has internal linkage, the declared type shall not be an incomplete type. A preprocessing directive consists of a sequence of preprocessing tokens that begins with a preprocessing token that is either the first character in the source file optionally after white space containing no new-line characters or that follows white space containing at least one new-line character, and is ended by the next new-line character.
The only white-space characters that shall appear between preprocessing tokens within a preprocessing directive from just after the introducing preprocessing token through just before the terminating new-line character are space and horizontal-tab including spaces that have replaced comments in translation phase 3. The implementation can process and skip sections of source files conditionally, include other source files, and replace macros.
These capabilities are called preprocessing , because conceptually they occur before translation of the resulting translation unit. The preprocessing tokens within a preprocessing directive are not subject to macro expansion unless otherwise stated.
The expression that controls conditional inclusion shall be an integral constant expression except that: Each preprocessing token that remains after all macro replacements have occurred shall be in the lexical form of a token. You can download the standard from ISO.
Only the draft versions are freely available. IS this one illegal? The reason for which this question was closed is invalid. It is not asking for a tool, library, or "favorite" off-site resource but for canonical specification of the language in question.
Sep 22 '16 at COrNotToC 22 9. All the C documents there are drafts, not actual standards. Yes, I mentioned that, albeit with some ambiguous language, in the answer, but the latest drafts are generally identical to the published standards except for cover page and such.
Aug 23 '13 at Is this legal? Pacerier, why will this be not legal? Thanks for sharing the draft standard links. I like the fact that they are linked html files: Their web-store link for C89 is here: Note the Abstract given on that page: Once you have the standard, then all amendments and technical corrigenda can be found here, for free: The first link appears to be dead for me.
September 19, 4 Comments In this article we will study about various C standards that specified after its development in Bell Labs. This article will cover standards specifications, technical details, features etc. In the previous article we studied C language introduction if you are new to programming we recommend you to study it first.
Read Here. These included: void functions i. Functions returning struct or union types rather than pointers. Assignment for struct data types and Enumerated types.