joi, 28 februarie 2013

Verificarea sintaxei în Ansi C

Am găsit un document mai vechi de prin facultate despre verificarea sintaxei în Ansi C şi mă gândeam că poate ar putea fi de folos cuiva.

Verificarea sintaxei în Ansi C

Nu cred că mai are nevoie de explicaţii. E destul de clar cam cum funcţionează automatul de sintaxă. Ansi C are totul foarte organizat şi cât se poate de elaborat astfel încât să acopere toate situaţiile posibile. Totul este să înţelegi exact ce faci şi cum va reacţiona C-ul la programul scris de tine :) . Sau invers , cum va reacţiona programul din prisma limbajului C.

Cred că documentul de mai sus este foarte folositor chiar şi pentru elevi şi studenţii.

"Keep it simple" şi Spor la treabă! 

miercuri, 27 februarie 2013

Maşină veche vs Maşină nouă

Mașina veche (de obicei peste 10 ani, Dacie :) ), are unele avantaje faţă de mașina nouă:
1. Nu prea te interesează dacă ți-o zgîrie în parcare
2. Gropile și denivelările luate în plin nu iți scot peri albi :)
3. Are ceva kilometri la bord și tot ce ar fi putut sa se strice până acum s-a stricat și ai înlocuit
4. Nu ai rată la bancă care să iți dea peste cap bugetul familiei
5. Faci practică la greu pe ea, mai poți repara fără sa iți fie frică de un eventual eşec .
6. Piesele se mai găsesc fără prea mari probleme.
7. Cheltuielile sunt minime : benzina, RCA-ul, eventual niște ulei, câte o spălare la două luni şi detergentul de spălat parbrizul.
8. Jenţile şi pneurile sunt destul de ieftine în târg (la mâna la doua dacă eşti norocos)
9. Dacă este întreţinută şi spălată regulat arată decent (asta dacă încă nu e plină de rugină)

Dezavantaje:
1. Tabla se cam rugineşte şi arată ca naiba
2. Uzura morală (parcată între două maşini noi îţi vine să nu te mai sui în ea =)
3. Uzura fizică (indiferent câte piese ai înlocuit la un moment dat încep să se strice în lanţ ca la domino, dar asta nu se aplică la toate maşinile, de exemplu Honda este una dintre cele mai fiabile maşini şi cu care nu ai treabă nici după 10 ani de rulaj)
4. Siguranţa pasagerilor e ca şi inexistentă la maşinile mai vechi de 10 ani ( ăsta ar fi argumentul cel mai bun să îţi cumperi o maşină nouă)
5. Mirosurile neplăcute din interior, care la un moment dat nu le mai scoţi nici cu slujbe

Dezavantajele sunt destul de importante mai ales dacă vrei să faci o călătorie mai lungă. Maşina veche este în schimb foarte bună pentru deplasarea prin oraş pentru că nu ştii niciodată când te lasă cu ochii în soare.
La maşină nouă tabla este impecabilă, arată bine, are garanţie ... hai că mă duc să îmi cumpăr o maşină nouă :D

luni, 25 februarie 2013

Eurovision

Întrebare: Când o să câştige România concursul Eurovision ?
Răspunsuri posibile:
- Când o face plopu pere şi răchita micşunele.
- Când o zbura porcu'.
- Când două linii paralele se vor întâlni.
- ....
Vă las pe voi să completaţi cu situaţii și mai imposibile.

De ce oare ? Pai e destul de simplu... Eurovision are o componenta politică şi geo-strategică. Nici dracu nu ne votează, decât eventual tot românii de prin Spania, Italia, Moldova etc...

vineri, 22 februarie 2013

Noi suntem români ..

A sosit ziua dreptății
Ziua sfânt-a libertății
Tot românul veselește
România-ntinereste.

Noi suntem români, noi suntem români
Noi suntem pe veci aici stăpâni.

Ardelean, copil de munte
Ia ridică-ţi a ta frunte
Şi în suflet de mândrie
Că ești fiu de Românie.

Noi suntem români, noi suntem români
Noi suntem pe veci aici stapâni.

Moldoveanul și munteanul
Sunt frați buni cu ardeleanul.
Trei romani plini de putere
Ca românu-n veci nu piere.

