C & C ++ Things to remember

Index

 


Operators in C and C++

  • Operators in C and C++, see WikipediA here.

Back on TOP



Member access through pointer
(->)

The member access expression has the form
expression -> member-name

where:
expression  –  an expression of type pointer to struct or union
member-name  –  an identifier that names a member of the struct or union pointed by expression

The member access through pointer expression designates the named member of the struct or union type pointed to by its left operand. Its value category is always lvalue

If the type pointed to by the left operand is const or volatile qualified, the result is also qualified. If the type pointed to by the left operand is atomic, the behavior is undefined.

#include <stdio.h>
struct s {int x;};

int main(void)
{
    struct s s={1}, *p = &s;
    p->x = 7; // changes the value of s.x through the pointer
    printf("%d\n", p->x); // prints 7
}

(From: cppreference)

Back on TOP


Structure

A struct in the C programming language (and many derivatives) is a complex data type declaration that defines a physically grouped list of variables to be placed under one name in a block of memory, allowing the different variables to be accessed via a single pointer, or the struct declared name which returns the same address. The struct can contain many other complex and simple data types in an association, so is a natural organizing type for records like the mixed data types in lists of directory entries reading a hard drive (file length, name, extension, physical (cylinder, disk, head indexes) address, etc.), or other mixed record type (patient names, address, telephone… insurance codes, balance, etc.). (From: WikipediA)

In Italian language

Le strutture del C sostanzialmente permettono l’aggregazione di più variabili, in modo simile a quella degli array, ma a differenza di questi non ordinata e non omogenea (una struttura può contenere variabili di tipo diverso). Per denotare una struttura si usa la parola chiave struct seguita dal nome identificativo della struttura, che è opzionale.
(Da: html.it)

struct book
{
  char titolo[100];
  char autore[50];
  int anno_pubblicazione;
  float prezzo;
} biblio; 

(Da: html.it)

Per accedere alle variabili interne della struttura si usa l’operatore punto ‘.‘.
Una variabile interna può essere poi manipolata come qualsiasi altra variabile.
(Da: html.it)

// Assign a value to the book price
biblio.prezzo = 67.32;

// Assign a variable int the year publication of the book
int year = biblio.anno_pubblicazione;

// Print the title of the book
printf ("% s n", biblio.titolo);

(Da: html.it)

Back on TOP


typedef

typedef – creates an alias that can be used anywhere in place of a (possibly complex) type name. (From: cppreference)

// simple typedef
typedef unsigned long ulong;
 
// the following two objects have the same type
unsigned long l1;
ulong l2;
 
// more complicated typedef
typedef int int_t, *intp_t, (&fp)(int, ulong), arr_t[10];
 
// the following two objects have the same type
int a1[10];
arr_t a2;
 
// common C idiom to avoid having to write "struct S"
typedef struct {int a; int b;} S, *pS;
 
// the following two objects have the same type
pS ps1;
S* ps2;
 
// error: storage-class-specifier cannot appear in a typedef declaration
// typedef static unsigned int uint;
 
// typedef can be used anywhere in the decl-specifier-seq
long unsigned typedef int long ullong;
 
// std::add_const, like many other metafunctions, use member typedefs
template< class T>
struct add_const {
    typedef const T type;
};
 
typedef struct Node {
    struct listNode* next;
    // declares a new (incomplete) struct type named listNode
} listNode; // error: conflicts with the previously declared struct name


(From: cppreference)

In Italian language

Per definire nuovi tipi di dato viene utilizzata la funzione typedef.
L’uso di typedef, combinato con struct ci permette di creare tipi di dato molto complessi, come mostrato nell’esempio seguente:

typedef struct libro
{
  char titolo[100];
  char autore[50];
  int anno_pubblicazione;
  float prezzo;
} t_libro;

t_libro guida = {"Guida al C", "Fabrizio Ciacchi", 2003, 45.2};

In questo modo abbiamo definito un nuovo tipo di nome t_libro, che non è altro che una struttura.
guida è la variabile creata di tipo t_libro.
Ora possiamo utilizzare il nuovo tipo come ogni altro, ad esempio possiamo creare un array di elementi di tipo t_libro.

t_libro raccolta[5000];

Per accedere agli elementi dell’array, o per inizializzare i valori, è sufficiente utilizzare l’indice per identificare l’elemento dell’array ed il punto (.) per accedere alle variabili interne del tipo t_libro.

