For details on functions search in the man page (man <function-name>
or man -a <function-name>
if there is also a unix command with same name), or search the web.
⇒ C and C++.
You can catch ctrl-c or other signals, for example to clean up things before to quit.
#include <signal.h> void function_upon_sig (int sig __attribute__((unused))) { // write what you want to do here exit(0); } int main() { signal(SIGINT, function_upon_sig); // ctrl-c signal(SIGTERM, function_upon_sig); signal(SIGHUP, function_upon_sig); signal(SIGALRM, function_upon_sig); }
You can see a complete list of all signals here.
You should only use “async-signal safe” functions in the handler to avoid deadlocks (async-signal safety is stronger than thread safety, because the main program is completely interrupted until the handler has terminated). For example, printf
is not safe, but write
is, so you should write text on the terminal using write(STDOUT_FILENO, text, text_length);
(more details here).
You can also change the signals actions with the sigaction function.
#include <unistd.h> unsigned int alarm(unsigned int seconds);
will trigger signal SIGALRM x seconds later that you can catch (see catching_signals).
If you need automatic repetition and/or sub-second precision, you can use:
#include <sys/time.h> int setitimer(int whichtimer, const struct itimerval *value, struct itimerval *ovalue);
Monitor multiple file descriptors.
#include <sys/select.h> int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
#include <pthread.h> void *threadFunction(void *threadid) { printf("%d: Hello World!\n", threadid); pthread_exit(NULL); } int main (int argc, char *argv[]) { pthread_t threadId; int threadData = 42; if (pthread_create(&threadId, NULL, threadFunction, (void *)threadData) != 0) { printf("thread creation failed"); exit(1); } return 0; }
join sem etc
pwd = getpwnam("cyril"); if (pwd) { setgid(pwd->pw_gid); setuid(pwd->pw_uid); }
But it doesn't really work to start shell commands, you should use sudo
too:
system("sudo -u cyril <command>); system("sudo -u cyril /bin/sh -c '<command1>; <command2>');
⇒ C++
#include <iomanip>
for everything in this section.
std::cout << "normal text, " << "\033[1;33m" << "colored text, " << "\033[1;00m" << "normal text" << std::endl;
Code | Effect | Code | Effect | |
---|---|---|---|---|
\033[1;00m | normal white | |||
\033[1;29m | bold white | \033[0;29m | normal white | |
\033[1;30m | bold grey | \033[0;30m | normal grey | |
\033[1;31m | bold red | \033[0;31m | normal red | |
\033[1;32m | bold green | \033[0;32m | normal green | |
\033[1;33m | bold yellow | \033[0;33m | normal yellow | |
\033[1;34m | bold blue | \033[0;34m | normal blue | |
\033[1;35m | bold purple | \033[0;35m | normal purple | |
\033[1;36m | bold cyan | \033[0;36m | normal cyan |
double x = 32.14554; std::cout << "Double with 3 significant digits : " << std::setprecision(3) << x << std::endl; // 32.1
std::cout << std::setw(10) << "hello"; // "hello " std::cout << std::setfill('.') << std::setw(10) << "hello"; // "hello....." std::cout << std::right << std::setw(10) << "hello"; // " hello"
To get all characters while they are white spaces.
std::cin >> std::ws >> buffer; // "\r\n pouet" -> "pouet"
To stop the compilation and print a message :
#error Cannot compile
To just print a message :
#warning Possible problem
To get a macro argument as a string :
#define ASSERT(x) if (x == NULL) printf("Pointer %s NULL", #x);
Macro with variable argument count (C99 only) :
#define ERROR(msg, ...) fprintf("ERROR:%s:%d# ", __FILE__, __LINE__, ## __VA_ARGS__);
You can also use the PRETTY_FUNCTION
but it is not standard:
#define ERROR(msg, ...) fprintf("ERROR:%s:%d %s# ", __FILE__, __LINE__, __PRETTY_FUNCTION__, ## __VA_ARGS__);
Get the type of an argument :
#define abs(x) ({ typeof(x) xx=(x); xx>0 ? xx : -xx; })
⇒ C++
#include <sstream> std::ostringstream oss; oss << 565; std::cout << oss.str() << std::endl;
⇒ C & C++
#include <stdio.h> char s[128]; sprintf(s, "%d", 565);
⇒ C & C++
#include <stdlib.h> int i = atoi("562"); long l = atol("4500294"); double f = atof("4.546643");
You can define names for the preprocessor from the command line (or the makefile) instead of the source file (#define name
). It can be very useful.
Command | Equivalent in source file |
---|---|
-D name | #define name |
-D name=value | #define name value |
-U name | #undef name |
g++ foo.cc -o foo -D BAR=3
The full test program is available here
int fonction(double x, bool b); // declaration of the function int (*pf)(double,bool); // declaration of the pointer to function pf = &fonction; // initialization of the pointer (*pf)(9,true); // call of the function through the pointer
Using typedef
:
int fonction(double x, bool b); // declaration of the function typedef int (*fnIdb)(double,bool); // declaration of pointer type fnIdb pf = &fonction; // declaration and initialization of the pointer (*pf)(9,true); // call of the function through the pointer
Static member functions behave the same way than normal functions.
class ClasseS { public: static int fonction(double x, bool b); }; // declaration of the function int (*psf)(double,bool); // declaration of the pointer to the function psf = &ClasseS::fonction; // initialization of the pointer (*psf)(5,true); // call of the static member function through the pointer
Member functions have a hidden parameter (a pointer to this
), so the pointer needs an object to call the function. If the member function is non virtual, the address of the member function is the same for all objects.
class Classe { public: int fonction(double x, bool b); }; // declaration of the function int (Classe::*pcf)(double,bool); // declaration of the pointer to function pcf = &Classe::fonction; // initialization of the pointer Classe classe; (classe.*pcf)(9,true) // call of the member function through the pointer
The syntax is the same as for non virtual member functions, and the pointer points to the place in the object where the address of the function is stored, so that it always points to the right function.
class Classe { public: int fonction(double x, bool b); }; class Classe2 : public Classe { public: int fonction(double x, bool b); }; int (Classe::*pcvf)(double,bool); // declaration pcvf = &Classe::fonction; // initialization Classe *classe1 = new Classe(), *classe2 = new Classe2(); (classe1->*pcvf)(9,true) // calls Classe::fonction (classe2->*pcvf)(9,true) // calls Classe2::fonction
This is done with constructors :
class FixedPoint { unsigned int data; public: FixedPoint() { data = 0; } FixedPoint(int x) { data = x<<8; } Fixedpoint(double x) { data = (unsigned int)(x * (1<<8)); } }; double pi; FixedPoint pif; pi = 3.14; pif = pi; // it works, FixedPoint(double) is called for the cast
The syntax is simple :
class FixedPoint { unsigned int data; public: ... operator double() { return data / (double)(1<<8); } }; double pi; FixedPoint pif(3.14); pi = pif; // it works, double() is called for the cast
Imagine the following situation :
template <typename T> class Pixel { T r,g,b; public: template <typename N> inline Pixel<T>& operator=(Pixel<N> &pix) { r=pix.r; g=pix.g; b=pix.b; return *this; } }; Pixel<unsigned char> pix1; Pixel<int> pix2; pix2 = pix1; // it works, because operator= and cast are simultaneously overloaded that way
Of course it works only if there is a possible cast from N to T. You can do the same with all operators (+,+= …).
It is painful to remember all declarations of operators overloading, then here they are :
#include <iostream> // for stream operators class Object { int a,b; public: Object(int a, int b) : a(a), b(b) {} // You MUST overload copy constructor and operator= if you allocate memory in your object Object(Object &o) : a(o.a), b(o.b) {} Object& operator= (const Object &o) { a=o.a; b=o.b; return *this; } // this is for +, but idem for all homogeneous binary operators : -,*,/, ... Object operator+ (const Object &o) const { return Object(a+o.a, b+o.b); } Object& operator+=(const Object &o) { a+=o.a; b+=o.b; return *this; } // this is for *, but idem for all heterogeneous binary operators : /,<<,>> ... Object operator* (int x) const { return Object(a*x, b*x); } Object& operator*=(int x) { a*=x; b*=x; return *this; } // stream operators should not be members, declare it friend to access protected data friend std::ostream& operator<<(std::ostream& os, const Object &o); friend std::istream& operator>>(std::istream& is, Object &o); }; //.cpp std::ostream& operator<<(std::ostream& os, const Object &o) { os << ...; return os; } std::istream& operator>>(std::istream& is, Object &o) { while (is >> ...) ... return is; }
Precedence | Operator | Name | Associativity |
---|---|---|---|
17 | :: :: | scope resolution / global | R/L |
16 | () () | function call / value construction | L/R |
[] | subscripting | L/R | |
. -> | member selection | L/R | |
++ -- | post increment/decrement | R/L | |
15 | () | type cast | R/L |
sizeof | size of type or object | R/L | |
& * | address of / dereference | R/L | |
~ ! | bitwise complement / logical not | R/L | |
+ - | unary plus and minus | R/L | |
++ -- | pre increment/decrement | R/L | |
new delete delete[] | create / destroy / destroy array | R/L | |
14 | .* ->* | member selection | L/R |
13 | * / % | multiply / divide / modulo | L/R |
12 | + - | plus / minus | L/R |
11 | << >> | bit shifting | L/R |
10 | < <= > >= | comparison | L/R |
9 | == != | comparison | L/R |
8 | & | bitwise and | L/R |
7 | ^ | bitwise exclusive or | L/R |
6 | | | bitwise inclusive or | L/R |
5 | && | logical and | L/R |
4 | || | logical inclusive or | L/R |
3 | ?: | conditional expression | R/L |
2 | = += -= *= /= %= | assignments | R/L |
<<= >>= &= ^= |= | |||
1 | throw | throw exception | R/L |
0 | , | comma | L/R |
Type | Size | Range | Precision |
---|---|---|---|
char | 1 byte | -128 to 127 | 1 |
unsigned char | 1 byte | 0 to 255 | 1 |
short | 2 bytes | -32768 to 32767 | 1 |
unsigned short | 2 bytes | 0 to 65535 | 1 |
int | 4 bytes | -2 147 483 648 to 2 147 483 647 | 1 |
unsigned int | 4 byte | 0 to 4 294 967 295 | 1 |
long (int) | 4 bytes | = int | 1 |
unsigned long (int) | 4 bytes | = unsigned int | 1 |
long long (int) | 8 bytes | -9.22337E+18 to 9.22337E+18 | 1 |
unsigned long long (int) | 8 bytes | 0 to 1.84467E+19 | 1 |
enum | 4 bytes | = int | 1 |
float | 4 bytes | 3.4E-38 to 3.4E+38 | 6 digits |
double | 8 bytes | 1.7E-308 to 1.7E+308 | 15 digits |
long double | 10 bytes | 1.2E-4932 to 1.2E+4932 | 18 digits |