Noi suntem români, noi suntem români
Noi suntem pe veci aici stapâni.

Hai, români, lumea ne vede,
România-n noi se-ncrede.
Ca de-acum românu-n lume
Va fi vrednic de-al sau nume.

Noi suntem români, noi suntem români
Noi suntem pe veci aici stapâni.

Noi suntem romani, noi suntem romani,
Noi suntem urmași de-ai lui Traian.
Versuri de la: http://www.versuri.ro/
O să analizez ultima strofă din punctul de vedere al unui inginer. Istoria ne spune că în imperiul roman era o mică criză economică în perioada aia, şi ce s-a gândit împăratul Trăienuţ .. hai să ne mai facem o nouă provincie ca să mai facem rost de aur să mai tragem un chef. Şi care credeţi că era ţărişoara de pe listă ? Aţi ghicit, Dacia. Şi au venit .... au UCIS, au SILUIT, au FURAT tone de aur .. şi din copiii rezultaţi din siluirea asta a rezultat poporul român. Suntem mândrii nevoie mare ...
Noi românii, două mii de ani după episodul ăsta foarte relaxant de siluire îl iubim de numa pe meseriaşu' ăsta numit Traian.
Pai asta se numeşte masochism ... adică te f**e şi îţi şi place .. plus că îi faci statuie şi cântece de preaslăvire ...
Cam asta e părerea mea despre romanii ăştia "civilizatori". Logic ... la rece ...
Acum a venit şi uniunea europeana ... mi se pare mie sau şi ăştia ne cam siluiesc ... dar ce contează, ne place de numa.
PS: siluire = viol

joi, 21 februarie 2013

Alergarea

Câteodată îmi vine pur și simplu sa alerg. Pur și simplu nu mai pot să stau pe loc sa fiu un sedentar. Vreau sa alerg. Există o vorbă: "De piatra care se mișca nu se prind plante", la fel de oamenii care aleargă nu se prinde boala.
Am citit textul de mai jos pe un site de profil:
"Alergarea uşoară, pe distanţe mici, reprezintă cea mai simplă activitate sportivă care ne ajută să eliminăm grăsimile din organism. Pentru cei mai slabi, alergarea se poate dovedi, de asemenea, utilă, în măsura în care le sporeşte apetitul de mâncare. Este deja un lucru banal şi unanim acceptat: alergarea face bine la sănătate. Reactivează muşchii. "Arătăm" mai bine. Tenul se împrospătează, muşchii devin mai supli, mai relaxaţi.
Este de mult timp dovedit că alergarea are o influenţă benefică asupra nivelului de lipide în sânge şi asupra tensiunii arteriale. Acest lucru se produce în special după o perioadă de alergare de circa o oră. (http://alergare.pasiunea.eu/alergarea-si-sanatatea_articol_268.html)"
Pur şi simplu. ALEARGĂ !!!! Nu poate să facă decât bine.

vineri, 15 februarie 2013

Sursa de tensiune liniară (bazat pe LM317) (2)

Proiectul acesta începe să prindă contur. Am asamblat totul într-o cutie încăpătoare :). Singurul lucru care a rămas neterminat este afișorul de tensiune. Acest afișor o să-l execut folosind arduino cu un LCD și un divizor de tensiune.
În partea dreapta din poză am loc pentru încă o sursă ;)
Conectorul de alimentare de la rețea este chiar profesional. În schimb radiatoarele sunt un pic cam subdimensionate .. o să vad cât rezistă.
Sunt un pic cam multe cabluri dar sincer nu am găsit altă soluție. Dacă aveți o soluție mai bună sunteți invitați să o scrieți. O să le mai aranjez când o să instalez și afișorul de tensiune.
Sursa scoate maxim 18 V și minim 1.2 V ... Sincer nu știu exact de ce nu ajunge la zero. Dar o să aflu ...
Gaura unde o să instalez afișorul de tensiune este încă nefinisată. O să arate mai bine la final, vă promit :)

Oricum ar arăta eu sunt bucuros că funcționează. Deocamdată am folosit sursa doar pentru o mini-mașină de găurit care se poate alimenta doar la DC.
Schema de bază a sursei arată cam așa:

