User Tools

Site Tools


cs:c_language:c99
Return to Home page

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cs:c_language:c99 [2016/03/03 11:33]
zioskenz
cs:c_language:c99 [2019/02/26 14:35]
Line 1: Line 1:
-====== c99 (Analysis of some aspects of the c99 standard) ====== 
- 
-===== Compilation ===== 
-In old ''​gcc''​ compilers, if you try to compile a program written with the //c99// standard, a compilation //warning// is notified by the compiler. You must use the specific ''​-std''​ option of the ''​gcc''​ compiler, to explicitly specify the standard used in the program you want to compile: 
-<code bash> 
-gcc -Wall --pedantic -std=c99 file.c 
-</​code>​ 
- 
-For new ''​gcc''​ compilers the //c99// standard is the default. As a consequence,​ to know if a program is adherent with the old ''​c90''​ standard, it must be compiled with the following options: ​ 
-<code bash> 
-gcc -Wall --pedantic -std=c90 file.c 
-</​code>​ 
- 
-ISO/IEC 9899:1999 [[http://​www.iso.org/​iso/​catalogue_detail.htm?​csnumber=29237]] 
- 
-Table which highlights supported features in GCC compilers [[https://​gcc.gnu.org/​c99status.html]] 
- 
-===== 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 ​           ^ NAME     ^ Predefined macro               ^ 
-|ANSI X3.159-1989 ​   |C89 | %%__STDC__%%                  | 
-|ISO/IEC 9899:​1990 ​  |C90 | %%__STDC__%%                  | 
-|ISO/IEC 9899-1:1994 |C94 | %%__STDC_VERSION__ = 199409L%% | 
-|ISO/IEC 9899:​1999 ​  |C99 | %%__STDC_VERSION__ = 199901L%% | 
-|ISO/IEC 9899:​2011 ​  |C11 | %%__STDC_VERSION__ = 201112L%% | 
- 
-Compiling with: 
-<code bash> 
-gcc -std=c99 c99_macro_std_version.c 
-</​code>​ 
-the following program: 
-<file c c99_macro_std_version.c>​ 
-/* c99: example of macro useful to identify the standard used by the compiler */ 
-#include <​stdio.h>​ 
- 
-int main() { 
- 
-  printf("​__STDC__:​ %d   ​__STDC_VERSION__:​ %ld\n",​ __STDC__, __STDC_VERSION__);​ 
-  ​ 
-  return 0; 
-} 
-</​file>​ 
-the output is: 
-<code bash> 
-__STDC__: 1   ​__STDC_VERSION__:​ 199901 
-</​code>​ 
- 
-===== 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 ''​inline''​ functions because: 
-  - //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 ''​inline''​ 
-  - compilation time increases 
- 
-For more details: [[http://​www.greenend.org.uk/​rjk/​tech/​inline.html]] 
- 
-==== Intermingled declarations and code ==== 
-Variables can be declared in **any point** of the source code. In the previous ''​c90''​ version, the declaration of the variables was restricted to the start of a block. 
- 
-This possibility is very useful for three main reasons: 
-  * Variable used in the ''​for''​ loops can be initialized directly inside the loop with scope restricted to the loop: 
- 
-<code c c99_var1.c>​ 
-/* c99: example of a variable declared inside a for loop */ 
- 
-#include <​stdio.h>​ 
- 
-int main() { 
-  int i = 123; 
-  ​ 
-  for (int i=0; i<3; i++) 
-    printf("​%d ", i);; 
- 
-  printf("​\nAFTER THE FOR: %d\n", i); 
-  ​ 
-  return 0; 
-} 
-</​code>​ 
-The above code corresponds to the following code written in the ''​c90''​ standard: 
-<code c c90_var1.c>​ 
-/* c90: how to restrict the scope of the variable used to manage 
-   the cycle in a for loop */ 
- 
-#include <​stdio.h>​ 
- 
-int main() { 
-  int i = 123; 
- 
-  { 
-    int i; 
-    for (i=0; i<3; i++) 
-      printf("​%d ", i);    ​ 
-  } 
-  printf("​\nAFTER THE FOR: %d\n", i); 
-  ​ 
-  return 0; 
-} 
-</​code>​ 
-  * 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,​ a good programming style is to use blocks inside blocks and declare a variable only when it is needed). 
-<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 <​stdio.h>​ 
- 
-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; 
-} 
-</​code>​ 
- 
-==== 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 use of VLAs is recommended only when their size is relatively small. As an example, VLAs could be useful for strings. 
-  * The main drawback is that the implementation of VLAs is **not mandatory** in ''​c11''​ standard. Therefore, a program that makes use of VLAs could not be compiled by some "​new"​ compilers. 
- 
-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 <​stdio.h>​ 
- 
-int main() { 
-  int l; 
- 
-  printf("​Insert length: "); 
-  scanf("​%d",​ &l); 
- 
-  int v[l]; 
-  for(int i=0; i<l; i++) 
-    scanf("​%d",​ &v[i]); 
- 
-  for(int i=0; i<l-1; i++) 
-    printf("​%d ", v[i]); 
-  printf("​%d\n",​ v[l-1]); 
- 
-  return 0; 
-} 
-</​file>​ 
- 
-In this second example, VLAs are used in the function ''​my_system''​ to concatenate two strings. The concatenation of the two strings is used as an argument of the system call ''​system''​. 
- 
-<file c variable-length_arrays_2.c>​ 
-/* c99: VLAs, system with the concatenation of two strings */ 
-  
-#include <​stdio.h>​ 
-#include <​stdlib.h>​ 
-#include <​string.h>​ 
- 
-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("​ls",​ "​-l"​);​ 
-  ​ 
-  return 0; 
-} 
-</​file>​ 
- 
-Reference regarding ''​malloc''​ vs. VLAs: http://​www.drdobbs.com/​the-new-cwhy-variable-length-arrays/​184401444 
- 
- 
- 
- 
- 
-==== A number of new data types ==== 
-=== long double === 
-Even if the ''​long double''​ type was present from the very beginning in the first version of the C standard, the support in standard libraries of this type starts from the ''​c99''​ version of the standard. 
- 
-Constants of type ''​long double''​ are identified by the ''​L''​ or ''​l''​ suffixes at the end of the number (e.g., ''​12.033134113425422423432L''​). 
- 
-The format specifier for ''​printf''​ and ''​scanf''​ functions family is "''​%Lf''"​ and "''​%LF''",​ "''​%Lg''"​ and "''​%LG''"​ for a number with up to 6 digits of precision, and "''​%Le''"​ and "''​%LE''"​ for the hexadecimal format. 
- 
-**Usually** in 32 bits architectures ''​long double''​ are stored with an 80 bits precision, while in a 64 bit architecture they are **usually** stored with a precision of 128 bits (see https://​en.wikipedia.org/​wiki/​Quadruple-precision_floating-point_format). The fact that dimension and characteristics of this type change depending on the architecture and on the compiler leads to compatibility problems when binary files containing ''​long double''​ values are transferred between different PCs. 
- 
-In the following program some statistics regarding the precision of ''​long double''​ are inspected and an example regarding the ''​printf''​ function is provided: 
-<file c c99_long_double.c>​ 
-/* c99: some statistics regarding long double and 
-   ​example of the use of the printf function */  
- 
-#include <​stdio.h>​ 
-#include <​float.h>​ 
- 
-int main() { 
-  long double ld = 1342344.42423412442344141232412L;​ 
-  ​ 
-  printf("​LEN:​\n"​);​ 
-  printf(" ​     Float len: %zu\n",​ sizeof(float));​ 
-  printf(" ​    ​Double len: %zu\n",​ sizeof(double));​ 
-  printf("​Long double len: %zu\n",​ sizeof(long double)); 
- 
-  ​ 
-  printf("​\nNUMBER OF SIGNIFICANT DIGITS:​\n"​);​ 
-  printf(" ​     Float significant digits = %d\n", FLT_DIG); 
-  printf(" ​    ​Double significant digits = %d\n", DBL_DIG); 
-  printf("​Long double significant digits = %d\n", LDBL_DIG); 
- 
-  printf("​\nPRINTF:​\n"​);​ 
-  printf("​%Lf\n",​ ld); 
-  printf("​%Lg\n",​ ld); 
-  printf("​%Le\n",​ ld); 
-  ​ 
-  return 0; 
-} 
-</​file>​ 
- 
-Output: 
-<code bash> 
-LEN: 
-      Float len: 4 
-     ​Double len: 8 
-Long double len: 16 
- 
-NUMBER OF SIGNIFICANT DIGITS: 
-      Float significant digits = 6 
-     ​Double significant digits = 15 
-Long double significant digits = 18 
- 
-PRINTF: 
-1342344.424234 
-1.34234e+06 
-1.342344e+06 
-</​code>​ 
- 
-A good reference regarding ''​float.h''​ library and floating points numbers in general: http://​pubs.opengroup.org/​onlinepubs/​009695399/​basedefs/​float.h.html 
- 
-=== long long int === 
-This new type and the relative ''​unsigned''​ version has been added to the allowed standard C types. 
-In particular: 
- 
-== long long, long long int, signed long long, signed long long int''​ == 
-  * They are equivalent ways to identify ''​signed long long''​ integers. The standard guarantees that in a variable of such type can be stored a number at least in the range [−9223372036854775807,​ +9223372036854775807],​ and the minimum size of such a kind of data is 64 bits. 
- 
-  * Constants are identified by the suffixes ''​ll''​ or ''​LL''​ added at the end of the integer constant. Examples are  7ll, 7LL, 07LL, 0x7ll. 
- 
-  * For ''​printf''​ and ''​scanf''​ functions the ''​%lld''​ format specifier is typically used. Other format specifiers are possible, for example for //octals// or //​exadecimals//​ numbers (e.g., ''​%llo'',​ ''​%llx'',​ ''​%llX''​). 
- 
- 
-== unsigned long long, unsigned long long int == 
-  * They are the same as ''​long long''​ (i.e., dimension of at least 64 bits), but only for unsigned positive integer numbers. As a consequence,​ the minimum range of number that can be stored in this type of variables is [0, +18446744073709551615]. 
- 
-  * Constants are identified by the suffixes ''​U''​ or ''​u''​ concatenated with the suffixes ''​ll''​ or ''​LL''​ added at the end of the integer constant. Examples are 7Ull, 7LLu, 0x7llu. 
- 
-  * For ''​printf''​ and ''​scanf''​ functions the ''​%llu''​ format specifier is typically used. Other format specifiers are possible, for example for //octals// or //​exadecimals//​ numbers (e.g., ''​%llo'',​ ''​%llx'',​ ''​%llX''​). 
- 
-The ''<​limits.h>''​ library defines the limits for ''​long long int''​ type: 
-  * ''​long long''​ in the range [LLONG_MIN,​LLONG_MAX] 
-  * ''​unsigned long long''​ in the range [0,​ULLONG_MAX] 
- 
-<code c c99_long_long_int.c>​ 
-/* c99: the long long int type */ 
- 
-#include <​stdio.h>​ 
-#include <​limits.h>​ 
- 
-int main() { 
-  long long int a; 
-  unsigned long long int b; 
-  ​ 
-  printf("​Range long long: [%lld, %lld]\n",​ LLONG_MIN, LLONG_MAX); 
-  printf("​Range unisigned long long: [0, %llu]\n",​ ULLONG_MAX);​ 
- 
-  a = -2; 
-  b = 2; 
-  ​ 
-  printf("​a:​ %lld   b: %llu\n",​ a, b); 
-  printf("​%3lld is hex %llX\n",​ a, a); 
- 
-  printf("​SIZE:​ %zu\n",​ sizeof(long long int)); 
-  ​ 
-  return 0; 
-} 
-</​code>​ 
- 
-Output: 
- 
-<code bash> 
-Range long long: [-9223372036854775808,​ 9223372036854775807] 
-Range unisigned long long: [0, 18446744073709551615] 
-a: -2   b: 2 
- -2 is hex FFFFFFFFFFFFFFFE 
-SIZE: 8 
-</​code>​ 
- 
-More details: [[http://​www.drdobbs.com/​the-new-c-integers-in-c99-part-1/​184401323]] 
- 
- 
-=== boolean (header: stdbool.h) === 
-The new ''​_Bool''​ (or ''​bool''​ defined as macro) type: 
-  - guarantees the possibility of comparison between boolean values (before ''​_Bool''​ a ''​true''​ boolean value in C was a number other than 0, i.e., -15, 1, 123) 
-  - it occupies in memory 1 byte, instead the small integer type (''​short int''​) occupies at least 2 bytes. 
- 
-By including the header ''​stdbool.h''​ the constants ''​true''​ and ''​false''​ are defined. 
- 
-Casting: (bool)0.5 evaluates to ''​true'',​ whereas (int)0.5 evaluates to ​''​0''​ (''​false''​). 
- 
-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 <​stdio.h>​ 
-#include <​stdbool.h>​ /* Header for _Bool */ 
- 
-int main() { 
-  _Bool x; 
-  bool y; /* bool is a macro with the same meaning of _Bool */  
-  ​ 
-  x = true; 
-  y = true; 
- 
-  if (x==y) printf("​Equals\n"​);​ 
-  ​ 
-  printf("​VALUES-> ​ true: %d false: %d\n", true, false); 
-  printf("​SIZES ​ -> _Bool: %ld short: %ld\n",​ sizeof(_Bool),​ sizeof(short));​ 
- 
-  return 0; 
-} 
-</​file>​ 
- 
-Output: 
- 
-<code bash> 
-Equals 
-VALUES-> ​ true: 1 false: 0 
-SIZES  -> _Bool: 1 short: 2 
-</​code>​ 
- 
-=== complex (header: complex.h) === 
-The ''​c99''​ standard defines full support to complex numbers through the new ''​complex''​ type defined in ''​complex.h''​. The three types of complex numbers that can be defined are listed in the following in increasing size order: ''​float complex'',​ ''​double complex''​ and ''​long double complex''​. 
-''​I''​ is a constant to identify an imaginary number. Functions ''​creal()''​ and ''​cimag()''​ have been defined to access the //real// or the //​imaginary//​ part of a complex number, respectively. All math functions (e.g., ''​sin()'',​ ''​cos()'',​ ''​sqrt()''​) have an counterpart to be used with complex numbers. Such functions are the same defined in ''​math.h''​ but their name starts with the suffix ''​c''​ (e.g., ''​csin()'',​ ''​ccos()'',​ ''​csqrt()''​). 
- 
-The following example should clarify the use of complex numbers: 
-<file c c99_complex.c>​ 
-/* c99: example regarding complex numbers */ 
- 
-#include <​stdio.h>​ 
-#include <​complex.h>​ 
-#include <​tgmath.h>​ 
-  
-int main(void) 
-{ 
- 
-  /* Square 1 */ 
-  double complex z1 = I * I; 
-  printf("​I * I = %.1f+%.1fi\n",​ creal(z1), cimag(z1)); 
- 
-  /* Square 2 */ 
-  double complex z2 = pow(I, 2); // imaginary unit squared 
-  printf("​pow(I,​ 2) = %.1f+%.1fi\n",​ creal(z2), cimag(z2)); 
- 
-  /* Conjugates numbers */ 
-  double complex z4 = 1+2*I, z5 = 1-2*I; // conjugates 
-  printf("​(1+2i)*(1-2i) = %.1f+%.1fi\n",​ creal(z4*z5),​ cimag(z4*z5));​ 
- 
-  /* Square root */ 
-  double complex z6=csqrt(-1);​ 
-  printf("​sqrt(-1) = %.1f+%.1fi\n",​ creal(z6), cimag(z6)); 
-      ​ 
-} 
-</​file>​ 
- 
-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 
-</​code>​ 
- 
-The specific header ''​tgmath.h''​ defines a type-generic macro for each mathematical function defined in both ''​math.h''​ and ''​complex.h''​. Basically, for each math function there are 6 variants: 3 for types ''​float'',​ ''​double''​ and ''​long double'',​ and 3 for types ''​float complex'',​ ''​double complex''​ and ''​long double complex''​. 
- 
-A good reference can be downloaded here: http://​en.cppreference.com/​w/​c/​numeric/​complex 
- 
-==== Other features ==== 
-Other characteristics added by the ''​c99''​ standard and not discussed here are: 
-  * The use of C++ style comments: ''<​nowiki>//</​nowiki>''​ 
-  * Flexible array member: https://​en.wikipedia.org/​wiki/​Flexible_array_member 
-  * Library ''​tgmath.h''​ with defines function for ''​float'',​ ''​double'',​ ''​long double'',​ ''​complex float'',​ ''​complex double''​ and ''​complex long double''​ (only some hints are provided in this guide) 
-  * The ''​snprintf''​ (which is a safe version of the ''​sprintf''​ function) and other new functions 
-  * Others features introduced by the ''​c99''​ standard can be found in https://​en.wikipedia.org/​wiki/​C99 or in the standard 
- 
  

If you found any error, or if you want to partecipate to the editing of this wiki, please contact: admin [at] skenz.it

You can reuse, distribute or modify the content of this page, but you must cite in any document (or webpage) this url: https://www.skenz.it/cs/c_language/c99?do=diff&rev2%5B0%5D=1457001228&rev2%5B1%5D=1551188114&difftype=sidebyside
/web/htdocs/www.skenz.it/home/data/pages/cs/c_language/c99.txt · Last modified: 2019/02/26 14:35 (external edit)

Privacy Policy