// assegna un valore al prezzo del 341mo libro
raccolta[340].prezzo = 67.32;

// assegna ad una variabile int l'anno di pubblicazione del 659mo libro
int anno = raccolta[658].anno_pubblicazione;

// stampa il titolo del 23mo libro
printf ("%s n", raccolta[22].titolo);

(Da: html.it)

Back on TOP


Callback

(From: WikipediA)

A callback is any executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at a given time.
This execution may be immediate as in a synchronous callback, or it might happen at a later time as in an asynchronous callback.
In all cases, the intention is to specify a function or subroutine as an entity[clarification needed] that is, depending on the language, more or less similar to a variable.
Programming languages support callbacks in different ways, often implementing them with subroutines, lambda expressions, blocks, or function pointers. (From: WikipediA)

In Italian language

Un callback (o, in italiano, richiamo) è, una funzione, o un “blocco di codice” che viene passata come parametro ad un’altra funzione.
In particolare, quando ci si riferisce alla callback richiamata da una funzione, la callback viene passata come parametro alla funzione chiamante.
In questo modo la chiamante può realizzare un compito specifico (quello svolto dalla callback).

Se invece ci si riferisce alla callback come funzione richiamata dal sistema operativo, di norma ciò si utilizza allo scopo di gestire particolari eventi: dal premere un bottone con il mouse, allo scrivere caratteri in un campo di testo.
Ciò consente, quindi, a un programma di livello più basso, di richiamare una funzione (o servizio) definita a un livello più alto.
(From: WikipediA)

Back on TOP


Clearing Bits & Setting Bits

Clearing Bits

PORTH &=  0xF5; // Changes bits 1 and 3 to zeros using C
              
     bit7  6  5  4  3  2  1  0   
0xAF == 1  0  1  0  1  1  1  1 (PORTH value)
0xF5 == 1  1  1  1  0  1  0  1
0xA5 == 1  0  1  0  0  1  0  1 (result) 

PORTH &= ~0x0A; // Same as above but using inverting the bit mask
                // easier to see which bits are cleared

Setting Bits

PORTH |= 0x0A;  // Set bits 1 and 3 to one using the OR
 
     bit7 6 5 4 3 2 1 0
0xA1 == 1 0 1 0 0 0 0 1 (PORTH value)
0x0A == 0 0 0 0 1 0 1 0
0xAB == 1 0 1 0 1 0 1 1 (result)

(From: Embedded Systems/C Programming)

 

Back on TOP


Bit Fields

Bit fields are a topic that few C programmers have any experience with, although it has been a standardized part of the language for some time now.
Bit fields allow the programmer to access memory in unaligned sections, or even in sections smaller than a byte.
Let us create an example:

struct _bitfield {
   flagA : 1;
   flagB : 1;
   nybbA : 4;
   byteA : 8;
}

The colon separates the name of the field from its size in bits, not bytes.
Suddenly it becomes very important to know what numbers can fit inside fields of what length.
For instance, the flagA and flagB fields are both 1 bit, so they can only hold boolean values (1 or 0) the nybbA field can hold 4 bits, for a maximum value of 15 (one hexadecimal digit).

Fields in a bitfield can be addressed exactly like regular structures.
For instance, the following statements are all valid:

struct _bitfield field;
field.flagA = 1;
field.flagB = 0;
field.nybbA = 0x0A;
field.byteA = 255;

(From: Embedded Systems/C Programming)

Back on TOP


const

const is used to store a value in ROM or FLASH.

This declaration put the months in RAM.

   char * months[] = {
       "January", "February", "March",
       "April", "May", "June",
       "July", "August", "September",
       "October", "November", "December",
   };

This declaration put the months in ROM or FLASH.

   char const * months[] = {
       "January", "February", "March",
       "April", "May", "June",
       "July", "August", "September",
       "October", "November", "December",
   };

We inform the compiler that we promise to never modify months.

(From: Embedded Systems/C Programming)

Back on TOP


static

The static keyword can accompany the declaration of one or more variables and / or functions, and takes on different meanings depending on the context in which it is used:

as part of a global or namespace
in the context of a function
as part of a class or struct

If it is used within a function, as in

int funz( )
{
static int ciccio;
}

It means that the integer variable ciccio SAVES its value between executions of func and any subsequent re-execution.

In Italian language