Weekend plăcut tuturor !

Ordinea operaţiilor

Operaţia asupra unui obiect în C se poate defini foarte simplu ca o modificare a obiectului sau a variabilei.
Limbajul C are integrat în interior un automat de determinare a ordinii operaţiilor. Acest automat (numit și state machine C) a fost conceput astfel încât să se evite situaţiile nedefinite. Pentru mai multe detalii vezi aici Order of operations
sau aici Precedence and Order of Evaluation(pentru pasionați :) ).

Punctul de succesiune este o stare abstractă a limbajului C care urmează să fie mapată într-o stare consistentă caracterizată prin valori concrete în regiştrii şi în memorie.

În general, ordinea de execuție a unui singur pas executat într-o singură instrucţiune nu este specificată. Dar limbajul C garantează că în momentul în care a ajuns la un punct de succesiune atunci valorile variabilelor sunt actualizate și în același timp corecte. Corecte din punct de vedere al procesării, dar nu neapărat corecte din punctul de vedere al programatorului care are impresia că operația scrisă de el este corectă (şi compilabilă) dar rezultatul este de cele mai multe ori nedefinit.

Puncte de succesiune
- Punctul în care se apelează o funcţie după ce se evaluează argumentele.
- După evaluarea operandului stâng pentru ŞI (AND,&&) logic sau operaţia SAU (||) logic.
- Sfârşitul operandului stâng al operatorului ?:
- După operandul stâng al operatorului virgula (,)
- După terminarea evaluării a întregii expresii:
- Evaluarea initializarii a unui obiect de tip auto
- O expresie urmată de punct şi virgulă ; (instrucţiune obişnuită ) - Toate expresiile din interiorul instructiunilor do, while, if, switch si for. - Expresia din instrucţiunea de return

Ordinea efectuării operațiilor în C este asigurata de automatul C, pentru că starea abstractă internă a automatului este garantat să fie sincronizată, dar nu neapărat bine definită. Starea internă a automatului C este aproape întotdeauna bine definită, dar exista anumite situații când nu se poate spune exact ce ar putea sa rezulte din o anumita operație.
O regulă de bază pentru a nu ajunge într-o stare nedefinită este să nu se modifice un obiect de două ori între două puncte de succesiune.
Am si niste exemple destul de sugestive:
#include "stdio.h"
int glob;
int value;
int i;
int a[20];

void f (void)
{
  glob = value + glob++;  /* undefined behaviour */
  printf("glob = %d",glob);
  glob = (glob++, glob) + /* undefined and
         (glob++, glob);   * unspecified behaviour */
  printf("glob = %d",glob);
  i = ++i + 1;            /* undefined */
  printf("i= %d",i);
  i = i + 1;              /* allowed */
  printf("i= %d",i);
  a[i++] = i;             /* undefined */
  printf("a[%d]= %d",++i,a[++i]);
  a[i] = i;               /* allowed */
  printf("i= %d",i);

}
int main(void)
{
 f();
 return 0;
}
Avem si o regula Misra foarte importantă:
- MISRA-C:2004, Rule 12.2(required): The value of an expression shall be the same under any order of evaluation.

Nu uitati , Keep It Simple !

joi, 14 februarie 2013

Precedenţa şi asociativitatea operatorilor

Limbajul C este unul dintre cele mai complexe limbaje când vine vorba de precedenţa operatorilor. Exista 15 de nivele diferite de precendenţă .
Precendenţa se referă la ordinea de evaluare a expresiilor şi depinde de doua lucruri:
- Operatorii au nivele de precendeţă diferite.
- Operatorii au asociativitate diferită de stânga sau de dreapta.
Operator Associativity
( ) [ ] -> . ++’postfix’ --’postfix’ Left
! ˜ ++ -- + - (type) * & sizeof Right
* / % Left
+’binary’ -’binary’ Left
<< >> Left
< <= > >= Left
== != Left
& Left
ˆ Left
| Left
&& Left
|| Left
?: Right
assignments Right
, Left
Exemplu:
#include "stdio.h"     /* printf */
#include "string.h"     /* strcat */
#include "stdlib.h"     /* strtol */

