C syntax
![]() The syntax of the C programming language is the set of rules governing writing of software in C. It is designed to allow for programs that are extremely terse, have a close relationship with the resulting object code, and yet provide relatively high-level data abstraction. C was the first widely successful high-level language for portable operating-system development. C syntax makes use of the maximal munch principle. Data structuresPrimitive data typesThe C programming language represents numbers in three forms: integral, real and complex. This distinction reflects similar distinctions in the instruction set architecture of most central processing units. Integral data types store numbers in the set of integers, while real and complex numbers represent numbers (or pair of numbers) in the set of real numbers in floating-point form. All C integer types have Integer typesC's integer types come in different fixed sizes, capable of representing various ranges of numbers. The type 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).
The 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 In addition to the standard integer types, there may be other "extended" integer types, which can be used for Integer constants may be specified in source code in several ways. Numeric values can be specified as decimal (example: Enumerated typeThe enumerated type in C, specified with the 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 An enumerated type is declared with the enum colors { RED, GREEN, BLUE = 5, YELLOW } paint_color;
This declares the Floating-point typesA 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 three more decimal types): single precision (
Floating-point constants may be written in decimal notation, e.g. The standard header file C23 introduces three additional decimal (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 since IBM System z10), can use the explicitly decimal types.
Storage class specifiersEvery object has a storage class.[citation needed] 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).[citation needed]
Variables declared within a block by default have automatic storage, as do those explicitly declared with the 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 The The 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). Type qualifiersTypes can be qualified to indicate special properties of their data. The type qualifier Incomplete typesAn incomplete type is a structure or union type whose members have not yet been specified, an array type whose dimension has not yet been specified, or the They are often used with pointers, either as forward or external declarations. For instance, code could declare an incomplete type like this: struct thing *pt;
This declares struct thing {
int num;
}; /* thing struct type is now completed */
Incomplete types are used to implement recursive structures; the body of the type declaration may be deferred to later in the translation unit: typedef struct Bert Bert;
typedef struct Wilma Wilma;
struct Bert {
Wilma *wilma;
};
struct Wilma {
Bert *bert;
};
Incomplete types are also used for data hiding; the incomplete type is defined in a header file, and the body only within the relevant source file. PointersIn declarations the asterisk modifier ( int *ptr;
ReferencingWhen a non-static pointer is declared, it has an unspecified value associated with it. The address associated with such a pointer must be changed by assignment prior to using it. In the following example, ptr is set so that it points to the data associated with the variable a: int a = 0;
int *ptr = &a;
In order to accomplish this, the "address-of" operator (unary DereferencingThe pointed-to data can be accessed through a pointer value. In the following example, the integer variable b is set to the value of integer variable a, which is 10: int a=10;
int *p;
p = &a;
int b = *p;
In order to accomplish that task, the unary dereference operator, denoted by an asterisk (*), is used. It returns the data to which its operand—which must be of pointer type—points. Thus, the expression *p denotes the same value as a. Dereferencing a null pointer is illegal. ArraysArray definitionArrays are used in C to represent structures of consecutive elements of the same type. The definition of a (fixed-size) array has the following syntax: int array[100];
which defines an array named array to hold 100 values of the primitive type int (*ptr_to_array)[100] = &array;
Accessing elementsThe primary facility for accessing the values of the elements of an array is the array subscript operator. To access the i-indexed element of array, the syntax would be Array subscript numbering begins at 0 (see Zero-based indexing). The largest allowed array subscript is therefore equal to the number of elements in the array minus 1. To illustrate this, consider an array a declared as having 10 elements; the first element would be C provides no facility for automatic bounds checking for array usage. Though logically the last subscript in an array of 10 elements would be 9, subscripts 10, 11, and so forth could accidentally be specified, with undefined results. Due to arrays and pointers being interchangeable, the addresses of each of the array elements can be expressed in equivalent pointer arithmetic. The following table illustrates both methods for the existing array:
Since the expression Variable-length arraysC99 standardised variable-length arrays (VLAs) within block scope. Such array variables are allocated based on the value of an integer value at runtime upon entry to a block, and are deallocated at the end of the block.[3] As of C11 this feature is no longer required to be implemented by the compiler. int n = ...;
int a[n];
a[3] = 10;
This syntax produces an array whose size is fixed until the end of the block. Dynamic arraysArrays that can be resized dynamically can be produced with the help of the C standard library. The #include <stdlib.h> /* declares malloc */
...
int *a = malloc(n * sizeof *a);
a[3] = 10;
The result is a "pointer to When the dynamically allocated memory is no longer needed, it should be released back to the run-time system. This is done with a call to the As a security measure, some programmers [who?] then set the pointer variable to free(a);
a = NULL;
This ensures that further attempts to dereference the pointer, on most systems, will crash the program. If this is not done, the variable becomes a dangling pointer which can lead to a use-after-free bug. However, if the pointer is a local variable, setting it to Recalling the array example, one could also create a fixed-size array through dynamic allocation: int (*a)[100] = malloc(sizeof *a);
...Which yields a pointer-to-array. Accessing the pointer-to-array can be done in two ways: (*a)[index];
index[*a];
Iterating can also be done in two ways: for (int i = 0; i < 100; i++)
(*a)[i];
for (int *i = a[0]; i < a[1]; i++)
*i;
The benefit to using the second example is that the numeric limit of the first example isn't required, which means that the pointer-to-array could be of any size and the second example can execute without any modifications. Multidimensional arraysIn addition, C supports arrays of multiple dimensions, which are stored in row-major order. Technically, C multidimensional arrays are just one-dimensional arrays whose elements are arrays. The syntax for declaring multidimensional arrays is as follows: int array2d[ROWS][COLUMNS];
where ROWS and COLUMNS are constants. This defines a two-dimensional array. Reading the subscripts from left to right, array2d is an array of length ROWS, each element of which is an array of COLUMNS integers. To access an integer element in this multidimensional array, one would use array2d[4][3]
Again, reading from left to right, this accesses the 5th row, and the 4th element in that row. The expression
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 an Iliffe vector or sometimes an array 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. The latter can be created by multiple uses of StringsIn C, string literals are surrounded by double quotes ( String literals may not contain embedded newlines; this proscription somewhat simplifies parsing of the language. To include a newline in a string, the backslash escape There are several standard library functions for operating with string data (not necessarily constant) organized as array of C's string-literal syntax has been very influential, and has made its way into many other languages, such as C++, Objective-C, Perl, Python, PHP, Java, JavaScript, C#, and Ruby. Nowadays, almost all new languages adopt or build upon C-style string syntax. Languages that lack this syntax tend to precede C. Backslash escapesBecause certain characters cannot be part of a literal string expression directly, they are instead identified by an escape sequence starting with a backslash ( Backslashes may be used to enter various control characters, etc., into a string:
The use of other backslash escapes is not defined by the C standard, although compiler vendors often provide additional escape codes as language extensions. One of these is the escape sequence Note that printf format strings use String literal concatenationC has string literal concatenation, meaning that adjacent string literals are concatenated at compile time; this allows long strings to be split over multiple lines, and also allows string literals resulting from C preprocessor defines and macros to be appended to strings at compile time: printf(__FILE__ ": %d: Hello "
"world\n", __LINE__);
will expand to printf("helloworld.c" ": %d: Hello "
"world\n", 10);
which is syntactically equivalent to printf("helloworld.c: %d: Hello world\n", 10);
Character constantsIndividual character constants are single-quoted, e.g. A character constant cannot be empty (i.e. 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 the OSType, 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, and Visual C++, Like string literals, character constants can also be modified by prefixes, for example Wide character stringsSince type Wide characters are most commonly either 2 bytes (using a 2-byte encoding such as UTF-16) or 4 bytes (usually UTF-32), but Standard C does not specify the width for The original C 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 for The now generally recommended method[note 3] of supporting international characters is through UTF-8, which is stored in Variable width stringsA common alternative to Library functionsStrings, both constant and variable, can be manipulated without using the standard library. However, the library contains many useful functions for working with null-terminated strings. Structures and unionsStructuresStructures and unions in C are defined as data containers consisting of a sequence of named members of various types. They are similar to records in other programming languages. The members of a structure are stored in consecutive locations in memory, although the compiler is allowed to insert padding between or after members (but not before the first member) for efficiency or as padding required for proper alignment by the target architecture. The size of a structure is equal to the sum of the sizes of its members, plus the size of the padding. UnionsUnions in C are related to structures and are defined as objects that may hold (at different times) objects of different types and sizes. They are analogous to variant records in other programming languages. Unlike structures, the components of a union all refer to the same location in memory. In this way, a union can be used at various times to hold different types of objects, without the need to create a separate object for each new type. The size of a union is equal to the size of its largest component type. DeclarationStructures are declared with the For example, the following statement declares a structure named struct s {
int x;
float y;
char *z;
} tee;
And the following statement will declare a similar union named union u {
int x;
float y;
char *z;
} n;
Members of structures and unions cannot have an incomplete or function type. Thus members cannot be an instance of the structure or union being declared (because it is incomplete at that point) but can be pointers to the type being declared. Once a structure or union body has been declared and given a name, it can be considered a new data type using the specifier struct s r;
It is also common to use the typedef struct {...} s_type;
Future statements can then use the specifier s_type (instead of the expanded Accessing membersMembers are accessed using the name of the instance of a structure or union, a period ( tee.y
Structures are commonly accessed through pointers. Consider the following example that defines a pointer to tee, known as ptr_to_tee: struct s *ptr_to_tee = &tee;
Member y of tee can then be accessed by dereferencing ptr_to_tee and using the result as the left operand: (*ptr_to_tee).y
Which is identical to the simpler ptr_to_tee->y
Members of unions are accessed in the same way. This can be chained; for example, in a linked list, one may refer to AssignmentAssigning values to individual members of structures and unions is syntactically identical to assigning values to any other object. The only difference is that the lvalue of the assignment is the name of the member, as accessed by the syntax mentioned above. A structure can also be assigned as a unit to another structure of the same type. Structures (and pointers to structures) may also be used as function parameter and return types. For example, the following statement assigns the value of 74 (the ASCII code point for the letter 't') to the member named x in the structure tee, from above: tee.x = 74;
And the same assignment, using ptr_to_tee in place of tee, would look like: ptr_to_tee->x = 74;
Assignment with members of unions is identical. Other operationsAccording to the C standard, the only legal operations that can be performed on a structure are copying it, assigning to it as a unit (or initializing it), taking its address with the address-of ( Bit fieldsC also provides a special type of member known as a bit field, which is an integer with an explicitly specified number of bits. A bit field is declared as a structure (or union) member of type As a special exception to the usual C syntax rules, it is implementation-defined whether a bit field declared as type Unnamed fields consisting of just a colon followed by a number of bits are also allowed; these indicate padding. Specifying a width of zero for an unnamed field is used to force alignment 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. The members of bit fields do not have addresses, and as such cannot be used with the address-of ( The following declaration declares a new structure type known as struct f {
unsigned int flag : 1; /* a bit flag: can either be on (1) or off (0) */
signed int num : 4; /* a signed 4-bit field; range -7...7 or -8...7 */
signed int : 3; /* 3 bits of padding to round out to 8 bits */
} g;
InitializationDefault initialization depends on the storage class specifier, described above. 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, though. int x = 12;
int y = { 23 }; //Legal, no warning
int z = { { 34 } }; //Legal, expect a warning
Structures, unions and arrays can be initialized in their declarations using an initializer list. Unless designators are used, the components of an initializer correspond with the elements in the order they are defined and stored, thus all preceding values must be provided before any particular element's value. Any unspecified elements are set to zero (except for unions). Mentioning too many initialization values yields an error. The following statement will initialize a new instance of the structure s known as pi: struct s {
int x;
float y;
char *z;
};
struct s pi = { 3, 3.1415, "Pi" };
Designated initializersDesignated initializers allow members to be initialized by name, in any order, and without explicitly providing the preceding values. The following initialization is equivalent to the previous one: struct s pi = { .z = "Pi", .x = 3, .y = 3.1415 };
Using a designator in an initializer moves the initialization "cursor". In the example below, if int a[MAX] = { 1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0 };
In C89, a union was initialized with a single value applied to its first member. That is, the union u defined above could only have its int x member initialized: union u value = { 3 };
Using a designated initializer, the member to be initialized does not have to be the first member: union u value = { .y = 3.1415 };
If an array has unknown size (i.e. the array was an incomplete type), the number of initializers determines the size of the array and its type becomes complete: int x[] = { 0, 1, 2 } ;
Compound designators can be used to provide explicit initialization when unadorned initializer lists
might be misunderstood. In the example below, struct { int a[3], b; } w[] = { [0].a = {1}, [1].a[0] = 2 };
This is equivalent to: struct { int a[3], b; } w[] =
{
{ { 1, 0, 0 }, 0 },
{ { 2, 0, 0 }, 0 }
};
There is no way to specify repetition of an initializer in standard C. Compound literalsIt 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 };
struct s pi = (struct s){ 3, 3.1415, "Pi" };
Compound literals are often combined with designated initializers to make the declaration more readable:[3] pi = (struct s){ .z = "Pi", .x = 3, .y = 3.1415 };
OperatorsControl structuresC is a free-form language. Bracing style varies from programmer to programmer and can be the subject of debate. See Indentation style for more details. Compound statementsIn the items in this section, any <statement> can be replaced with a compound statement. Compound statements have the form: {
<optional-declaration-list>
<optional-statement-list>
}
and are used as the body of a function or anywhere that a single statement is expected. The declaration-list declares variables to be used in that scope, and the statement-list are the actions to be performed. Brackets define their own scope, and variables defined inside those brackets will be automatically deallocated at the closing bracket. Declarations and statements can be freely intermixed within a compound statement (as in C++). Selection statementsC has two types of selection statements: the The if (<expression>)
<statement1>
else
<statement2>
In the The switch (<expression>)
{
case <label1> :
<statements 1>
case <label2> :
<statements 2>
break;
default :
<statements 3>
}
No two of the case constants associated with the same switch may have the same value. There may be at most one Switches may be nested; a It is possible, although unusual, to insert the Iteration statementsC has three forms of iteration statement: do
<statement>
while ( <expression> ) ;
while ( <expression> )
<statement>
for ( <expression> ; <expression> ; <expression> )
<statement>
In the The statement: for (e1; e2; e3)
s;
is equivalent to: e1;
while (e2)
{
s;
cont:
e3;
}
except for the behaviour of a Any of the three expressions in the Since C99, the first expression may take the form of a declaration, typically including an initializer, such as: for (int i = 0; i < limit; ++i) {
// ...
}
The declaration's scope is limited to the extent of the Jump statementsJump statements transfer control unconditionally. There are four types of jump statements in C: The goto <identifier> ;
The identifier must be a label (followed by a colon) located in the current function. Control transfers to the labeled statement. A while (expression)
{
/* ... */
cont: ;
}
do
{
/* ... */
cont: ;
} while (expression);
for (expr1; expr2; expr3) {
/* ... */
cont: ;
}
a The A function returns to its caller by the Storing the address of a labelGCC extends the C language with a unary void *ptr = &&J1;
J1: printf("hi ");
goto *ptr;
This feature can be used to implement a jump table. FunctionsSyntaxA C function definition consists of a return type ( <return-type> functionName( <parameter-list> )
{
<statements>
return <expression of type return-type>;
}
A function with non- The return type cannot be an array type or function type. int f()[3]; // Error: function returning an array
int (*g())[3]; // OK: function returning a pointer to an array.
void h()(); // Error: function returning a function
void (*k())(); // OK: function returning a function pointer
If there are no parameters, the It is possible to define a function as taking a variable number of parameters by providing the int printf (const char*, ...);
Manipulation of these parameters can be done by using the routines in the standard library header Function PointersA pointer to a function can be declared as follows: <return-type> (*<function-name>)(<parameter-list>);
The following program shows use of a function pointer for selecting between addition and subtraction: #include <stdio.h>
int (*operation)(int x, int y);
int add(int x, int y)
{
return x + y;
}
int subtract(int x, int y)
{
return x - y;
}
int main(int argc, char* args[])
{
int foo = 1, bar = 1;
operation = add;
printf("%d + %d = %d\n", foo, bar, operation(foo, bar));
operation = subtract;
printf("%d - %d = %d\n", foo, bar, operation(foo, bar));
return 0;
}
Global structureAfter preprocessing, at the highest level a C program consists of a sequence of declarations at file scope. These may be partitioned into several separate source files, which may be compiled separately; the resulting object modules are then linked along with implementation-provided run-time support modules to produce an executable image. The declarations introduce functions, variables and types. C functions are akin to the subroutines of Fortran or the procedures of Pascal. A definition is a special type of declaration. A variable definition sets aside storage and possibly initializes it, a function definition provides its body. An implementation of C providing all of the standard library functions is called a hosted implementation. Programs written for hosted implementations are required to define a special function called Hosted implementations start program execution by invoking the int main() {...}
int main(void) {...}
int main(int argc, char *argv[]) {...}
int main(int argc, char **argv) {...} // char *argv[] and char **argv have the same type as function parameters
The first two definitions are equivalent (and both are compatible with C++). It is probably up to individual preference which one is used (the current C standard contains two examples of The C standard defines return values A minimal correct C program consists of an empty int main(void){}
Because no The Some implementations are not hosted, usually because they are not intended to be used with an operating system. Such implementations are called free-standing in the C standard. A free-standing implementation is free to specify how it handles program startup; in particular it need not require a program to define a Functions may be written by the programmer or provided by existing libraries. Interfaces for the latter are usually declared by including header files—with the A function may return a value to caller (usually another C function, or the hosting environment for the function Argument passingIn C, arguments are passed to functions by value while other languages may pass variables by reference. This means that the receiving function gets copies of the values and has no direct way of altering the original variables. For a function to alter a variable passed from another function, the caller must pass its address (a pointer to it), which can then be dereferenced in the receiving function. See Pointers for more information. void incInt(int *y)
{
(*y)++; // Increase the value of 'x', in 'main' below, by one
}
int main(void)
{
int x = 0;
incInt(&x); // pass a reference to the var 'x'
return 0;
}
The function scanf works the same way: int x;
scanf("%d", &x);
In order to pass an editable pointer to a function (such as for the purpose of returning an allocated array to the calling code) you have to pass a pointer to that pointer: its address. #include <stdio.h>
#include <stdlib.h>
void allocate_array(int ** const a_p, const int A) {
/*
allocate array of A ints
assigning to *a_p alters the 'a' in main()
*/
*a_p = malloc(sizeof(int) * A);
}
int main(void) {
int * a; /* create a pointer to one or more ints, this will be the array */
/* pass the address of 'a' */
allocate_array(&a, 42);
/* 'a' is now an array of length 42 and can be manipulated and freed here */
free(a);
return 0;
}
The parameter Array parametersFunction parameters of array type may at first glance appear to be an exception to C's pass-by-value rule. The following program will print 2, not 1: #include <stdio.h>
void setArray(int array[], int index, int value)
{
array[index] = value;
}
int main(void)
{
int a[1] = {1};
setArray(a, 0, 2);
printf ("a[0]=%d\n", a[0]);
return 0;
}
However, there is a different reason for this behavior. In fact, a function parameter declared with an array type is treated like one declared to be a pointer. That is, the preceding declaration of void setArray(int *array, int index, int value)
At the same time, C rules for the use of arrays in expressions cause the value of Since C99, the programmer can specify that a function takes an array of a certain size by using the keyword Anonymous functionsThe anonymous function is not supported by standard C programming language, but supported by some C dialects, such as GCC[9] and Clang. GCCThe GNU Compiler Collection (GCC) supports anonymous functions, mixed by nested functions and statement expressions. It has the form: ( { return_type anonymous_functions_name (parameters) { function_body } anonymous_functions_name; } )
The following example works only with GCC. Because of how macros are expanded, the #include <stdio.h>
//* this is the definition of the anonymous function */
#define lambda(l_ret_type, l_arguments, l_body) \
({ \
l_ret_type l_anonymous_functions_name l_arguments \
l_body \
&l_anonymous_functions_name; \
})
#define forEachInArray(fe_arrType, fe_arr, fe_fn_body) \
{ \
int i=0; \
for(;i<sizeof(fe_arr)/sizeof(fe_arrType);i++) { fe_arr[i] = fe_fn_body(&fe_arr[i]); } \
}
typedef struct
{
int a;
int b;
} testtype;
void printout(const testtype * array)
{
int i;
for ( i = 0; i < 3; ++ i )
printf("%d %d\n", array[i].a, array[i].b);
printf("\n");
}
int main(void)
{
testtype array[] = { {0,1}, {2,3}, {4,5} };
printout(array);
/* the anonymous function is given as function for the foreach */
forEachInArray(testtype, array,
lambda (testtype, (void *item),
{
int temp = (*( testtype *) item).a;
(*( testtype *) item).a = (*( testtype *) item).b;
(*( testtype *) item).b = temp;
return (*( testtype *) item);
}));
printout(array);
return 0;
}
Clang (C, C++, Objective-C, Objective-C++)Clang supports anonymous functions, called blocks,[10] which have the form: ^return_type ( parameters ) { function_body }
The type of the blocks above is Using the aforementioned blocks extension and Grand Central Dispatch (libdispatch), the code could look simpler: #include <stdio.h>
#include <dispatch/dispatch.h>
int main(void) {
void (^count_loop)() = ^{
for (int i = 0; i < 100; i++)
printf("%d\n", i);
printf("ah ah ah\n");
};
/* Pass as a parameter to another function */
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), count_loop);
/* Invoke directly */
count_loop();
return 0;
}
-fblocks and linked with -lBlocksRuntime MiscellaneousReserved keywordsThe following words are reserved, and may not be used as identifiers:
Implementations may reserve other keywords, such as Case sensitivityC identifiers are case sensitive (e.g., CommentsText starting with the token /*
This line will be ignored.
/*
A compiler warning may be produced here. These lines will also be ignored.
The comment opening token above did not start a new comment,
and the comment closing token below will close the comment begun on line 1.
*/
This line and the line below it will not be ignored. Both will likely produce compile errors.
*/
C++ style line comments start with // this line will be ignored by the compiler
/* these lines
will be ignored
by the compiler */
x = *p/*q; /* this comment starts after the 'p' */
Command-line argumentsThe parameters given on a command line are passed to a C program with two predefined variables - the count of the command-line arguments in myFilt p1 p2 p3 results in something like:
While individual strings are arrays of contiguous characters, there is no guarantee that the strings are stored as a contiguous group. The name of the program, #include <stdio.h>
int main(int argc, char *argv[])
{
printf("argc\t= %d\n", argc);
for (int i = 0; i < argc; i++)
printf("argv[%i]\t= %s\n", i, argv[i]);
}
Evaluation orderIn any reasonably complex expression, there arises a choice as to the order in which to evaluate the parts of the expression:
Expressions 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 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]);
Undefined behaviorAn aspect of the C standard (not unique to C) is that the behavior of certain code is said to be "undefined". In practice, this means that the program produced from this code can do anything, from working as the programmer intended, to crashing every time it is run. For example, the following code produces undefined behavior, because the variable b is modified more than once with no intervening sequence point: #include <stdio.h>
int main(void)
{
int b = 1;
int a = b++ + b++;
printf("%d\n", a);
}
Because there is no sequence point between the modifications of b in "b++ + b++", it is possible to perform the evaluation steps in more than one order, resulting in an ambiguous statement. This can be fixed by rewriting the code to insert a sequence point in order to enforce an unambiguous behavior, for example: a = b++;
a += b++;
See also
Notes
References
External links |
Portal di Ensiklopedia Dunia