La parola static può accompagnare la dichiarazione di una o più variabili e/o funzioni, e assume diversi significati secondo il contesto in cui è utilizzata:

  • nell’ambito globale o di un namespace
  • nell’ambito di una funzione
  • nell’ambito di una class o una struct

Se viene usata nell’ambito di una funzione, come in

int funz( )
{
static int ciccio;
}

significa che la variabile intera ciccio CONSERVA il proprio valore tra un’esecuzione di funz e un’eventuale esecuzione successiva.

Per le spiegazioni complete vedere UNIBO lab info

Back on TOP


Preprocessing or Preprocessor directives

The C preprocessor or cpp is the macro preprocessor for the C and C++ computer programming languages.
The preprocessor provides the ability for the inclusion of header files, macro expansions, conditional compilation, and line control. (From: WikipediA)

Including files

One of the most common uses of the preprocessor is to include another file: #include

#include <file>

Putting the name of the include file Among the less than symbol (<) and That of greater than (>); in this form, the compiler’s going to look for the files present in the selected directory to include; and generally this default directory, and That Which Contains the libraries and files standards, coming for example stdio.h, stdlib.h, math.h, string.h, time.h and so on.

But if you want to include a file that is in the same folder of our program, we should use an alternative form, as follows:

#include "file"

Conditional compilation

The if-else directives #if, #ifdef, #ifndef, #else, #elif and #endif can be used for conditional compilation.

#if VERBOSE >= 2
  print("trace message");
#endif

Translation can also be caused to fail by using the #error directive see the examples below.

#if RUBY_VERSION == 190
#error 1.9.0 not supported
#endif

#if defined USING_SQLITE && defined USING_MYSQL
#error You cannot use both sqlite and mysql at the same time
#endif

#if !(defined USING_SQLITE && defined USING_MYSQL)
#error You must use either sqlite or mysql
#endif

Macro definition and expansion

There are two types of macros, object-like and function-like. Object-like macros do not take parameters; function-like macros do (although the list of parameters may be empty). The generic syntax for declaring an identifier as a macro of each type is, respectively:

// object-like macro
#define <identifier> <replacement token list>        

// function-like macro, note parameters
#define <identifier>(<parameter list>) <replacement token list>

(From: WikipediA)

Examples:

#define NUMERO 5
#define QUADRATO(a) (a)*(a)
#include <stdio.h>

#define NUMERO 5
#define QUADRATO(a) (a)*(a)

int main()
{
   int x;

   printf(“Numero : %d n”, NUMERO);
   x = QUADRATO(NUMERO);
   printf(“Quadrato: %d n”, x);

   #undef NUMERO
   #define NUMERO 7

   printf(“Numero : %d n”, NUMERO);
   x = QUADRATO(NUMERO);
   printf(“Quadrato: %d n”, x);

   return 0;
}

(From: html)

Special macros and directives

Certain symbols are required to be defined by an implementation during preprocessing. These include __FILE__ and __LINE__, predefined by the preprocessor itself, which expand into the current file and line number. For instance the following:

// debugging macros so we can pin down message origin at a glance
#define WHERESTR  "[file %s, line %d]: "
#define WHEREARG  __FILE__, __LINE__
#define DEBUGPRINT2(...)       fprintf(stderr, __VA_ARGS__)
#define DEBUGPRINT(_fmt, ...)  DEBUGPRINT2(WHERESTR _fmt, WHEREARG, __VA_ARGS__)
//...

  DEBUGPRINT("hey, x=%d\n", x);

prints the value of x, preceded by the file and line number to the error stream, allowing quick access to which line the message was produced on. Note that the WHERESTR argument is concatenated with the string following it.
The values of __FILE__ and __LINE__ can be manipulated with the #line directive.
The #line directive determines the line number and the file name of the line below. E.g.:

#line 314 "pi.c"
printf("line=%d file=%s\n", __LINE__, __FILE__);

generates the printf function:

printf("line=%d file=%s\n", 314, "pi.c");

Source code debuggers refer also to the source position defined with __FILE__ and __LINE__.
This allows source code debugging, when C is used as target language of a compiler, for a totally different language.
The first C Standard specified that the macro __STDC__ be defined to 1 if the implementation conforms to the ISO Standard and 0 otherwise, and the macro __STDC_VERSION__ defined as a numeric literal specifying the version of the Standard supported by the implementation. (From: WikipediA)

Back on TOP