unsigned char *p;
unsigned char *ps;
unsigned char  a;
unsigned char  b;
unsigned char  c;

unsigned char  x;
unsigned char  y;
unsigned char  z;
typedef struct
{
  unsigned char h;
  unsigned short r;
} ms;
ms *m;
unsigned char  result;
unsigned char  temp;
unsigned char  flag;
unsigned char  low;
unsigned char  high;

const char *byte_to_binary(int x)
{
    static char b[9];
    b[0] = '\0';

    int z;
    for (z = 128; z > 0; z >>= 1)
    {
        strcat(b, ((x & z) == z) ? "1" : "0");
    }

    return b;
}

int main()
{

  *p++;           /* equivalent to *(p++); */
  /*(char)!-˜*++p; */  /* applied using an inside out order */
  /* m<- ps="">m;*/   /* ’->’ is an unary operator */
  a = b = c;          /* equivalent to a = (b = c); */
  temp = x + y + z;   /* equivalent to (x + y) + z */
  flag =2;
  if (flag & 2) /* clear meaning */
  {
    printf("flag = %d\n", flag);
  }
  if (flag & 2 != 0) /* more explicit? */
  {
    printf("flag = %d\n", flag);
  }
  if (flag & (2 != 0)) /* unfortunately:
                          * ’!=’ binds stronger... */
  {
   printf("flag = %d\n", flag);
  }

  low = 1;
  printf("low = %s\n", byte_to_binary(low));
  high = 8;
  printf("high = %s\n", byte_to_binary(high));

  result = high << 4 + low; /* hmm ... */
  printf("result = %s\n", byte_to_binary(result));

  low = 1;
  high = 8;
  result = high << (4 + low); /* probably not intended */
  printf("result = %s\n", byte_to_binary(result));

  low = 1;
  high = 8;
  result = (high << 4) + low; /* probably the
                               * correct implementation */
  printf("result = %s\n", byte_to_binary(result));

  a = 3;
  a++;
  printf("a = %d\n", a);
  ++a;
  printf("a = %d\n", a);

  b = 3;
  b--;
  printf("b = %d\n", b);
  --b;
  printf("b = %d\n", b);

}
Rezultat:
/precendata.exe
flag = 2
result = 00000001
result = 00001000
result = 00000000
result = 00000000
result = 10000001
a = 4
a = 5
b = 2
b = 1

Regula de bază pentru a evita problemele este :
Fiecare subexpresie a unei expresii mai complicate ar trebui flancată de parenteze.
Exemplu:
   r = (hi << 4) + (low >> 2); /* operatiile flancate de paranteze 
                                * sunt executate primele */

E bine să ne bazăm şi pe cele două reguli MISRA:
MISRA-C:2004, Rule 12.1: Limited dependence should be placed on C’s operator precedence rules in expressions

MISRA-C:2004, Rule 12.2: The value of an expression shall be the same under any order of evaluation that the standard permits

Nu uitaţi , Keep It Simple!

luni, 11 februarie 2013

Alocarea variabilelor în embedded C (1)

În primul rând durata de stocare determină timpul de viata al unui obiect, în cazul nostru a variabilelor. Un obiect există, are o adresă constantă şi reţine ultima valoare stocată de-a lungul vieţii.
Există 3 tipuri de durate de stocare:
- Static
- automatic
- Alocate dinamic

1. Variabilele "statice"
Un obiect are o durata statică "static" de alocare dacă:
- Identificatorul este declarat cu linkage extern sau intern
- Identificatorul este declarat folosind cuvântul cheie "static"
Acest tip de obiect are durata de viaţă a întregului program şi este iniţializat doar o singură dată la începutul rulării programului.

2. Automatic
Un obiect a cărui identificator nu are linkage și fără cuvântul cheie static are durata de stocare automatic. De exemplu o variabila declarata în interiorul unei funcţii folosind cuvântul cheie auto se va considera locală şi nu va fi vizibilă în alte funcţii din interiorul modulului.
Durata de viaţă a acestor variabile este limitată pe durata execuţiei funcţiei. Pentru aceste variabile compilatorul de obicei nu va aloca memorie ci va "optimiza" aceste variabile şi se vor folosi regiştrii pentru procesarea lor.

