Last modified: 2023-04-08
C
Year | Informal name | C Standard |
---|---|---|
1972 | Birth | |
1978 | K&R C | |
1989 | ANSI C | |
1990 | C90 | ISO/IEC 9899:1990 |
1999 | C99 | ISO/IEC 9899:1999 |
2011 | C11, C1x | ISO/IEC 9899:2011 |
2018 | C17 | ISO/IEC 9899:2018 |
- C89 / ANSI is the most important standard, a must to know in C world
- C89 and C90 are practically identical
- C99 and C11 are nice to have
- It is recommended to use
gcc program.c -Wall -Wextra -pedantic -std=c89
to give you additional feedback and code checks - Many things from C++ were backported into C99
- like
const
, so you can avoid preprocessor's#define
- and
stdint.h
- like
- specifications of C standards (source; they are technically drafts, but are valid)
Stuff to cover
*.c
and*.cpp
contain the implementation*.h
contain the definitions or prototypes- Preprocessor
- Header files
- Macros
- construction enclosed in
(
and)
- C language is stream oriented
- Memory Layout of C Programs
Operators
Sources:
See also:
-
Unary operators
- Perform action with single variable
- Examples:
++
,++
,!
,sizeof
, etc
-
Binary operators
- Perform action with two variables
- Examples:
+
,-
,*
,>=
, etc
-
Ternary operator
?
- shorthand for
if
statement
int larger;
if (a > b)
larger = a;
else
larger = b;
int larger;
larger = (a > b) ? a : b;
Comparison operators / relational operators
Syntax | Operator |
---|---|
a == b | Equal to |
a != b | Not equal to |
a > b | Greater than |
a < b | Less than |
a >= b | Greater than or equal to |
a <= b | Less than or equal to |
C++
also has this:
Syntax | Operator |
---|---|
a <=> b | Three-way comparison |
Logic operators
Operator | Function |
---|---|
a && b | AND |
a || b | OR |
!a | NOT |
- Non-zero values are
TRUE
- Zero is always
FALSE
just like\0
Bitwise logic operators
Operator | Function |
---|---|
a & b | AND |
a | b | OR |
~a | NOT |
a ^ b | XOR |
a >> b | right shift |
a << b | left shift |
Assignment operators
Syntax | Operator name |
---|---|
a = b | Direct assignment |
a += b | Addition assignment |
a -= b | Subtraction assignment |
a *= b | Multiplication assignment |
a /= b | Division assignment |
a %= b | Modulo assignment |
a |= b | Bitwise OR assignment |
a ^= b | Bitwise XOR assignment |
a <<= b | Bitwise left shift assignment |
a >>= b | Bitwise right shift assignment |
Member and pointer operators
Syntax | Operator name |
---|---|
a[b] | Subscript |
*a | Indirection (object pointed to by a) |
&a | Address-of (address of a) |
a->b | Structure dereference (member b of object pointed to by a) |
a.b | Structure reference (member b of object a) |
Other operators
Syntax | Operator name |
---|---|
a(b, c) | Function call |
a, b | Comma |
a ? b : c | Ternary conditional |
sizeof a | sizeof |
sizeof(type) | sizeof |
(type) a | conversion / cast |
Variables
extern
static
Sources:
static
:
- A static variable inside a function keeps its value between invocations.
- When you use
static int x = 0;
, the variable is initialized to0
only on creation and is not reset in later iterations. - Can be used instead of global variable.
- When you use
- A static global variable or a function is "seen" only in the file it's declared in.
- Static variables are allocated memory in data segment, not stack segment (see Memory Layout of C Programs)
- Static variables should not be declared inside structure. The reason is C compiler requires the entire structure elements to be placed together (i.e.) memory allocation for structure members should be contiguous.
In C++
the static
can be used to define class attributes and methods shared between all objects of given class.
Arrays
Size of array
Sources:
sizeof
with first element
int a[20];
size_t length = sizeof(a) / sizeof(a[0]);
sizeof
with type
int a[20];
size_t length = sizeof(a) / sizeof(int);
Macro
#define NUM(a) (sizeof(a) / sizeof(*a))
for (i = 0; i < NUM(a); i++)
Compiler should be smart enough to not calculate the macro at compile time.
Libraries
math
vs cmath
vs math.h
vs cmath.h
- those with
.h
will pollute your global namespace with a lot of junk, those without may or may not (no guarantees) c
vsc++
: prefixc
is forC++
and is missing the.h
at the end
stdio.h
int printf ( const char * format, ... );
- print C stringint putchar ( int character );
- print single characterint puts ( const char * str);
- print C string with newlineint scanf ( cost chat * format, ... );
- read formatted data fromstdin
- for example
scanf ("format", &var);
, do not use&
for string or array - stops at first white-space character
- discouraged to input strings because of possible buffer overflow
- rather use
fgets
- rather use
- for example
char * fgets ( char * str, int num, FILE * stream );
char input[64];
fgets(input,64,stdin);
Look into format specifiers to format data.
math.h
- usually use
double
- Order of precedence
- equations are evaluated left to right
- multiplication and division are done first
- addition and subtraction
- parentheses used to prioritize some calculations
string.h
- C language does not have string, but rather arrays of characters
- final character of string is
null
character (\0
)
- final character of string is
char string[]
where brackets can be empty if immediate assignment, otherwise length of desired string + 1 for null characterchar string[] = "hello";
char string[6]; strcpy(string,"hello");
- string manipulation function are in
string.h
stdlib.h
void* malloc(size_t size);
- successful allocation returns address
- failed allocation returns
NULL
pointerNULL
is a contant pointer, use it to check if allocation was succesful (not the same thing as\0
)
char *sto;
sto = malloc( sizeof(char) * 1024 ); // want to store 1024 chars
if (sto == NULL){
printf("Unable to allocate memory\n");
return(1);
}
Pointers
- pointer is declared with
*
operator - pointer type must match variable type it is pointing at
- when used without
*
it represents an address - when used with
*
it represents the value at the address
int pokey = 987;
int *p = &pokey;
printf("The address of 'pokey' is %p\n", &pokey);
printf("The address in 'p' is %p\n", p);
printf("The value of `pokey` is %d\n", pokey);
printf("The value of `*p` is %d\n", *p);
The address of 'pokey' is 0x7ffd437e4a8c
The address in 'p' is 0x7ffd437e4a8c
The value of `pokey` is 987
The value of `*p` is 987
Pointer arithmetic
int array[] = {11, 13, 17, 19};
int *aptr, *aptr2;
aptr = array;
aptr2 = &array[1];
printf("Elements is %d\n", *aptr);
printf("Elements is %d\n", *aptr2);
printf("Elements is %d\n", array[3]);
printf("Elements is %d\n", *(aptr+3));
Elements is 11
Elements is 13
Elements is 19
Elements is 19
Misc
- Required
main()
function (this is the entry point) - operator
sizeof
returns number of bytes used by variable- can be even used of
struct
- can be even used of
- uninitialized variables contain garbage, this includes pointers
- modulo operator
%
is for remainder after integer division
sizeof
struct stuff {
int a;
float b;
char c[32];
}
printf("Sizeof struct is %lu bytes", sizeof(struct stuff) );
returns:
Sizeof struct is 40 bytes