Improve index

This commit is contained in:
Ciro Santilli 2015-04-20 22:53:33 +02:00
parent 987b26f008
commit b5b81f0d99
14 changed files with 932 additions and 629 deletions

View File

@ -1,2 +1,2 @@
# Cannoe be a symlink.
# Cannot be a symlink.
language: cpp

39
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,39 @@
# CONTRIBUTING
## Style
Non-portable features shall be clearly separated from portable ones in either:
- ifdef macro blocks
- separate files
- separate directories
- separate repositories
This includes features which were not present in the first standardized version of languages. E.g., C99 features must be put inside `#ifdf __STDC_VERSION__` blocks.
Everything that can be checked in an assertion will be checked, and will not get printed.
For example, a C addition operator `+` test should be done as:
assert(1 + 1 == 2);
and *never*:
printf("%d\n", 1 + 1);
so that all can be verified automatically.
Features which yield unpredictable outputs can print results to stdout. For example, `time(NULL)`
printf("%d\n", 1 + 1);
Features that:
- require user input such as C `scanf`
- make programs wait for perceptible amounts of time
shall be put inside a block analogous to a `if (0){ ... }` to be turned on only when users want to test those specific features.
Cheat source comments are written in markdown *indented by headers* and commented out.
Every important keyword that one might search for in the feature has a hash before it, e.g. `#function`, `#include`, `#printf`, etc.

142
README.md
View File

@ -6,113 +6,35 @@ C and C++ information, cheatsheets and mini-projects.
Relies on <https://github.com/cirosantilli/cpp-boilerplate> to factor code out. See [its documentation](https://github.com/cirosantilli/cpp-boilerplate/blob/master/README.md) for information on how to use this project.
## Most useful files
- [c.c](c.c): C cheatsheet
- [cpp.cpp](main_cpp.cpp): C++ cheatsheet
- [POSIX](posix/): POSIX C API
- [Multi-file](multifile/): `include`, `extern` vs `static`, dynamic libraries, cross language calls
- [GCC](gcc/): GCC extensions
- [OpenGL](opengl/)
- [KDE](kde/)
Other files:
- [Boost](boost/)
- [Flex and Bison](flex-bison/)
- [GDB](gdb.md)
- [glibc](glibc/)
- [Implementations](implementations.md)
- [Style guides](style-guides.md)
- [CMake](cmake.md)
- [hello_world.c](hello_world.c)
- [hello_world_cpp.cpp](hello_world_cpp.cpp)
GUI:
- [GTK](gtk/)
- [Qt](qt/)
- [X11](x11)
- [Open GL](opengl/)
Scientific:
- [Fortran](fortran/)
- [GSL](gsl/)
- [LAPACK](lapack/)
- [OpenCV](opencv/)
- [PLplot](plplot/)
## Dependencies
Most builds require:
- `make` (POSIX)
- `gcc` >= 4.7
- `g++` >= 4.7
Even though we use GNU tools by default, great attention is paid to portability of portable subjects like ANSI C, which should compile in any compiler.
In addition, each directory may have their own extra dependencies as stated in their README.
You can install dependencies on latest LTS Ubuntus with:
./configure
Other system install are not going to be supported as that would lead to too much maintenance overhead. If you don't have Ubuntu, consider using our [Vagrantfile](Vagrantfile).
## Usage
When there are multiple files compiled, e.g.:
c.c -> c
cpp.cpp -> cpp
run a given file by specifying the basename without extension:
make run=c
make run=cpp
The `=` sign is *not* optional!
Doing just `make run` in those cases will run the default file: `main`.
## Style
Non-portable features shall be clearly separated from portable ones in either:
- ifdef macro blocks
- separate files
- separate directories
- separate repositories
This includes features which were not present in the first standardized version of languages. E.g., C99 features must be put inside `#ifdf __STDC_VERSION__` blocks.
Everything that can be checked in an assertion will be checked, and will not get printed.
For example, a C addition operator `+` test should be done as:
assert(1 + 1 == 2);
and *never*:
printf("%d\n", 1 + 1);
so that all can be verified automatically.
Features which yield unpredictable outputs can print results to stdout. For example, `time(NULL)`
printf("%d\n", 1 + 1);
Features that:
- require user input such as C `scanf`
- make programs wait for perceptible amounts of time
shall be put inside a block analogous to a `if (0){ ... }` to be turned on only when users want to test those specific features.
Cheat source comments are written in markdown *indented by headers* and commented out.
Every important keyword that one might search for in the feature has a hash before it, e.g. `#function`, `#include`, `#printf`, etc.
##
1. [Getting started](getting-started.md)
1. Best content
1. [c.c](c.c): C cheatsheet
1. [cpp.cpp](main_cpp.cpp): C++ cheatsheet
1. [POSIX](posix/): POSIX C API
1. [Multi-file](multifile/): `include`, `extern` vs `static`, dynamic libraries, cross language calls
1. [GCC](gcc/): GCC extensions
1. [OpenGL](opengl/)
1. [KDE](kde/)
1. Other files
1. [Boost](boost/)
1. [Flex and Bison](flex-bison/)
1. [GDB](gdb.md)
1. [glibc](glibc/)
1. [Implementations](implementations.md)
1. [Style guides](style-guides.md)
1. [CMake](cmake.md)
1. [hello_world.c](hello_world.c)
1. [hello_world_cpp.cpp](hello_world_cpp.cpp)
1. GUI
1. [GTK](gtk/)
1. [Qt](qt/)
1. [X11](x11)
1. [Open GL](opengl/)
1. Scientific
1. [Fortran](fortran/)
1. [GSL](gsl/)
1. [LAPACK](lapack/)
1. [OpenCV](opencv/)
1. [PLplot](plplot/)
1. [CONTRIBUTING](CONTRIBUTING.md)
1. [Bibliography](bibliography.md)

59
bibliography.md Normal file
View File

@ -0,0 +1,59 @@
# Bibliography
## Free
- <http://www.cplusplus.com>
Explains well what most the features of the language do for beginners.
Not official in any way, despite the amazing URL and Google rank.
Is said to contain many errors, and that `cppreference` is superior.
- <http://en.cppreference.com/w/>
Similar to `cplusplus.com`, but seems to have more info.
Wiki driven.
Attempts to document all the language and stdlibs.
Many behaviour examples.
- <http://www.parashift.com/c++-faq/index.html>
C++ FAQ.
Deep and extensive tutorial.
- <http://herbsutter.com/gotw/>
Herb Sutter Guru of the week.
Hard topics with simple examples.
- <http://yosefk.com/c++fqa/>
Comments on the quirks of c++.
Fun and informative for those that know the language at intermediate level.
- <http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp>
IBM implementation of C++.
Contains a few extension, but lots of well explained docs with many examples.
Contains clear examples and explanations on very specific subjects.
Horrible navigation and URLs.
- <http://www.agner.org/optimize/>
Hardcore optimization tutorials for C++ and assembly.
## Non-free
- <http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list>
List of books.

444
c.c
View File