/*variabile globale*/
unsigned char a=2;
unsigned char b=3;

void f (void)
{
/* variabile locale*/
auto int a=1;
auto int b=2;

}
void f2()
{
 /* variabila locala */
 int c; 
 
 /* rezultatul va fi c = 5 */
 c = a + b;
}

3. Alocate (memorie dinamică) Variabilele alocate dinamic au durată de viaţă variabilă. Se alocă de către programator folosind funcţia malloc în memoria dinamică (heap memory). Proprietate de bază a acestui tip de memorie este că are o dimensiune infinită. De fapt nu există acest tip de memorie. Acest tip de memorie a fost inventat în sistemele de operare moderne care dispun de spaţii de memorie foarte mare care pot fi considerate "infine". Într-un mediul embedded şi mai ales în sistemele safety-critical acest tip de alocare nu este permisă. Motivul este lesne de înţeles : memoria dinamică este prin definiţie nedeterministă şi nu prea se împacă cu , de exemplu un microcontroler pe 16 biți cu spaţiu de adresare de 65536 adrese , cu o memorie de program (flash) de câţiva kilo octeţi, cu o memorie RAM limitată şi eventual cu un spţiu de stocare EEPROM de 32 KB.
În embedded se aplică regula de mai jos:
MISRA-C:2004, Rule 20.4: Dynamic heap memory allocation shall not be used.
Chiar şi în sistemele cu suficientă memorie este recomandat să se utilizeze cu mare atenţie acest tip de alocare pentru că este nedeterminist. (e ca vinul roşu, e bun dar în cantităţi mici :) )


Durata de stocare și linkage-ul
Obiectele sau variabilele definite în interiorul funcţiilor care nu sunt declarate folosind cuvântul cheie static, nu au linkage şi nici durată de stocare statică. Obiectele care nu au linkage și care au durata statica de stocare mențin ultima valoare între două apeluri de funcție. Inițializarea acestor variabile nu este dinamică, dacă aceste variabile sunt inițializate folosind o instrucțiune și nu o expresie de inițializare atunci asignarea este executata de fiecare data când se apelează funcția.

static int a; /* Linkage intern in modul, 
               * durata statica de stocare 
               * (variabila globala in modul) */
int b; /* linkage extern, 
        * durata statica de stocare
        * (variabila globala pentru toate 
        * fisierele din proiect) */
 
void func (void)
{
int c; /* nu are linkage , are durata auto de stocare (locala) */
static int d; /* nu are linkage, are durata statica de stocare */
static int e = 2+1; /* ... cu initializare, 
                     * aceasta initializare 
                     * se va face de fiecare 
                     * data cand se apeleaza functia */
}

sâmbătă, 9 februarie 2013

Bitfield în embedded C

Un mod foarte util de a folosi structurile este bitfield-urile. Practic structura statusBitfield8 contine doar un singur byte (8 biți) de informație utilă. Dar fiecare bit poate să însemne orice dorește programatorul. Cea de-a doua structură conține 2 bytes (16 biți). În embedded C se încurajează foarte mult folosirea memoriei foarte rațional pentru a se elimina risipa de informație. Fiecare bit trebuie folosit la maxim. Acest lucru este foarte util în momentul în care avem un microcontroller cu putina memorie.
În programul de mai jos practic folosesc doar 3 bytes de date(24 de biți). Practic folosesc 24 de variabile te tip boolean.
#include 

struct
{
  unsigned char bit0:1;
  unsigned char bit1:1;
  unsigned char bit2:1;
  unsigned char bit3:1;

  unsigned char bit4:1;
  unsigned char bit5:1;
  unsigned char bit6:1;
  unsigned char bit7:1;
} statusBitfield8;

struct
{
  unsigned short bit0:1;
  unsigned short bit1:1;
  unsigned short bit2:1;
  unsigned short bit3:1;

  unsigned short bit4:1;
  unsigned short bit5:1;
  unsigned short bit6:1;
  unsigned short bit7:1;

  unsigned short bit8:1;
  unsigned short bit9:1;
  unsigned short bit10:1;
  unsigned short bit11:1;

