This shows you the differences between two versions of the page.
— |
cs:c_language:c99 [2020/11/26 23:18] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== c99 (Analysis of some aspects of the c99 standard) ====== | ||
+ | |||
+ | ===== Compilation ===== | ||
+ | In old '' | ||
+ | <code bash> | ||
+ | gcc -Wall --pedantic -std=c99 file.c | ||
+ | </ | ||
+ | |||
+ | For new '' | ||
+ | <code bash> | ||
+ | gcc -Wall --pedantic -std=c90 file.c | ||
+ | </ | ||
+ | |||
+ | ISO/IEC 9899:1999 [[http:// | ||
+ | |||
+ | Table which highlights supported features in GCC compilers [[https:// | ||
+ | |||
+ | ===== The C standards ===== | ||
+ | In the following table the C standards are listed. The compiler predefines the following macros, that can be used to check if a given standard is supported and possibly, in the case the standard is not supported, to check if the compiler provides a C90 implementation. | ||
+ | |||
+ | ^Standard | ||
+ | |ANSI X3.159-1989 | ||
+ | |ISO/IEC 9899: | ||
+ | |ISO/IEC 9899-1:1994 |C94 | %%__STDC_VERSION__ = 199409L%% | | ||
+ | |ISO/IEC 9899: | ||
+ | |ISO/IEC 9899: | ||
+ | |||
+ | Compiling with: | ||
+ | <code bash> | ||
+ | gcc -std=c99 c99_macro_std_version.c | ||
+ | </ | ||
+ | the following program: | ||
+ | <file c c99_macro_std_version.c> | ||
+ | /* c99: example of macro useful to identify the standard used by the compiler */ | ||
+ | #include < | ||
+ | |||
+ | int main() { | ||
+ | |||
+ | printf(" | ||
+ | | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | the output is: | ||
+ | <code bash> | ||
+ | __STDC__: 1 | ||
+ | </ | ||
+ | |||
+ | ===== Some new features included in the standard ===== | ||
+ | ==== Inline functions ==== | ||
+ | Function is inline inserted in the code of the program. | ||
+ | |||
+ | Usually it is better to avoid the use of '' | ||
+ | - //gcc// is better than you in code optimization | ||
+ | - the generated code is bigger | ||
+ | - you cannot use function pointers | ||
+ | - functions evolve and may no longer be suitable to be declared as '' | ||
+ | - compilation time increases | ||
+ | |||
+ | For more details: [[http:// | ||
+ | |||
+ | ==== Intermingled declarations and code ==== | ||
+ | Variables can be declared in **any point** of the source code. In the previous '' | ||
+ | |||
+ | This possibility is very useful for three main reasons: | ||
+ | * Variable used in the '' | ||
+ | |||
+ | <code c c99_var1.c> | ||
+ | /* c99: example of a variable declared inside a for loop */ | ||
+ | |||
+ | #include < | ||
+ | |||
+ | int main() { | ||
+ | int i = 123; | ||
+ | | ||
+ | for (int i=0; i<3; i++) | ||
+ | printf(" | ||
+ | |||
+ | printf(" | ||
+ | | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | The above code corresponds to the following code written in the '' | ||
+ | <code c c90_var1.c> | ||
+ | /* c90: how to restrict the scope of the variable used to manage | ||
+ | the cycle in a for loop */ | ||
+ | |||
+ | #include < | ||
+ | |||
+ | int main() { | ||
+ | int i = 123; | ||
+ | |||
+ | { | ||
+ | int i; | ||
+ | for (i=0; i<3; i++) | ||
+ | printf(" | ||
+ | } | ||
+ | printf(" | ||
+ | | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | * Allowing the declaration of variable-length arrays (see in this page in the following) | ||
+ | * Declare the variables exactly where they are needed (limiting the scope of variables is useful, because if a variable exists for a smaller time, the probability of bugs is reduced. As a consequence, | ||
+ | <code c c99_scope.c> | ||
+ | /* c99: limiting the scope of variables declaring them when needed | ||
+ | or declaring them in a block inside a block */ | ||
+ | |||
+ | #include < | ||
+ | |||
+ | int main() { | ||
+ | int x; | ||
+ | x = 2; | ||
+ | /* i cannot be used here */ | ||
+ | int i; | ||
+ | i = x; | ||
+ | |||
+ | /* Block inside a block */ | ||
+ | { | ||
+ | /* This is another variable, it is not i=x */ | ||
+ | int i; | ||
+ | i = 3; | ||
+ | |||
+ | /* At the end of the block i=3 no longer exist */ | ||
+ | } | ||
+ | /* i=x still exist */ | ||
+ | | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Variable-length arrays ==== | ||
+ | Variable-length arrays (VLAs) are classical C arrays, but with a length not declared as a constant expression. | ||
+ | |||
+ | Drawbacks of VLAs are two: | ||
+ | * They are declared as any automatic variable in the //stack//, which has a limited memory space. As a consequence, | ||
+ | * The main drawback is that the implementation of VLAs is **not mandatory** in '' | ||
+ | |||
+ | A first easy example is the following, where an array with unknown dimension is read from stdin | ||
+ | <file c c99_variable-length_arrays_1.c> | ||
+ | /* c99: VLAs, reading a vector with unknown dimension from stdin */ | ||
+ | |||
+ | #include < | ||
+ | |||
+ | int main() { | ||
+ | int l; | ||
+ | |||
+ | printf(" | ||
+ | scanf(" | ||
+ | |||
+ | int v[l]; | ||
+ | for(int i=0; i<l; i++) | ||
+ | scanf(" | ||
+ | |||
+ | for(int i=0; i<l-1; i++) | ||
+ | printf(" | ||
+ | printf(" | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | In this second example, VLAs are used in the function '' | ||
+ | |||
+ | <file c variable-length_arrays_2.c> | ||
+ | /* c99: VLAs, system with the concatenation of two strings */ | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int my_system(char *s1, char *s2) { | ||
+ | char s[strlen(s1) + 1 + strlen(s2) + 1]; | ||
+ | strcpy(s, s1); | ||
+ | strcat(s, " "); | ||
+ | strcat(s, s2); | ||
+ | | ||
+ | return system(s); | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | |||
+ | my_system(" | ||
+ | | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Reference regarding '' | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== A number of new data types ==== | ||
+ | === long double === | ||
+ | Even if the '' | ||
+ | |||
+ | Constants of type '' | ||
+ | |||
+ | The format specifier for '' | ||
+ | |||
+ | **Usually** in 32 bits architectures '' | ||
+ | |||
+ | In the following program some statistics regarding the precision of '' | ||
+ | <file c c99_long_double.c> | ||
+ | /* c99: some statistics regarding long double and | ||
+ | | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int main() { | ||
+ | long double ld = 1342344.42423412442344141232412L; | ||
+ | | ||
+ | printf(" | ||
+ | printf(" | ||
+ | printf(" | ||
+ | printf(" | ||
+ | |||
+ | | ||
+ | printf(" | ||
+ | printf(" | ||
+ | printf(" | ||
+ | printf(" | ||
+ | |||
+ | printf(" | ||
+ | printf(" | ||
+ | printf(" | ||
+ | printf(" | ||
+ | | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | <code bash> | ||
+ | LEN: | ||
+ | Float len: 4 | ||
+ | | ||
+ | Long double len: 16 | ||
+ | |||
+ | NUMBER OF SIGNIFICANT DIGITS: | ||
+ | Float significant digits = 6 | ||
+ | | ||
+ | Long double significant digits = 18 | ||
+ | |||
+ | PRINTF: | ||
+ | 1342344.424234 | ||
+ | 1.34234e+06 | ||
+ | 1.342344e+06 | ||
+ | </ | ||
+ | |||
+ | A good reference regarding '' | ||
+ | |||
+ | === long long int === | ||
+ | This new type and the relative '' | ||
+ | In particular: | ||
+ | |||
+ | == long long, long long int, signed long long, signed long long int'' | ||
+ | * They are equivalent ways to identify '' | ||
+ | |||
+ | * Constants are identified by the suffixes '' | ||
+ | |||
+ | * For '' | ||
+ | |||
+ | |||
+ | == unsigned long long, unsigned long long int == | ||
+ | * They are the same as '' | ||
+ | |||
+ | * Constants are identified by the suffixes '' | ||
+ | |||
+ | * For '' | ||
+ | |||
+ | The ''< | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | <code c c99_long_long_int.c> | ||
+ | /* c99: the long long int type */ | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int main() { | ||
+ | long long int a; | ||
+ | unsigned long long int b; | ||
+ | | ||
+ | printf(" | ||
+ | printf(" | ||
+ | |||
+ | a = -2; | ||
+ | b = 2; | ||
+ | | ||
+ | printf(" | ||
+ | printf(" | ||
+ | |||
+ | printf(" | ||
+ | | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | |||
+ | <code bash> | ||
+ | Range long long: [-9223372036854775808, | ||
+ | Range unisigned long long: [0, 18446744073709551615] | ||
+ | a: -2 b: 2 | ||
+ | -2 is hex FFFFFFFFFFFFFFFE | ||
+ | SIZE: 8 | ||
+ | </ | ||
+ | |||
+ | More details: [[http:// | ||
+ | |||
+ | |||
+ | === boolean (header: stdbool.h) === | ||
+ | The new '' | ||
+ | - guarantees the possibility of comparison between boolean values (before '' | ||
+ | - it occupies in memory 1 byte, instead the small integer type ('' | ||
+ | |||
+ | By including the header '' | ||
+ | |||
+ | Casting: '' | ||
+ | |||
+ | The language guarantees that any two true values will compare equal (which was impossible to achieve before the introduction of the type) | ||
+ | |||
+ | |||
+ | <file c c99_bool_type.c> | ||
+ | /* c99: the _Bool type */ | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int main() { | ||
+ | _Bool x; | ||
+ | bool y; /* bool is a macro with the same meaning of _Bool */ | ||
+ | | ||
+ | x = true; | ||
+ | y = true; | ||
+ | |||
+ | if (x==y) printf(" | ||
+ | | ||
+ | printf(" | ||
+ | printf(" | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | |||
+ | <code bash> | ||
+ | Equals | ||
+ | VALUES-> | ||
+ | SIZES -> _Bool: 1 short: 2 | ||
+ | </ | ||
+ | |||
+ | === complex (header: complex.h) === | ||
+ | The '' | ||
+ | '' | ||
+ | |||
+ | The following example should clarify the use of complex numbers: | ||
+ | <file c c99_complex.c> | ||
+ | /* c99: example regarding complex numbers */ | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | |||
+ | /* Square 1 */ | ||
+ | double complex z1 = I * I; | ||
+ | printf(" | ||
+ | |||
+ | /* Square 2 */ | ||
+ | double complex z2 = pow(I, 2); // imaginary unit squared | ||
+ | printf(" | ||
+ | |||
+ | /* Conjugates numbers */ | ||
+ | double complex z4 = 1+2*I, z5 = 1-2*I; // conjugates | ||
+ | printf(" | ||
+ | |||
+ | /* Square root */ | ||
+ | double complex z6=csqrt(-1); | ||
+ | printf(" | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | |||
+ | <code bash> | ||
+ | I * I = -1.0+0.0i | ||
+ | pow(I, 2) = -1.0+0.0i | ||
+ | (1+2i)*(1-2i) = 5.0+0.0i | ||
+ | sqrt(-1) = 0.0+1.0i | ||
+ | </ | ||
+ | |||
+ | The specific header '' | ||
+ | |||
+ | A good reference can be downloaded here: http:// | ||
+ | |||
+ | ==== Other features ==== | ||
+ | Other characteristics added by the '' | ||
+ | * The use of C++ style comments: ''< | ||
+ | * Flexible array member: https:// | ||
+ | * Library '' | ||
+ | * The '' | ||
+ | * Others features introduced by the '' | ||
+ | |||