The C programming language – Lecture 2.
The structure of C programs
1
2
3
4
5
6
7
8
9
10
/*
* my first C program // comment
*
*/
#include <stdio.h> // preprocessor directive
int main()
{
printf( "hello world\n" ); // c tokens...
return 0;
}
C programs consist of:
Comments:
single line comment (since C99) from // to end of line
1
2
3
4
5
6
7
8
9
/* multi
line
comments
// hiding single line comments
*/
/*
/* but must not be nested */
*/
not comments inside strings: “/* this is not comment */”
1
2
3
4
5
/*************************************\
* *
* exist in various style and format *
* *
\*************************************/
Preprocessor directives
starting with ‘#’
1
2
3
4
5
6
7
8
9
10
11
#ifdef
#define MY_HEADER
#include <header.h>
#if MY_PLATFORM
#define BUFFER 100
#else
#error platform not defined
#endif
#endif
… more on preprocessor in the next lecture
C tokens
keywords
all lowercase
- C89: 32
- C99: +5
- C11: +7
identifyers
starts with letter (incl _underscore) continues with letters or numbers
literals
- 1 decimal integer literal
- 0x14 hexadecimal integer literal
- 3.14 floating point literal
- ‘x’ character literal
- “Hello world” string literal
operators
- unary e.g. -2
- binary e.g. 2 + 4
- terciary x<y ? x : y
separators
{ } ,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
* my first C program <--- comment
*
*/
#include <stdio.h> <---- preprocessor directvive
int main() int <-- type name: keyword
main <-- function name: identifier
() <-- function call: operator
{ { <-- block begin: separator
printf <-- function name: identifier
( <-- function call: operator
printf("Hello world"); "Hello world" <-- string literal, type char[13]
) <-- function call: operator
; <-- command-end separator
return <-- keyword
return 0; 0 <-- decimal int literal, type int
} } <-- block end: separator
Keywords
we will learn them …
Identifiers
- starts with letter (underscore ‘_’ is a letter)
- continues with letters and digits
- no maximum length
- but compilers should translate
- only the first 63 letters (internal linkage)
- only the first 31 letters (external linkage)
- must not use keywords as identifiers
- case sensitive
Different conventions:
- camelCaseNotation
- CTypenamesStartsWithUppercase
- under_score_notation
A research on this: https://whathecode.wordpress.com/2011/02/10/camelcase-vs-underscores-scientific-showdown/
results on February 2015:
- camelCase: 52.5 %
- underscore: 47.5 %
MACRO_NAMES_ARE_ALL_UPPERCASE by convention
A paper on this: http://www.cs.loyola.edu/~binkley/papers/icpc09-clouds.pdf
Literals
void
Integrals, type + value
- decimal integral 12 type = int, value = 12
- octal integral 014 type = int, value = 12
-
hexadecimal integral 0xC type = int, value = 12
- long integer 12l type = long int, value = 12
-
long long integer (since C99)
- unsigned integer 12u type = unsigned int, value = 12
-
signed integers are the same as integers
-
if an integer literal longer than integer 10000000 –> long or long long
- int size knot known ==> the best for the compiler, machine word
sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
// at least 16 bit at least 32 bit at least 64 bit
- also exist signed and unsigned versions, e.g. long <==> signed long
Characters
- character ‘A’ type = char, value = ascii value of ‘A’, likely 65
- escape sequences:
- ’'’ single quote
- ’"’ double quote
- ’\?’ question mark
- ’\’ backslash
- ‘\a’ bell (audio)
- ‘\b’ backspace
- ‘\f’ form feed – new page
- ‘\n’ newline
- ‘\r’ carriage return
- ‘\t’ horizontal tab
- ‘\v’ vertical tab
- octal value: type = char
- ‘\377’ -> 11111111
- hexadecimal value type = char
- ‘\xff’ -> 11111111
- unicode value
- ‘\U1234’ type = char16_t (min 16bit)
- ‘\U12345678 type = char32_t (min 32bit)
- wchar_t is the longest character type
- signed char and unsigned char also exist, but here char not necessary the same as signed char
1 == sizeof(char) < sizeof(char16_t) <= sizeof(char32_t) <= sizeof(wchar_t)
Boolean
_Bool 1 (true) or 0 (false)
bool, true, false (macro)
true –> 1 false –> 0
In conditional expressions all non-zero values are TRUE values!
Conversion of _Bool differs from int conversions:
1
2
3
4
5
6
#include <stdio.h>
int main()
{
printf("_Bool == %d\t int == %d\n", (_Bool) 0.5, (int) 0.5);
return 0;
}
$ ./a.out
_Bool == 1 int == 0
Floating point numbers
- float 3.14f
- double 3.14 (as double precision)
- long double 3.14l
sizeof(float) <= sizeof(double) <= sizeof(long double)
Complex floating points
#include <complex.h>
float _Complex or float complex
double _Complex double complex
long double _Complex long double complex
Example;
1
2
3
4
5
6
7
8
#include <complex.h>
#include <stdio.h>
int main(void)
{
double complex z = 1 + 2*I;
z = 1/z;
printf("1/(1.0+2.0i) = %.1f%+.1fi\n", creal(z), cimag(z));
}
Have to link to the math library! Use the “-lm” flag!
$ gcc -ansi -pedantic -Wall -W complex.c -lm
$ ./a.out
1/(1.0+2.0i) = 0.2-0.4i
Size is not fixed! (C is NOT Java!)
int ==> best for integral computation, “machine word”
double ==> best for floating point computation