  unsigned short bit12:1;
  unsigned short bit13:1;
  unsigned short bit14:1;
  unsigned short bit15:1;
} statusBitfield16;

int main()
{
  printf( "Memory size occupied by statusBitfield8 : %d\n", sizeof(statusBitfield8));
  printf( "Memory size occupied by statusBitfield16 : %d\n", sizeof(statusBitfield16));

  /*Setarea bitilor*/
  statusBitfield8.bit0=1;
  statusBitfield16.bit15=1;
  /*Afisarea structurilor*/
  printf( " statusBitfield8 : %d\n", statusBitfield8);
  printf( " statusBitfield16 : %d\n", statusBitfield16);
  return 0;
}
rezultatul programului este : D:\MinGW\msys\1.0\home\Florin>bitfield.exe
Memory size occupied by statusBitfield8 : 1
Memory size occupied by statusBitfield16 : 2
statusBitfield8 : 1
statusBitfield16 : 32768

Compilare in C folosind mediul MINGW32

Compilarea pentru exemplele prezentate pe site le-am încercat în gcc , versiunea folosită în mediul de programare al celor de la MinGW32 (gcc-4.6.2). Instalarea se face descărcând de aici ultima versiune stabilă și durează max 5 min.
E destul de simplu de folosit, în primul rând se deschide fereastra de compilare MINGW32 iar apoi după compilare rezultă un executabil care poate fi rulat în MS-DOS (cmd.exe din Windows). Este foarte ușor de folosit chiar si pentru programele mai mari.
Vizitați și pagina de howto pentru începători iar apoi vă puteți apuca de programat în limbajul C.
Codul se salvează într-un fișier folosind Notepad sau orice alt editor de text. Fișierul pointer_1.c :
#include 
int main()
{
 unsigned char i=19; 
 unsigned char *ip;
 
 ip = &i;
 
 printf("&i=%p\n",&i);
 printf("&ip=%p\n",&ip);
 printf("i=%d\n",i);
 printf("*ip=%d\n",*ip);
 printf("ip=%p\n",ip);
 
 return 0;
}

Compilarea se executa tastând comanda in MINGW32:
Florin@Florin-PC ~
$ gcc pointer_1.c -o pointer_1.exe
și rezultatul este următorul:
D:\MinGW\msys\1.0\home\Florin>pointer_1.exe
&i=0022FF1F
&ip=0022FF18
i=19
*ip=19
ip=2293535

În concluzie:
Pas 1: Download MINGW32 și instalează.
Pas 2: Alege un editor de cod (eu folosesc PSPad).
Pas 3: Scrie codul sursă.
Pas 4: Compilează.
Pas 5: Execută programul rezultat.

Ce părere aveți ?

joi, 7 februarie 2013

Variabile de tip pointeri în C - pointer la o funcţie (2)

În cazul variabilelor de tip pointer la o funcție e un pic mai complicat. In variabila pointer se stochează adresa funcției. Adresa respectivă poate să se afle într-un alt fișier c sau chiar într-un dll.
Trebuiesc respectate două reguli de bază pentru a avea un cod cat mai clar:
1. Pentru apelul funcțiilor este imperativ sa se folosească parantezele ().
2. Pentru a prelua adresa unei funcții se folosește operatorul de adresă &.

void functie_1 (void)
{
  /* codul tau aici */
}

void functie_2 (void)
{
  /* codul tau aici */
}

void g (void) {
/* converted to "pointer to"* and assigned */
void (*pf_1)(void) = &functie_1;
/* converted to "pointer to"* and assigned */ 
void (*pf_2)(void) = &functie_2;

functie_1(); /* apel al functiei 1 */
pf_1();      /* si acesta e un apel al functiei 1*/    
pf_2();      /* acesta e un apel al functiei 2 */    
}
/*un exemplu mai obscur dar de asemenea corect */
void f (void)
{
 ;
}
void g (void) {
void (*pf)(void) = &f;
&f();
(*pf)();
}
/*
* In exemplul de mai jos toate apelurile de functii sunt echivalente
*/
void f (void)
{
 ;
}
void g (void)
{
f();
(f)();
(*f)();
(**f)();
(*******f)();
(&f)();
}
/* Utilizarea operatorului de adresa este redundant 
   dar este foarte util pentru cel care citeste codul */