@ -203,21 +203,15 @@ Small comments on comparing ANSI C with extensions are acceptable.
*/
/*
# Preprocessor
# include
Loes simple stuff *before* compilation.
Look in standard dirs directly:
Ly simple understand non-turing complete.
#include <file.h>
# include
Looks in current dir first:
Look in standard dirs directly:
#include <file.h>
Looks in current dir first:
#include "file.h"
#include "file.h"
*/
#include <assert.h>
@ -233,7 +227,7 @@ Small comments on comparing ANSI C with extensions are acceptable.
#include <stddef.h> /* offsetof, type_t */
#include <stdlib.h> /* malloc, EXIT_SUCCESS, EXIT_FAILURE: */
#include <stdio.h> /* printf, puts */
#include <string.h> /* sprintf, strlen, strcpy, memset */
#include <string.h> /* sprintf, strlen, strcpy, memset, memcmp */
#include <math.h>
#include <time.h> /* time() */
@ -476,8 +470,8 @@ int setjmp_func(int jmp, jmp_buf env_buf) {
# overload
There is no function overloading in C to avoid name mangling:
C ABI simplifity is one of it's greatest strengths:
<http://stackoverflow.com/questions/8773992/c11-type-generic-expressions-why-not-just-add-function-overloading>
C ABI simplicity is one of it's greatest strengths:
http://stackoverflow.com/questions/8773992/c11-type-generic-expressions-why-not-just-add-function-overloading
C11 introduces generics, which allow for a similar, albeit more limited effect.
*/
@ -1556,11 +1550,13 @@ int main(int argc, char **argv) {
{ char c = (char)130; }
/* Possible via escape seqs like in strings. */
/* Possible via escape sequences are like in strings. */
{ assert(((int)'\n') == 10); }
assert(((int)'\n') == 0x0a);
assert(((int)'\'') == 0x27);
/* TODO how to make a literal backslash char? */
}
/*
@ -1793,7 +1789,8 @@ int main(int argc, char **argv) {
Language keyword.
Gives the size of the RAM representation of types in bytes.
Gives the size of the RAM representation of types **in multiples of CHAR_BIT**,
which is the size of `char`. *Not* necessarily in bytes.
The return type is `size_t.
@ -1823,11 +1820,11 @@ int main(int argc, char **argv) {
# Fixed size types
besides the base times with nonfixed sizes, c99 ANSI libc also furnishes
fixed sized types. See
Besides the base times with nonfixed sizes, c99 ANSI libc also furnishes
fixed sized types
you should only use those when having a fixed size is crucial,
otherwise just use the base c types which are optimized for speed
You should only use those when having a fixed size is crucial,
otherwise just use the base C types which are optimized for speed
according to each architecture.
*/
{
@ -1835,33 +1832,37 @@ int main(int argc, char **argv) {
size_t size = sizeof(int);
puts("sizeof (bytes):");
printf("char = %zu\n", sizeof(char) );
printf("int = %zu\n", sizeof(int) );
printf("long int = %zu\n", sizeof(long int) );
printf("long long = %zu\n", sizeof(long long) );
printf("float = %zu\n", sizeof(float) );
printf("double = %zu\n", sizeof(double) );
printf("long double = %zu\n", sizeof(long double) );
printf("wchar_t = %zu\n", sizeof(wchar_t) );
printf("size_t = %zu\n", sizeof(size_t) );
printf(" char = %zu\n", sizeof(char) );
printf(" int = %zu\n", sizeof(int) );
printf(" long int = %zu\n", sizeof(long int) );
printf(" long long = %zu\n", sizeof(long long) );
printf(" float = %zu\n", sizeof(float) );
printf(" double = %zu\n", sizeof(double) );
printf(" long double = %zu\n", sizeof(long double) );
printf(" wchar_t = %zu\n", sizeof(wchar_t) );
printf(" size_t = %zu\n", sizeof(size_t) );
/* char has fixed size: */
assert(sizeof(char) == 1 );
assert(sizeof(char) == 1 );
/* Size equality is always possible: */
assert(sizeof(short int ) <= sizeof(int ));
assert(sizeof(int ) <= sizeof(long int ));
assert(sizeof(long int ) <= sizeof(long long int ));
assert(sizeof(float ) <= sizeof(double ));
assert(sizeof(double ) <= sizeof(long double ));
/* size equality is always possible: */
/*
The following lower bounds are guaranteed.
http://stackoverflow.com/questions/1738568/any-guaranteed-minimum-sizes-for-types-in-c
*/
assert(sizeof(short int) >= 2);
assert(sizeof(long int) >= 4);
assert(sizeof(long long int) >= 8);
assert(sizeof(short int ) <= sizeof(int ));
assert(sizeof(int ) <= sizeof(long int ));
assert(sizeof(long int ) <= sizeof(long long int ));
assert(sizeof(float ) <= sizeof(double ));
assert(sizeof(double ) <= sizeof(long double ));
/* unsigned does not change sizeof: */
assert(sizeof(unsigned int) == sizeof(int));
assert(sizeof(unsigned long int) == sizeof(long int));
/* Unsigned does not change sizeof: */
assert(sizeof(unsigned int) == sizeof(int));
assert(sizeof(unsigned long int) == sizeof(long int));
}
/*
@ -3904,32 +3905,73 @@ int main(int argc, char **argv) {
assert((5 % 3) == 2);
assert((6 % 3) == 0);
}
/* # Comparison operators */
{
assert((1 == 1) == 1);
assert((0 == 1) == 0);
assert((0 > 1) == 0);
assert((0 > 0) == 0);
assert((0 > -1) == 1);
assert((0 < 1) == 1);
assert((0 < 0) == 0);
assert((0 < -1) == 0);
assert((0 >= 1) == 0);
assert((0 >= 0) == 1);
assert((0 >= -1) == 1);
assert((0 <= 1) == 1);
assert((0 <= 0) == 1);
assert((0 <= -1) == 0);
}
}
/* # Boolean operators */
/*
# Boolean operators
The boolean operators treat all integers as:
- 0: false
- != 0: true
The output of the boolean operators is always either 0 or 1.
*/
{
assert((1 == 1) == 1);
assert((0 == 1) == 0);
/*
# !
assert((0 > 1) == 0);
assert((0 > 0) == 0);
assert((0 > -1) == 1);
assert((0 < 1) == 1);
assert((0 < 0) == 0);
assert((0 < -1) == 0);
# Negation
*/
{
assert((!0) == 1);
assert((!1) == 0);
assert((!2) == 0);
assert((!-1) == 0);
assert((0 >= 1) == 0);
assert((0 >= 0) == 1);
assert((0 >= -1) == 1);
assert((0 <= 1) == 1);
assert((0 <= 0) == 1);
assert((0 <= -1) == 0);
/*
`x == 0` is equivalent to `!x`.
But its likely more readable to use `== 0` when doing comparisons,
and to leave `!x` just for boolean operations.
*/
}
/*
# ||
# or
*/
assert((0 || 0) == 0);
assert((0 || 1) == 1);
assert((1 || 0) == 1);
assert((1 || 1) == 1);
/*
# &&
# and
*/
assert((0 && 0) == 0);
assert((0 && 1) == 0);
assert((1 && 0) == 0);
@ -3958,20 +4000,28 @@ int main(int argc, char **argv) {
/* # Bitwise operators */
{
/* NOT */
/*
# ~
# NOT bitwise
*/
assert((~(char)0x00) == (char)0xFF);
assert((~(char)0xFF) == (char)0x00);
/* AND bitwise */
/*
# &
AND bitwise
*/
{
assert(((char)0x00 & (char)0x00) == (char)0x00);
assert(((char)0xFF & (char)0x00) == (char)0x00);
assert(((char)0xFF & (char)0xFF) == (char)0xFF);
/*
# even
# Even
# odd
# Odd
# Find if number is even or odd
@ -3987,12 +4037,20 @@ int main(int argc, char **argv) {
}
}
/* OR */
/*
# ||
# OR bitwise
*/
assert(((char)0x00 | (char)0x00) == (char)0x00);
assert(((char)0xFF | (char)0x00) == (char)0xFF);
assert(((char)0xFF | (char)0xFF) == (char)0xFF);
/* XOR */
/*
# ^
# XOR bitwise
*/
assert(((char)0x00 ^ (char)0x00) == (char)0x00);
assert(((char)0xFF ^ (char)0x00) == (char)0xFF);
assert(((char)0xFF ^ (char)0xFF) == (char)0x00);
@ -5196,28 +5254,84 @@ int main(int argc, char **argv) {
}
}
/* # String literals */
/*
# String literals
http://en.cppreference.com/w/c/language/string_literal
*/
{
/* Escape chars in string conts */
{
puts("Backslash escapes:");
puts(">>>\"<<< double quotes");
puts(">>>\\<<< backslash");
puts(">>>\n<<< new line");
puts(">>>\t<<< tab char");
puts(">>>\f<<< feed char");
puts(">>>\v<<< vertical tab");
puts(">>>\r<<< carriage return");
puts(">>>\a<<< alert (your terminal may interpret this as a sound beep or not)");
puts(">>>\x61<<< a in hexadecimal");
/* Chinese UTF-8. */
puts(">>>\xe4\xb8\xad<<< zhong1, chinese for \"middle\" in utf8");
/* \0 is the NUL char, but you can't insert is directly on the literal, */
/* or else the string is interpreted to end there since C strigs are NUL terminated. */
/* Octal bytes */
assert(!strcmp("\141", "a"));
/* Hexadecimal bytes */
{
assert(!strcmp("\x61", "a"));
/*
WARNING: Hex escape out of range.
Happens because f can be part of a hex literal,
and C tries to put it together.
TODO what happens exactly according to ANSI C?
Undefined behaviour?
*/
/*{ "\xfff"; }*/
/*
The solution is to either concatenate strings, or use another escape:
*/
assert(strcmp("\xff""f", "\xff\x66") == 0);
/* Chinese UTF-8. */
puts(">>>\xe4\xb8\xad<<< zhong1, chinese for \"middle\" in utf8");
}
/*
\0 is the NUL char, but you can't insert is directly on the literal,
or else the string is interpreted to end there since C strigs are NUL terminated.
*/
printf(">>>%c<<< NUL char\n", '\0');
/* \e is a notable GNU extension for the ESC character. */
/* Double quotes. */
assert(strcmp("\"", "\x22") == 0);
/* Single quote. Likely exists for symmetry with character literals. */
assert(strcmp("\'", "\x27") == 0);
/* Backslash. */
assert(strcmp("\\", "\x5c") == 0);
/*
WARNING: Unknown escape sequence. TODO what ANSI C says can happen?
*/
/*assert(strcmp("\c", "\x0b") == 0);*/
/* Alert. Your terminal may interpret this as a sound beep or not. */
assert(strcmp("\a", "\x07") == 0);
/* Backspace. */
assert(strcmp("\b", "\x08") == 0);
/* Feed */
assert(strcmp("\f", "\x0c") == 0);
/* New line */
assert(strcmp("\n", "\x0a") == 0);
/* Carriage return */
assert(strcmp("\r", "\x0d") == 0);
/* Tab */
assert(strcmp("\t", "\x09") == 0);
/* Vertical tab */
assert(strcmp("\v", "\x0b") == 0);
/* Famous extensions: \e GNU for ESC */
}
/* String literals may be concatenated */
@ -6159,7 +6273,13 @@ int main(int argc, char **argv) {
assert(getenv("NOT_DEFINED") == NULL);
}
/* # preprocessor */
/*
# preprocessor
Does simple operations before compilation.
Not Turing complete.
*/
{
/*
# #define
@ -6170,6 +6290,16 @@ int main(int argc, char **argv) {
Use defines with discretion: they make it much harder to debug!
*/
{
/*
Syntax: the line must start with `#`,
but there can be spaces after it to give indentation.
*/
{
# define SPACE_AFTER_HASH 1
assert(SPACE_AFTER_HASH == 1);
}
/* Constants. */
{
#define A B
@ -6337,7 +6467,11 @@ int main(int argc, char **argv) {
}
/*
# #if ##else
# #if
# #else
# #elif
The preprocessor can do certain integer arithmetic operations such as: +, -, ==, <.
*/
@ -7011,39 +7145,33 @@ int main(int argc, char **argv) {
TODO what happens when a wrong type is passed? Typecast? Undefined?
*/
{
printf("u UINT_MAX = %u\n", UINT_MAX);
printf("u UINT_MAX = %u\n", UINT_MAX);
sprintf(s, "%d", UINT_MAX);
assert(strcmp(s, "-1") == 0);
sprintf(s, "%d", UINT_MAX);
assert(strcmp(s, "-1") == 0);
}
/* char: */
/* char */
sprintf(s, "%c", 'a');
assert(strcmp(s, "a") == 0);
sprintf(s, "%c", 'a');
assert(strcmp(s, "a") == 0);
/* int: */
printf("d INT_MAX = %d\n", INT_MAX);
/* int */
printf("d INT_MAX = %d\n", INT_MAX);
/* long int: */
printf("d LONG_MAX = %ld\n", LONG_MAX);
printf("d LONG_MAX = %ld\n", LONG_MAX);
/* long long (int): */
printf("lld LLONG_MAX = %lld\n", LLONG_MAX);
printf("lld LLONG_MAX = %lld\n", LLONG_MAX);
/* # floating point numbers */
{
/* float and double both use the the same char `f` char: */
printf("printf float = %f\n", 1.0f);
printf("printf double = %f\n", 1.0);
printf("printf float = %f\n", 1.0f);
printf("printf double = %f\n", 1.0);
/* long double: */
printf("f = %Lf\n", (long double)1.0);
printf("f = %Lf\n", (long double)1.0);
/* # control number of zeros after dot */
{
@ -7160,7 +7288,7 @@ int main(int argc, char **argv) {
#endif
/*
pointers
# printf Pointers
prints the hexadeciamal linear address.
@ -7230,7 +7358,7 @@ int main(int argc, char **argv) {
#endif
/*
# escape percentage.
# Escape percentage.
Note that `%` is printf specific,
not string literal specific,
@ -7497,7 +7625,9 @@ int main(int argc, char **argv) {
}
/*
# file streams #file io
# File streams
# File IO
To get streams that deal with files, use `fopen`.
@ -7530,16 +7660,16 @@ int main(int argc, char **argv) {
Windows also does trailing \z magic for ultra backwards compatibility.
Therefore for portability, always use this when you are going to do IO with binary IO functions
such as fwrite.
Therefore for portability, always use this when you are going to do IO
with binary IO functions such as fwrite.
In case of error:
- return `NULL` and set `errno`.
# text IO vs #binary IO
# Text IO vs # Binary IO
# text vs binary for numerical types
# Text vs binary for numerical types
Example: an int 123 can be written to a file in two ways:
@ -7557,7 +7687,7 @@ int main(int argc, char **argv) {
- it much shorter for large integers
- inevitable for data that cannot be interpretred as text (images, executables)
# newline vs carriage return newline
# Newline vs carriage return newline
Newline carriage return realated TODO confirm
@ -7592,13 +7722,16 @@ int main(int argc, char **argv) {
Returns number of elements written.
If less elements are written than required an erro ocurred.
If less elements are written than required an error ocurred.
Why take both bytes per item and items instead of just total bytes:
<http://stackoverflow.com/questions/295994/what-is-the-rationale-for-fread-fwrite-taking-size-and-count-as-arguments>
http://stackoverflow.com/questions/295994/what-is-the-rationale-for-fread-fwrite-taking-size-and-count-as-arguments
It seems that no less than size per item can be writen, so we are guaranteed
that some object will not be half writen.
The byte order is implementation defined.
This is therefore not a valid way to serialize data across machines.
*/
{
fp = fopen(path, "wb");
@ -7646,6 +7779,34 @@ int main(int argc, char **argv) {
}
}
assert(memcmp(elems_read, elems_write, nelems) == 0);
/*
# Endianess
# Byte order
The C standard does not specify how bytes are ordered in memory.
http://www.ibm.com/developerworks/aix/library/au-endianc/
*/
{
/*
Check endianess.
Works because `short int` is guaranteed to be at least of size 2.
We must work with pointers, because doing `(char)i` directly is specified ot be 1.
The compilers produces the assembly code required to do so taking endianess into consideration.
*/
{
const short int i = 1;
if ((*(char*)&i) == 0) {
printf("Endianess = big\n");
} else {
printf("Endianess = small\n");
}
}
}
}
/*
@ -7658,7 +7819,7 @@ int main(int argc, char **argv) {
/*freopen("/dev/null", "r", stdin);*/
}
/* # reposition read write */
/* # Reposition read write */
{
/*
For new code, always use `fgetpos` and `fsetpos` unless you absolutely
@ -9059,27 +9220,43 @@ int main(int argc, char **argv) {
in the current architecure
*/
{
/* # INT_MAX #UINT_MAX */
printf("CHAR_MAX = %d\n", CHAR_MAX);
assert(CHAR_MAX == 127);
printf("INT_MAX = %d\n", INT_MAX);
printf("INT_MIN = %d\n", INT_MIN);
printf("LONG_MAX = %ld\n", LONG_MAX);
printf("LLONG_MIN = %lld\n", LLONG_MIN);
puts("limits.h");
/*
# CHAR_BIT
Numbers of bits in a char.
POSIX fixes it to 8 TODO reference.
But it is very rare to finda a system where it will not be 8.
`sizeof` returns results in multiples of it.
*/
printf(" CHAR_BIT = %d\n", CHAR_BIT);
/* Guaranteed. */
assert(CHAR_BIT >= 8);
/* TODO Not determined by CHAR_BIT? */
printf(" CHAR_MAX = %d\n", CHAR_MAX);
/* # INT_MAX */
printf(" INT_MAX = %d\n", INT_MAX);
printf(" INT_MIN = %d\n", INT_MIN);
printf(" LONG_MAX = %ld\n", LONG_MAX);
printf(" LLONG_MIN = %lld\n", LLONG_MIN);
/*
Unsigned versions are prefiexed by `U`.
There is no MIN macro for unsigned versions since it is necessarily `0`.
*/
printf("UINT_MAX = %u\n", UINT_MAX);
printf(" UINT_MAX = %u\n", UINT_MAX);
}
/*
# float.h
gives characteristics of floating point numbers and of base numerical operations
Gives characteristics of floating point numbers and of base numerical operations
for the current architecture
All macros that start with FLT have versions starting with:
@ -9088,6 +9265,7 @@ int main(int argc, char **argv) {
- LDBL for `long double`
*/
{
puts("float.h");
/*
# FLT_ROUNDS
@ -9105,7 +9283,7 @@ int main(int argc, char **argv) {
TODO0 can it be changed?
*/
{
printf("FLT_ROUNDS = %d\n", FLT_ROUNDS);
printf(" FLT_ROUNDS = %d\n", FLT_ROUNDS);
}
/*
@ -9119,7 +9297,7 @@ int main(int argc, char **argv) {
TODO0 understand better
*/
{
printf("FLT_EVAL_METHOD = %d\n", FLT_EVAL_METHOD);
printf(" FLT_EVAL_METHOD = %d\n", FLT_EVAL_METHOD);
}
/*
@ -9131,9 +9309,9 @@ int main(int argc, char **argv) {
and support is optional.
*/
{
printf("FLT_MIN = %a\n", FLT_MIN);
printf("DBL_MIN = %a\n", DBL_MIN);
printf("LDBL_MIN = %La\n", LDBL_MIN);
printf(" FLT_MIN = %a\n", FLT_MIN);
printf(" DBL_MIN = %a\n", DBL_MIN);
printf(" LDBL_MIN = %La\n", LDBL_MIN);
}
/*
@ -9150,7 +9328,7 @@ int main(int argc, char **argv) {
TODO0 wow, there are non radix 2 representation implementations?!
*/
{
printf("FLT_RADIX = %d\n", FLT_RADIX);
printf(" FLT_RADIX = %d\n", FLT_RADIX);
}
#if __STDC_VERSION__ >= 201112L
@ -9196,15 +9374,15 @@ int main(int argc, char **argv) {
- 1: yes
*/
{
printf("FLT_HAS_SUBNORM = %d\n", FLT_HAS_SUBNORM);
printf("DBL_HAS_SUBNORM = %d\n", DBL_HAS_SUBNORM);
printf("LDBL_HAS_SUBNORM = %d\n", LDBL_HAS_SUBNORM);
printf(" FLT_HAS_SUBNORM = %d\n", FLT_HAS_SUBNORM);
printf(" DBL_HAS_SUBNORM = %d\n", DBL_HAS_SUBNORM);
printf(" LDBL_HAS_SUBNORM = %d\n", LDBL_HAS_SUBNORM);
assert(isnormal(LDBL_MIN));
if (LDBL_HAS_SUBNORM) {
long double ldbl_min_2 = LDBL_MIN / 2.0;
printf("LDBL_MIN / 2.0 = %La\n", ldbl_min_2);
printf(" LDBL_MIN / 2.0 = %La\n", ldbl_min_2);
assert(ldbl_min_2 != 0);
assert(ldbl_min_2 != LDBL_MIN);
assert(! isnormal(ldbl_min_2));
@ -9593,7 +9771,7 @@ int main(int argc, char **argv) {
}
/*
# main return #return
# main return
Valid returns are:

56
cpp.cpp
View File

@ -159,62 +159,6 @@ Features which are identical to C will not be described.
- <http://stackoverflow.com/questions/6163683/cycles-in-family-tree-software>
Funny...
# Sources
# Free
- <http://www.cplusplus.com>
Explains well what most the features of the language do for beginners.
Not official in any way, despite the amazing url and google rank.
Is said to contain many errors, and that cppreference is superior.
- <http://en.cppreference.com/w/>
Similar to cplusplus.com, but seems to have more info.
Wiki driven.
Attempts to document all the language and stdlibs.
Many behaviour examples.
- <http://www.parashift.com/c++-faq/index.html>
C++ faq.
Deep and extensive tutorial.
- <http://herbsutter.com/gotw/>
Herb Sutter Guru of the week.
Hard topics with simple examples.
- <http://yosefk.com/c++fqa/>
Comments on the quirks of c++.
Fun and informative for those that know the language at intermediate level.
- <http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp>
IBM implementation of C++.
Contains a few extension, but lots of well explained docs with many examples.
Contains clear examples and explanations on very specific subjects.
Horrible navigation and urls.
# Non-free
- <http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list>
List of books.
*/
/*

View File

@ -12,30 +12,29 @@ int nested() {
/* Attribute */
/* # Function attributes */
char not_aligned16 = 0;
char aligned16 __attribute__ ((aligned (16))) = 0;
int sprintf_wrapper(char *s, int useless, const char *fmt, int useless2, ...) {
int ret;
va_list args;
va_start(args, useless2);
ret = vsprintf(s, fmt, args);
va_end(args);
return ret;
}
/* Format */
int sprintf_wrapper(char *s, int useless, const char *fmt, int useless2, ...) {
int ret;
va_list args;
va_start(args, useless2);
ret = vsprintf(s, fmt, args);
va_end(args);
return ret;
}
/*
3 says: the 3rd argument is the format string
5 says: the va_list starts at the 5th argument
Declaration and definition *must* be separated.
*/
int sprintf_wrapper_attr(char *s, int useless, const char *fmt, int useless2, ...) __attribute__((format(printf, 3, 5)));
int sprintf_wrapper_attr(char *s, int useless, const char *fmt, int useless2, ...)
__attribute__((format(printf, 3, 5)));
int sprintf_wrapper_attr(char *s, int useless, const char *fmt, int useless2, ...) {
int ret;
@ -61,7 +60,7 @@ int nested() {
void func_not_used(){}
//warn_unused_result
/* warn_unused_result */
int func_warn_unused_result() __attribute__((warn_unused_result));
int func_warn_unused_result(){ return 0; }
@ -84,7 +83,7 @@ int nested() {
exit(EXIT_SUCCESS);
}
//WARNING: control reaches end of non void function
/* WARNING: control reaches end of non void function */
/*
int noreturn_possible(int n) {
if (n > 0)
@ -288,10 +287,11 @@ int main() {
/* This would cause a redefinition error: */
//int nested()
//{
// return 2;
//}
/*
int nested() {
return 2;
}
*/
/* Like variable redefinitions, the nested version overrides all external version */
/* which have become completelly innacessible */
@ -302,7 +302,7 @@ int main() {
/*
# Preprocessor defines
Full list: <http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros>
Full list: http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros
View all macros that would be automatically defined:
@ -318,7 +318,7 @@ int main() {
`__GNUC_MINOR__` : minor
`__GNUC_PATCHLEVEL__`: patch
<http://stackoverflow.com/questions/259248/how-do-i-test-the-current-version-of-gcc>
http://stackoverflow.com/questions/259248/how-do-i-test-the-current-version-of-gcc
There is also:
@ -355,17 +355,27 @@ int main() {
#endif
/*
gcc defines architecture macros TODO where?
# Architecture detection macro
you can find a list of those macros: <http://sourceforge.net/p/predef/wiki/Architectures/>
http://stackoverflow.com/questions/152016/detecting-cpu-architecture-compile-time
GCC defines architecture macros TODO where?
Seems to use the list: http://sourceforge.net/p/predef/wiki/Architectures/
*/
#ifdef __i386__
puts("__i386__");
#elif __x86_64__
puts("__x86_64__");
#endif
/*
gcc defines OS macros TODO where?
# OS detection macro
http://stackoverflow.com/questions/142508/how-do-i-check-os-with-a-preprocessor-directive
Same riddle as architecture detection.
*/
#ifdef __linux__
@ -376,6 +386,8 @@ int main() {
/*
# Attribute
https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax
Specifies special attributes of functions or data.
There are three types of attributes:
@ -408,7 +420,7 @@ int main() {
[[vendor::attr5]] return i;
}
and two attributes; noreturn and carries_dependency.
and two attributes; `noreturn` and `carries_dependency`.
# Multiple attributes
@ -427,7 +439,7 @@ int main() {
See next section.
# Eliminating __attribute__ on non gnu projects
# Eliminating __attribute__ on non-GNU projects
This is really easy:
@ -445,110 +457,117 @@ int main() {
*/
{
/*
# format
# Function attributes
If this is used, gcc can check if printf format strings are correct because of the use of attributes,
and emmit errors otherwise.
https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
*/
{
char s[32];
sprintf_wrapper(s, 0, "%c", 0, 'a');
assert(s[0] == 'a');
sprintf_wrapper_attr(s, 0, "%c", 0, 'b');
assert(s[0] == 'b');
/*
With `__attribute__((format,X,Y))` the compile time error checking gets done.
# format
If this is used, gcc can check if printf format strings are correct because of the use of attributes,
and emmit errors otherwise.
*/
{
//compile error check not done
//could segfault at runtime
if (0) {
sprintf_wrapper(s, 0, "%s", 0);
}
char s[32];
sprintf_wrapper(s, 0, "%c", 0, 'a');
assert(s[0] == 'a');
//compile error check is done
sprintf_wrapper_attr(s, 0, "%c", 0, 'b');
assert(s[0] == 'b');
/*
With `__attribute__((format,X,Y))` the compile time error checking gets done.
*/
{
//sprintf_wrapper_attr(s, 0, "%s", 0);
/* Compile error check not done. */
/* Could segfault at runtime. */
if (0) {
sprintf_wrapper(s, 0, "%s", 0);
}
/* Compile error check is done. */
{
/*sprintf_wrapper_attr(s, 0, "%s", 0);*/
}
}
}
}
/*
# deprecated
/*
# deprecated
Using a function marked as deprecated will emmit warnings.
*/
{
//func_deprecated();
}
Using a function marked as deprecated will emmit warnings.
*/
{
/*func_deprecated();*/
}
/*
# used
/*
# used
Useful when the function may be called from assembly code, in which case GCC
may not be easily able to detect that it was called.
Useful when the function may be called from assembly code, in which case GCC
may not be easily able to detect that it was called.
TODO0 what is this for? If a func is not called, what does gcc do? Remove it from text?
*/
{
}
TODO0 what is this for? If a func is not called, what does gcc do? Remove it from text?
*/
{
}
/*
# warn_unused_result
/*
# warn_unused_result
Always emmit a warning if the return value is not used.
Always emmit a warning if the return value is not used.
Useful to enforce callers to do error checks when the return value signals the error.
*/
{
/* No warning. */
func_not_warn_unused_result();
Useful to enforce callers to do error checks when the return value signals the error.
*/
{
/* No warning. */
func_not_warn_unused_result();
assert(func_warn_unused_result() == 0);
assert(func_warn_unused_result() == 0);
//WARNING ignored return value
/* WARNING ignored return value */
//func_warn_unused_result();
}
/*func_warn_unused_result();*/
}
/*
# const
/*
# const
A function marked const may be optimized in the sense that the compiler calculates its value at compile time,
or chaches its result of each calculation.
A function marked const may be optimized in the sense that the compiler calculates its value at compile time,
or chaches its result of each calculation.
A function can only be marked const if:
A function can only be marked const if:
- its return value is only a function of its arguments, and not of any global or static function variable
- the function has no desired side effect besides returning the value
- its return value is only a function of its arguments, and not of any global or static function variable
- the function has no desired side effect besides returning the value
Marking a function which does one of the above const will lead to serious hard to find bugs.
*/
{
assert(next(0) == 1);
assert(next(0) == 1);
assert(next_const(0) == 1);
assert(next_const(0) == 1);
}
Marking a function which does one of the above const will lead to serious hard to find bugs.
*/
{
assert(next(0) == 1);
assert(next(0) == 1);
assert(next_const(0) == 1);
assert(next_const(0) == 1);
}
/*
# always_inline
/*
# always_inline
Always inline the function.
Always inline the function.
ANSI C99 `inline` does not guarantee that, it only hints it to the compiler.
ANSI C99 `inline` does not guarantee that, it only hints it to the compiler.
Must see generated assembly code to notice this (except for the possible desired speedup effect).
Must see generated assembly code to notice this (except for the possible desired speedup effect).
On `gcc -O0 4.7`, only the `incr_always_inline` was inlined.
*/
{
int i = 0;
i = incr(i);
i = incr_inline(i);
i = incr_always_inline(i);
On `gcc -O0 4.7`, only the `incr_always_inline` was inlined.
*/
{
int i = 0;
i = incr(i);
i = incr_inline(i);
i = incr_always_inline(i);
}
}
/*
@ -612,7 +631,7 @@ int main() {
GCC built-ins for vectorized SIMD operations.
<http://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html>
http://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
Allowed operators: +, -, *, /, unary minus, ^, |, &, ~, %, ==, !=, <, <=, >, >=
@ -658,7 +677,7 @@ int main() {
# asm
Great intro: <http://www.ibm.com/developerworks/library/l-ia/index.html>
Great intro: http://www.ibm.com/developerworks/library/l-ia/index.html
Can be used if you really, really want to optimize at the cost of:
@ -682,10 +701,13 @@ int main() {
where:
- commands: actual gas code into a single c string. Remember: each command has to end in newline or `;`.
- outputs: start with `=`. gcc has to enforce is that at the end of the `asm` block that those values are set.
- inputs:
- clobbered registers:
- commands: actual gas code into a single c string. Remember: each command has to end in newline or `;`.
- outputs: start with `=`. gcc has to enforce is that at the end of the `asm` block that those values are set.
- inputs:
- clobbered registers:
Registers that may be modified explicitly in the assembly code.
@ -728,7 +750,7 @@ int main() {
{
int in = 1;
int out = 0;
//out = in
/*out = in*/
asm volatile (
"movl %1, %%eax;"
"movl %%eax, %0"
@ -742,7 +764,7 @@ int main() {
/* No input. */
{
int out = 0;
//out = 1
/*out = 1*/
asm volatile (
"movl $1, %0"
: "=m" (out)
@ -754,7 +776,7 @@ int main() {
{
float in = 1.0;
float out = 0.0;
//out = -in
/*out = -in*/
asm volatile (
"flds %1;"
"fchs;"
@ -768,7 +790,7 @@ int main() {
/* Input and ouput can be the same memory location. */
{
float x = 1.0;
//x = -x
/*x = -x*/
asm (
"flds %1;"
"fchs;"
@ -810,7 +832,7 @@ int main() {
{
int in = 0;
int out = 0;
//out = in + 2
/*out = in + 2*/
asm (
"incl %1;"
"movl %1, %0;"
@ -924,7 +946,7 @@ int main() {
Get address that function will return to after return.
It seems that it is not possible to jump to a location without assemby:
<http://stackoverflow.com/questions/8158007/how-to-jump-the-program-execution-to-a-specific-address-in-c>
http://stackoverflow.com/questions/8158007/how-to-jump-the-program-execution-to-a-specific-address-in-c
This is most useful for debugging.
*/

6
gdb.md
View File

@ -155,6 +155,12 @@ So here we see that:
TODO understand everything
## Step backwards in time
## Omniscient debugging
Considered a "high priority project" by the FSF as of January 2015 <http://www.fsf.org/campaigns/priority-projects/reversible-debugging-in-gdb>
---
TODO format the rest of this section as md:

35
getting-started.md Normal file
View File

@ -0,0 +1,35 @@
# Getting started
## Dependencies
Most builds require:
- `make` (POSIX)
- `gcc` >= 4.7
- `g++` >= 4.7
Even though we use GNU tools by default, great attention is paid to portability of portable subjects like ANSI C, which should compile in any compiler.
In addition, each directory may have their own extra dependencies as stated in their README.
You can install dependencies on latest LTS Ubuntus with:
./configure
Other system install are not going to be supported as that would lead to too much maintenance overhead. If you don't have Ubuntu, consider using our [Vagrantfile](Vagrantfile).
## Usage
When there are multiple files compiled, e.g.:
c.c -> c
cpp.cpp -> cpp
run a given file by specifying the basename without extension:
make run=c
make run=cpp
The `=` sign is *not* optional!
Doing just `make run` in those cases will run the default file: `main`.

View File

@ -2,4 +2,5 @@
int main() {
puts("Hello world C.");
return 0;
}

View File

@ -1 +1,9 @@
# POSIX C API
## Bibliography
- <http://www.amazon.com/Beginning-Linux-Programming-Neil-Matthew/dp/0470147628>
Matthew; Stones - Beginning Linux Programming.
Very good intro do many of POSIX utilities with interesting examples and topics.

View File

@ -426,6 +426,8 @@ int main(int argc, char** argv) {
}
/*
# File IO
# File descriptors
`int` identifier to a data stream.
@ -481,29 +483,30 @@ int main(int argc, char** argv) {
Flags. Must specify one and only of the following:
- O_WRONLY: write only
- O_RDONLY: read only.
- `O_WRONLY`: write only
- `O_RDONLY`: read only.
Undefined behaviour with O_TRUNC.
TODO0 can be used with O_CREAT?
- O_RDWR: read and write
- `O_RDWR`: read and write
Other important flags.
- O_APPEND: If the file exists, open fd at the end of the file.
- `O_APPEND`: If the file exists, open fd at the end of the file.
- O_TRUNC: If the file exists, open fd at the end of the file,
- `O_TRUNC`: If the file exists, open fd at the end of the file,
set its length to zero, discarding existing contents.
Undefined behaviour with O_RDONLY.
- O_CREAT: If the file does not exit, creat it, with permissions given in mode.
- `O_CREAT`: If the file does not exit, creat it, with permissions given in mode.
Mode must be specified when this flag is set, and is ignored if this is not set.
- O_EXCL: Used with O_CREAT, ensures that the caller creates the file.
- `O_EXCL`: Used with O_CREAT, ensures that the caller creates the file.
The open is atomic; that is, no two opens can open at the same time.
@ -716,7 +719,7 @@ int main(int argc, char** argv) {
}
}
//read
/* read */
{
fd = open(fname, O_RDONLY);
if (fd == -1) {
@ -741,7 +744,7 @@ int main(int argc, char** argv) {
}
}
//BAD forget O_CREAT on non-existent file gives ENOENT
/* BAD forget O_CREAT on non-existent file gives ENOENT */
{
fd = open("/i/do/not/exist", O_RDONLY, S_IRWXU);
if (fd == -1) {
@ -751,7 +754,7 @@ int main(int argc, char** argv) {
}
}
//BAD write on a O_RDONLY fd gives errno EBADF
/* BAD write on a O_RDONLY fd gives errno EBADF */
{
int fd;
char *fname = "write_rdonly.tmp";
@ -785,13 +788,15 @@ int main(int argc, char** argv) {
}
/*
open and write without truncate
Open and write without truncate.
after write 1: abcd
after write 2: 01cd
Output:
after write 1: abcd
after write 2: 01cd
*/
{
//set file to abc
/* Set file to `abc`. */
{
fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
if (fd == -1) {
@ -809,7 +814,7 @@ int main(int argc, char** argv) {
}
}
//open and write to it without truncating
/* Open and write to it without truncating. */
{
fd = open(fname, O_RDWR);
if (fd == -1) {
@ -823,7 +828,7 @@ int main(int argc, char** argv) {
}
}
//check the new result
/* Check the new result. */
{
if (lseek(fd, 0, SEEK_SET) != 0) {
perror("lseek");
@ -833,7 +838,7 @@ int main(int argc, char** argv) {
perror("read");
exit(EXIT_FAILURE);
} else {
//the first two bytes were overwriten
/* The first two bytes were overwriten. */
assert(memcmp(out, "01cd", nbytes) == 0);
}
if (close(fd) == -1) {
@ -864,7 +869,7 @@ int main(int argc, char** argv) {
perror("write");
exit(EXIT_FAILURE);
}
// Read after eof, return 0 and read nothing.
/* Read after eof, return 0 and read nothing. */
if (read(fd, out, 1) != 0) {
assert(false);
}
@ -872,7 +877,7 @@ int main(int argc, char** argv) {
perror("lseek");
exit(EXIT_FAILURE);
}
// Byte 0 was never writen, so reading it returns `(int)0`.
/* Byte 0 was never writen, so reading it returns `(int)0`. */
if (read(fd, out, 2) != 2) {
perror("read");
exit(EXIT_FAILURE);
@ -908,6 +913,39 @@ int main(int argc, char** argv) {
printf("STDOUT_FILENO = %d\n", STDOUT_FILENO);
printf("STDERR_FILENO = %d\n", STDERR_FILENO);
}
/*
# aio family
# Asynchronous IO
# aio_cancel
# aio_error
# aio_fsync
# aio_read
# aio_return
# aio_suspend
# aio_write
Great soruce: <http://www.fsl.cs.sunysb.edu/~vass/linux-aio.txt>
In Linux, implemented with the system calls:
io_cancel(2) 2.6
io_destroy(2) 2.6
io_getevents(2) 2.6
io_setup(2) 2.6
io_submit(2) 2.6
*/
{
/* TODO */
}
}
/*
@ -937,7 +975,7 @@ int main(int argc, char** argv) {
char *oldpath = "link_old.tmp";
char *newpath = "link_new.tmp";
// Create old.
/* Create old. */
fd = open(oldpath, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
if (fd == -1) {
perror("open");
@ -1034,16 +1072,17 @@ int main(int argc, char** argv) {
TODO application?
*/
{
char *filepath = "mmap.tmp";
char* filepath = "mmap.tmp";
int numints = 4;
int filesize = numints * sizeof(int);
int i;
int fd;
int result;
int *map; /* mmapped array of int's */
/* mmapped array of int's */
int* map;
// Write to file with mmap.
/* Write to file with mmap. */
{
/* `O_WRONLY` is not sufficient when mmaping, need `O_RDWR`.*/
fd = open(filepath, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
@ -1094,7 +1133,7 @@ int main(int argc, char** argv) {
}
}
// Read result back in.
/* Read result back in. */
{
fd = open(filepath, O_RDONLY, 0);
if (fd == -1) {
@ -1111,9 +1150,9 @@ int main(int argc, char** argv) {
assert(map[1] == 1);
// Segmentation fault because no `PROT_WRITE`:
/* Segmentation fault because no `PROT_WRITE`: */
{
//map[1] = 2;
/*map[1] = 2;*/
}
if (munmap(map, filesize) == -1) {
@ -1137,7 +1176,7 @@ int main(int argc, char** argv) {
TODO0 application?
*/
{
// Private write
/* Private write */
{
fd = open(filepath, O_RDONLY, 0);
if (fd == -1) {
@ -1165,7 +1204,7 @@ int main(int argc, char** argv) {
}
}
// Read
/* Read */
{
fd = open(filepath, O_RDONLY, 0);
if (fd == -1) {
@ -1180,7 +1219,7 @@ int main(int argc, char** argv) {
exit(EXIT_FAILURE);
}
//did not change!
/* Did not change! */
assert(map[0] == 0);
if (munmap(map, filesize) == -1) {
@ -1196,7 +1235,7 @@ int main(int argc, char** argv) {
}
}
//#pathname operations
/* # Pathname operations */
{
/*
# realpath
@ -1285,7 +1324,6 @@ int main(int argc, char** argv) {
- portable lightweight: dirent.h
*/
{
/*
# stat family
@ -1396,7 +1434,7 @@ int main(int argc, char** argv) {
}
}
//#mkdir
/* # mkdir */
{
struct stat s;
char fname[] = "mkdir";
@ -1410,7 +1448,7 @@ int main(int argc, char** argv) {
assert(false);
}
//#rmdir
/* # rmdir */
{
mkdir("rmdir", 0777);
if(rmdir("rmdir") == -1)
@ -1556,11 +1594,10 @@ int main(int argc, char** argv) {
}
}
// OK, enough of error checking from now on.
/* OK, enough of error checking from now on. */
printf("RLIM_INFINITY = %ju\n", (uintmax_t)RLIM_INFINITY);
// maximum total CPU usage in seconds.
/* maximum total CPU usage in seconds. */
getrlimit(RLIMIT_CPU, &limit);
printf(
"RLIMIT_CPU\n soft = %ju\n hard = %ju\n",
@ -1568,7 +1605,7 @@ int main(int argc, char** argv) {
(uintmax_t)limit.rlim_max
);
// Maximum file size in bytes.
/* Maximum file size in bytes. */
getrlimit(RLIMIT_FSIZE, &limit);
printf(
"RLIMIT_FSIZE\n soft = %ju\n hard = %ju\n",
@ -1576,7 +1613,7 @@ int main(int argc, char** argv) {
(uintmax_t)limit.rlim_max
);
// Number of file descriptors:
/* Number of file descriptors: */
getrlimit(RLIMIT_NOFILE, &limit);
printf(
"RLIMIT_NOFILE\n soft = %ju\n hard = %ju\n",
@ -1660,13 +1697,11 @@ int main(int argc, char** argv) {
Similar to sysconf, but for parameters that depend on a path, such as maxium filename lengths.
*/
{
// Max basename in given dir including trailling null:
/* Max basename in given dir including trailling null: */
printf("pathconf(\".\", _PC_NAME_MAX) = %ld\n", pathconf(".", _PC_NAME_MAX));
printf("pathconf(\".\", _PC_NAME_MAX) = %ld\n", pathconf(".", _PC_NAME_MAX));
// Max pathname in (TODO this is per device?)
printf("pathconf(\".\", _PC_PATH_MAX) = %ld\n", pathconf(".", _PC_PATH_MAX));
/* Max pathname in (TODO this is per device?) */
printf("pathconf(\".\", _PC_PATH_MAX) = %ld\n", pathconf(".", _PC_PATH_MAX));
}
}

View File

@ -10,159 +10,163 @@ To send arbitrary signals to a process from a terminal, consider using the `kill
Also consider the convenient non POSIX stadardized VT100 control characters such as `<C-C>`
which generate certain signals such as `SIGTERM`.
#ANSI
# ANSI signals
ANSI C supports the concept of signals, and only POSIX specific features shall be discussed here.
ANSI C supports the concept of signals, and only POSIX specific features shall be discussed here.
Please look for ANSI C info for any feature used but not explained here.
Please look for ANSI C info for any feature used but not explained here.
Linux extends POSIX by adding new signals, Those shall not be discussed here.
Linux extends POSIX by adding new signals, Those shall not be discussed here.
#POSIX
# POSIX signals
Docs here: <http://pubs.opengroup.org/onlinepubs/009696699/basedefs/signal.h.html>.
Docs here: http://pubs.opengroup.org/onlinepubs/009696699/basedefs/signal.h.html
POSIX defines several signals in addition to the ANSI C signals.
POSIX defines several signals in addition to the ANSI C signals.
As in ANSI C, each signal has the following attributes:
As in ANSI C, each signal has the following attributes:
- general description of which conditions generate the signal
- general description of which conditions generate the signal
- the signal can or cannot be handled.
- the signal can or cannot be handled.
Most signals can be handled, but there are a few exceptions such as:
Most signals can be handled, but there are a few exceptions such as:
- `SIGKILL`: always kill processes, cannot be handled.
- `SIGKSTOP` and `SIGCONT`
- `SIGKILL`: always kill processes, cannot be handled.
- `SIGKSTOP` and `SIGCONT`
- default action to take
- default action to take
For signals that can be handled, you can change those behavious by creating your own handlers.
For signals that can be handled, you can change those behavious by creating your own handlers.
The possible default behaviours are:
The possible default behaviours are:
- T:
- T:
Abnormal termination of the process.
Abnormal termination of the process.
The process is terminated with all the consequences of `_exit()` except that the status made available to
`wait()` and `waitpid()` indicates abnormal termination by the specified signal.
The process is terminated with all the consequences of `_exit()` except that the status made available to
`wait()` and `waitpid()` indicates abnormal termination by the specified signal.
Default action for most signals.
Default action for most signals.
- A :Abnormal termination of the process.
- A :Abnormal termination of the process.
[XSI] [Option Start] Additionally, implementation-defined abnormal termination actions,
such as creation of a core file, may occur. [Option End]
[XSI] [Option Start] Additionally, implementation-defined abnormal termination actions,
such as creation of a core file, may occur. [Option End]
Linux implements concept of core dumps on those cases.
Note however that those may be turned on or off depending on the system configuration.
Linux implements concept of core dumps on those cases.
Note however that those may be turned on or off depending on the system configuration.
- I: Ignore the signal.
- I: Ignore the signal.
An important example is `SIGCHLD`, which is generated when a child terminates,
but has no effect by default, since in general killing the parent is not what
should happen on most programs.
An important example is `SIGCHLD`, which is generated when a child terminates,
but has no effect by default, since in general killing the parent is not what
should happen on most programs.
- S: Stop the process.
- S: Stop the process.
Mainly `SIGSTOP`.
Mainly `SIGSTOP`.
- C: Continue the process, if it is stopped; otherwise, ignore the signal.
- C: Continue the process, if it is stopped; otherwise, ignore the signal.
Mainly `SIGCONT`.
Mainly `SIGCONT`.
POSIX specific signals include:
POSIX specific signals include:
- SIGKILL
# SIGKILL
Kills program.
Kills program.
Cannot be handled unlike to `SIGINT` and `SIGTERM`.
Cannot be handled unlike to `SIGINT` and `SIGTERM`.
- SIGQUIT
# SIGQUIT
Quit program.
Quit program.
Used in case of abnormal termination (`A`), unlike `SIGINT` and `SIGTERM` which happen on normal temrination.
Used in case of abnormal termination (`A`), unlike `SIGINT` and `SIGTERM` which happen on normal temrination.
May generate a core dump <https://en.wikipedia.org/wiki/Core_dump> depending on system configurations.
May generate a core dump https://en.wikipedia.org/wiki/Core_dump depending on system configurations.
On Ubuntu, coredumps are disabled by default. You can enable them for the current session with:
On Ubuntu, coredumps are disabled by default. You can enable them for the current session with:
ulimit -c unlimited
ulimit -c unlimited
on the terminal where you will run the command to enable core dumps.
on the terminal where you will run the command to enable core dumps.
The setting can be permanently changed on the `/etc/security/limits.conf` file.
The setting can be permanently changed on the `/etc/security/limits.conf` file.
The core file is binary. To interpret it you must have compiled the program with debugging
information and then use GDB on the core file and the executable as:
The core file is binary. To interpret it you must have compiled the program with debugging
information and then use GDB on the core file and the executable as:
gcc -g -o myfile myfile.c
gdb myfile core
gcc -g -o myfile myfile.c
gdb myfile core
- SIGSTOP
# SIGSTOP
Freezes program.
Freezes program.
`ctrl+z`, in linux terminals.
`ctrl+z`, in linux terminals.
Cannot be handle.
Cannot be handle.
- SIGCONT
# SIGCONT
Continues a process that
Continues a process that
- SIGHUP
# SIGHUP
Controlling terminal was killed.
Controlling terminal was killed.
This is why killing the terminal kills most process by default unless those process implement a handler.
This is why killing the terminal kills most process by default unless those process implement a handler.
- SIGPIPE
# SIGPIPE
Process write to a pipe with no readers on other side
Process write to a pipe with no readers on other side
- SIGCHLD
# SIGCHLD
Child terminated, stopped or continued.
Child terminated, stopped or continued.
Ignored by default.
Ignored by default.
- SIGALRM
# SIGALRM
Received after the alarm call after given no of secs.
Received after the alarm call after given no of secs.
- SIGUSR1 and SIGUSR2: left to users to do whatever they want with
# SIGUSR1
#Parent death signal
# SIGUSR2
In POSIX, no signal needs to be sent to the child if the parent exits:
<http://stackoverflow.com/questions/284325/how-to-make-child-process-die-after-parent-exits>
In Linux, this can be achieved via the `prctl` syscall.
This may seem surprising considering that:
Left to users to do whatever they want with. Default to `term`.
- parents can wait for children
# Parent death signal
- children get a NOHUP when controling process is killed
This is mentioned at: <http://pubs.opengroup.org/onlinepubs/009695399/functions/exit.html>
In POSIX, no signal needs to be sent to the child if the parent exits:
http://stackoverflow.com/questions/284325/how-to-make-child-process-die-after-parent-exits
In Linux, this can be achieved via the `prctl` syscall.
This may seem surprising considering that:
TODO what is a controlling process?
- parents can wait for children
#sources
- children get a NOHUP when controling process is killed
This is mentioned at: http://pubs.opengroup.org/onlinepubs/009695399/functions/exit.html
- <http://www.alexonlinux.com/signal-handling-in-linux>
TODO what is a controlling process?
good intro
# Sources
- man 7 signal
- `man 7 signal`
man pages
man pages
# TODO
- http://www.alexonlinux.com/signal-handling-in-linux
- determine where specification barriers betwwen ANSIC / POSIX / linux
good intro
# TODO
- determine where specification barriers betwwen ANSIC / POSIX / linux
*/
#define _XOPEN_SOURCE 700
@ -175,28 +179,36 @@ POSIX specific signals include:
#include <unistd.h>
void signal_handler(int sig) {
// The `sig` arg allows us to use a single function for several different signals:
// just look at it and decide which action to take based on the signal number.
/*
The `sig` arg allows us to use a single function for several different signals:
just look at it and decide which action to take based on the signal number.
*/
printf("sig: %d\n", sig);
// After the signal is dealt with, the handler is then changed to its default action
// If you want to continue using this handler for future signals, you have to reregister
// it here: TODO confirm. If I remove this it does not work.
/*
After the signal is dealt with, the handler is then changed to its default action
signal(sig, signal_handler);
If you want to continue using this handler for future signals, you have to reregister
it here: TODO confirm. If I remove this it does not work.
*/
// You can change the action handler at any time
// For example, if you uncomment this line, only the first signal will be ignored
// and but the second will be dealt with the default action:
/*signal(sig, signal_handler);*/
//(void) signal( sig, SIG_DFL );
/*
You can change the action handler at any time
For example, if you uncomment this line, only the first signal will be ignored
and but the second will be dealt with the default action:
*/
/*(void) signal( sig, SIG_DFL );*/
}
int main() {
/*
#signal
# signal
POSIX recommends `sigaction` instead of `signal`.
*/
@ -204,7 +216,7 @@ int main() {
signal(SIGALRM, signal_handler);
/*
#Send signal
# Send signal
This is done via the kill function:
@ -217,7 +229,7 @@ int main() {
TODO 0 which? same uid?
*/
//send a SIGINT to ourselves:
/* send a SIGINT to ourselves: */
assert(kill(getpid(), SIGALRM) == 0);
int i = 0;
@ -234,7 +246,7 @@ int main() {
}
/*
#pause
# pause
Stop program until it receives a signal.
*/

196
signal.c
View File

@ -1,91 +1,123 @@
/*
signals are a simple way for processes to communicate
Signals are a simple way for processes to communicate.
signals are limited to passing a single byte between two processes
Signals are limited to passing a single byte between two processes.
what almost each signal does is all predefined by ansi c
What almost each signal does is all predefined by ANSI C
or specific operating systems
# example: control c
# Example: control + c
an example most linux people have used directly already:
hit ctrl+c in a terminal and this will send an INT signal
to the running process.
An example most Linux people have used directly already:
hit Ctrl + C in a terminal and this will send an INT signal
to the running process.
Unless the process implements a handler for this process,
this has the effect of destroying the process,
which is what happens by default for most, but not all signals.
Unless the process implements a handler for this process,
this has the effect of destroying the process,
which is what happens by default for most, but not all signals.
# ansi c
# ANSI C
there is a small C ANSI signal interface,
and individual operating systems may implement many more
which is the case for linux
There is a small ANSI C signal interface,
and individual operating systems may implement many more
which is the case for Linux.
6 signals defined:
6 signals defined:
- SIGABRT: (Abort) Abnormal termination, such as is initiated by the abort function.
# SIGABRT
- SIGFPE: (Floating-Point Exception) Erroneous arithmetic operation.
Abort.
Such as zero divide or an operation resulting in overflow
Abnormal termination, such as is initiated by the `abort` function.
Not necessarily generated by a floating-point operation, may be an integer operation.
# SIGFPE
floating point division by 0 `1.0 / 0.0` does not generate exceptoins since it is defined by IEEE:
<http://stackoverflow.com/questions/7267838/division-by-zero-does-not-throw-sigfpe>
Floating-Point Exception.
integer division by 1 / 0 may generate a SIGFPE
Erroneous arithmetic operation such as division by zero divide
or an operation resulting in overflow.
TODO is 1 / 0 guaranteed to generate a `SIGFPE`?
Unlike the name suggests, it is not necessarily generated by a floating-point operation:
it may also happen on an integer operation.
TODO how to deal with it? it just keeps coming back time after time.
Floating point division by 0 `1.0 / 0.0` does not generate exceptoins since it is defined by IEEE:
<http://stackoverflow.com/questions/7267838/division-by-zero-does-not-throw-sigfpe>
very similar question, but his behaviour is not exactly the same as mine:
<http://stackoverflow.com/questions/14905947/what-does-c-c-handler-sigfpe>
Integer division by 1 / 0 may generate a `SIGFPE`.
TODO is 1 / 0 guaranteed to generate a `SIGFPE`?
- SIGILL: (Illegal Instruction) Things that can generate this on Linux x86:
TODO how to deal with it? it just keeps coming back time after time.
- making an assembly operation that is only legal from kernel mode on user mode,
such as modify cs, ds or ss registers from a user program.
Very similar question, but his behaviour is not exactly the same as mine:
http://stackoverflow.com/questions/14905947/what-does-c-c-handler-sigfpe
- SIGSEGV: (Segmentation Violation)
# SIGILL
Invalid access to storage: When a program tries to read or write outside the memory it has allocated.
Illegal Instruction.
- SIGINT: (Interrupt) Ask the process to terminate, possibly nicely. Sample cause: linux terminal ctrl+c.
Things that can generate this on Linux x86:
- SIGTERM: (Terminate) Termination request sent to program. Major cause: shutdown, window close.
- making an assembly operation that is only legal from kernel mode on user mode,
such as modify cs, ds or ss registers from a user program.
The only difference between `SIGINT` and `SIGTERM` is that `SIGINT` is meant to be generated manually by users
from the terminal, while `SIGTERM` is meant to be generated by other applications.
# SIGSEGV
Functions defined (handlers):
Segmentation Violation.
- SIG_DFL Default handling: The signal is handled by the default action for that particular signal.
- SIG_IGN Ignore Signal: The signal is ignored.
- SIG_ERR Special return value indicating failure.
Invalid access to storage: When a program tries to read or write
outside on an address and the OS does not like it because it is using too much memory.
#raise
# SIGINT
TODO
Interrupt
#abort
Ask the process to terminate, possibly nicely.
TODO
Sample cause: Linux terminal Ctrl + C.
#allows opeartions on signal handlers
# SIGTERM
TODO can any operation be done in a signal handler (print to stdout for example?)
Terminate.
#sig_atomic_t
Termination request sent to program. Major cause: shutdown, window close.
TODO
The only difference between `SIGINT` and `SIGTERM` is that `SIGINT` is meant to be generated manually by users
from the terminal, while `SIGTERM` is meant to be generated by other applications.
# sources
Functions defined (handlers):
- <http://www.alexonlinux.com/signal-handling-in-linux>
# SIG_DFL
Default handling: The signal is handled by the default action for that particular signal.
# SIG_IGN
Ignore Signal: The signal is ignored.
# SIG_ERR
Special return value indicating failure.
# raise
TODO
# abort
TODO
# Allowed opeartions on signal handlers
TODO can any operation be done in a signal handler (print to stdout for example?)
# sig_atomic_t
TODO
# Sources
- http://www.alexonlinux.com/signal-handling-in-linux
good intro, covers lots of POSIX / linux specific stuff,
but also has nice examples that help understand the ANSI C model.
@ -95,28 +127,36 @@ TODO
#include <stdio.h>
#include <stdlib.h>
void signal_handler( int sig )
{
//sig arg allows us to use a single function for several different signals:
//just look at it and decide which action to take based on the signal number
void signal_handler(int sig) {
/*
Signal arguments allow us to use a single function for several different signals:
just look at it and decide which action to take based on the signal number
*/
//printf( "sig: %d\n", sig );
/*printf("sig: %d\n", sig);*/
//after the signal is dealt with, the handler is then changed to its default action
//if you want to continue using this handler for future signals, you have to reregister
//it here: TODO confirm. If I remove this it does not work.
/*
After the signal is dealt with, the handler is then changed to its default action
signal( sig, signal_handler );
if you want to continue using this handler for future signals, you have to reregister
it here: TODO confirm. If I remove this it does not work.
*/
//you can change the action handler at any time
//for example, if you uncomment this line, only the first signal will be ignored
//and but the second will be dealt with the default action:
signal(sig, signal_handler);
//(void) signal( sig, SIG_DFL );
/*
You can change the action handler at any time.
For example, if you uncomment this line, only the first signal will be ignored.
And but the second will be dealt with the default action:
*/
{
/*(void) signal(sig, SIG_DFL);*/
}
}
int main()
{
int main() {
/*
registers signal_handler as handler for SIGINT and SIGTERM:
@ -128,23 +168,25 @@ int main()
- opening a new termianal (ex: `xterm` on linux)
- running this program on that terminal
from the current terminal, and then closing the first terminal.
From the current terminal, and then closing the first terminal.
*/
signal( SIGINT, signal_handler );
signal( SIGTERM, signal_handler );
signal( SIGFPE, signal_handler );
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGFPE, signal_handler);
//#floating point exception
//# Floating point exception
//{
// int i = 0;
// int j = 0;
// //cannot do 1 / 0 or the compiler will give a warning. Lets dupe him:
// j = 1 / i;
// //you need this `printf` or the compiler may optimize your division away
// printf( "%d", j );
//}
/*
{
int i = 0;
int j = 0;
//cannot do 1 / 0 or the compiler will give a warning. Lets dupe him:
j = 1 / i;
//you need this `printf` or the compiler may optimize your division away
printf( "%d", j );
}
*/
//int i = 0;
//while ( i < 10 )