int f (void) {
   /* code */
}
void g (void) 
{
  if (f != 0) /* suspicios */
  {
   ;
  }
  if (f() != 0) /* se face de fapt verificarea return-ului 
functiei care este void - e cam obscur */
  {
   ;
  }
  if ( &f != 0) /* redundant, dar foarte clar */
  {
   ; 
  }
 }
}
Sugestia mea este sa păstrați codul cat mai simplu.Credeți-mă, o să încercaţi să înțelegeți codul peste 2-3 luni și o să vă fie foarte ușor.
Conceptul K.I.S. (Keep It Simple) ar trebui să se aplice peste tot, inclusiv în programare. (sau K.I.S.S. Keep It Simple Stupid :) )

Acum ceva vreme am căutat prin codul scris prin facultate şi m-am chinuit un pic până să înțeleg.

Alte tutoriale mai detaliate: http://www.cprogramming.com/tutorial/function-pointers.html
http://www.tutorialspoint.com/cplusplus/cpp_function_call_by_pointer.htm

Pentru cei care vor să înveţe C atunci cumpăraţi cartea C Programming Language (2nd Edition) scrisă de Dennis M. Ritchie şi Brian W. Kernighan

miercuri, 6 februarie 2013

Variabile de tip pointeri în C - pointer la un obiect (1)

Pointerii sunt variabile care țin o adresă.
Mai ştiinţific spus un pointer este o variabilă a cărui valoare este adresa altei variabile şi care îţi oferă oportunitatea de a accesa orice locaţie de memorie (din punctul acesta de vedere e destul de periculos, dar dacă ştii ce "meştereşti" nu ar fi nici o problemă).
Exista doua tipuri de pointeri:
- pointeri la un obiect
- pointer la o funcție
#include "stdio.h"

void main ()
{
   int  var = 23;   /* declaratia variabilei */
   int  *ip;        /* declaratia variabilei pointer */

   ip = &var;  /* stocheaza adresa variabilei var in variabila pointer ip*/

   printf("Adresa variabilei var este: %p\n", &var  ); /*%p afiseaza pointer , 
   in cazul acesta adresa variabilei var */

   /* Adresa stocata in variabila pointer */
   printf("Adresa variabilei var stocata in ip este: %p\n", ip );

   /* Accesarea valorii variabilei folosind pointerul */
   printf("Valoare variabilei (*ip) este: %d\n", *ip );
}

Alte informaţii despre pointeri

luni, 4 februarie 2013

Domenii de vizibiliate în C (Scope)

Am un exemplu simplu care arată domeniile de vizibilitate a variabilelor în embedded C:

int x; /* file scope */

void f (int y); /* y has function prototype scope */

void f (int y) /* y has block scope */
{
  int z; /* block scope */
  {
    int x; /* block scope, different object than outer x */
    int z; /* block scope */
  } /* scope of x and z end here */
} /* scope of y and z and here */


O variabilă declarată în interiorul unui bloc de acolade este vizibilă doar în acel bloc şi în toate blocurile de cod din interiorul blocului unde a fost declarată variabila.
O variabilă declarată în interiorul unei funcţii este vizibilă doar în aceea funcţie dar în toate blocurile de cod din acea funcţie.
O variabilă declarată în interiorul unui fişier C este vizibilă doar în acel fişier dar în toate funcţiile şi blocurile de cod din acel fişier.
Există şi o regulă MISRA care legiferează denumirea variabilelor :
"MISRA-C:2004, Rule 5.2: Identifiers in an inner scope shall not use the same name as an identifier in an outer scope, and therefore hide that identifier."

Destin

“Ai grijă ce gandeşti, gândurile tale devin cuvinte
 Ai grijă ce spui, cuvintele devin acţiuni
 Ai grijă ce faci, acţiunile devin obiceiuri
 Ai grijă ce obisnuiesti sa faci, obisnuintele devin caracter
 Analizează-ţi caracterul, el iţi devine destin”
                                             (Frank Outlaw)