C

Gjuha e vjetër por ende mbretëreshë: sistemet operative, pajisjet elektronike dhe themeli i shumë gjuhëve të tjera. · 102 terma

++i vs i++

Rritja para dhe pas

Të dyja e rrisin i-në me 1, por ndryshon vlera që kthejnë: ++i e rrit dhe pastaj e jep vlerën e re, ndërsa i++ e jep vlerën e vjetër dhe pastaj e rrit. Mos i përdor dy herë në të njëjtën shprehje — është sjellje e papërcaktuar.

2D arrays

Vargjet dydimensionale

Një varg dydimensional është një varg vargjesh — si një tabelë me rreshta dhe kolona. a[1][2] është elementi në rreshtin 2, kolonën 3 (numërimi fillon nga 0). Përdoret për matrica, tabela loje dhe imazhe.

Arrays and pointers

Vargjet dhe pointer-ët

Në C, kur ia jep një varg një funksioni, ai „shndërrohet“ në pointer drejt elementit të parë — funksioni s'e di më sa elemente ka. Prandaj në C gjithmonë ia kalon madhësinë si parametër të veçantë.

Arrays of strings

Vargjet e teksteve

Në C, një listë tekstesh është një varg pointer-ësh drejt char: const char *qytetet[] = {"Pejë", "Tiranë"};. argv te main është pikërisht një varg i tillë.

Arrow operator (->)

Operatori shigjetë

Operatori -> lexon një fushë të struct-it përmes një pointer-i: p->emri është njësoj si (*p).emri, por shumë më i lexueshëm. Me pikë (.) punon kur ke vetë struct-in; me shigjetë (->) kur ke pointer-in drejt tij.

assert

assert(kusht) e ndal programin me një mesazh të qartë nëse kushti është false. Përdoret për të kapur gabime gjatë zhvillimit — „kjo s'duhet të ndodhë kurrë“. Me -DNDEBUG çaktivizohen në versionin final.

atoi & strtol

atoi("42") e kthen tekstin në numër, por s'të tregon nëse teksti ishte i gabuar ("abc" jep thjesht 0). strtol() është më i sigurt: të tregon ku ndaloi leximi, që ta dish nëse ishte numër i vlefshëm.

Binary files (fread, fwrite)

Skedarët binarë

Skedarët binarë ruajnë bajtët ashtu siç janë në memorie, jo si tekst. Me fwrite() shkruan direkt një struct, me fread() e lexon prapa, dhe me fseek() lëviz në një pozicion të caktuar. Hapen me "rb" ose "wb".

Bit fields

Fushat me bit-e

Te bit fields, një fushë e struct-it zë vetëm aq bit-e sa i thua — unsigned ndezur : 1; Kursen memorie në pajisje të vogla dhe në protokolle rrjeti.

Bit flags & masks

Flamujt me bit-e

Me flamuj bit-esh, një numër i vetëm mban disa opsione po/jo — secili bit është një çelës. Me | e ndez një flamur, me & e kontrollon, me & ~ e fik. Kështu punojnë p.sh. lejet e skedarëve në Linux.

Bitwise operators (&, |, ^, <<)

Operatorët mbi bit-et

Operatorët bitwise punojnë me çdo bit të një numri veç e veç: & (DHE), | (OSE), ^ (OSE ekskluzive), ~ (kthim), dhe << / >> (zhvendosje majtas/djathtas). 1 << 3 jep 8. Përdoren shumë në pajisje elektronike, grafikë dhe kriptografi.

bool in C (stdbool.h)

Tipi bool në C

C-ja e vjetër s'kishte true dhe false: 0 do të thoshte „jo“ dhe çdo numër tjetër „po“. Me <stdbool.h> merr tipin bool dhe fjalët true/false, që e bëjnë kodin më të lexueshëm (në C23 janë pjesë e gjuhës).

bsearch

bsearch() kërkon shpejt një vlerë në një varg të renditur me kërkim binar dhe kthen një pointer drejt saj, ose NULL nëse s'e gjen. Përdor të njëjtin funksion krahasimi si qsort().

Buffer overflow

Tejmbushja e buffer-it

Buffer overflow ndodh kur shkruan më shumë të dhëna në një varg sesa nxë — p.sh. një emër 100 shkronjash në char[10]. Të dhënat e tepërta mbishkruajnë memorien fqinje. Është ndër gabimet më të rrezikshme të sigurisë: hakerët e kanë përdorur për të marrë kontrollin e programeve.

C

C-ja është një nga gjuhët më të vjetra dhe më të rëndësishme, nga viti 1972. Është shumë e shpejtë dhe afër hardware-it; me të janë shkruar sisteme operative si Linux-i, dhe ka ndikuar gjuhë si C++, Java dhe JavaScript.

C data types (int, float, char)

Tipet e të dhënave në C

C-ja ka pak tipe bazë: char (një bajt, një shkronjë), short, int, long (numra të plotë të madhësive të ndryshme), float dhe double (numra me presje). Madhësia e saktë e tyre varet nga kompjuteri — prandaj ekziston sizeof.

C standards (C89, C99, C11, C23)

Versionet e C-së

C-ja ka disa versione zyrtare: C89/ANSI C (klasikja), C99 (shtoi // komente, bool dhe deklarimin e variablave kudo), C11, C17 dhe C23 më i riu. Me -std=c17 i thua kompajlerit cilin të përdorë.

C vs C++

Dallimet mes C dhe C++

C++ lindi si „C me klasa“, dhe pothuajse çdo kod C kompajlohet si C++. Por C++ shton klasa, template, STL, referenca dhe menaxhim automatik të memories, ndërsa C mbetet më i vogël, më i thjeshtë dhe më afër harduerit.

calloc & realloc

calloc() është si malloc, por e mbush memorien me zero. realloc() e ndryshon madhësinë e një blloku që e ke marrë më parë — p.sh. kur një listë rritet dhe s'nxë më. Mund ta zhvendosë bllokun diku tjetër, prandaj përdor pointer-in që të kthen.

char & ASCII codes

Karakteret dhe kodet ASCII

Në C, një char është thjesht një numër i vogël: 'A' është 65, 'a' është 97, '0' është 48. Prandaj mund të bësh llogaritje me shkronja — 'a' + 1 jep 'b', dhe '7' - '0' jep numrin 7.

Command-line arguments (argc, argv)

Argumentet e komandës

Kur nis një program nga terminali, mund t'i japësh fjalë pas emrit — p.sh. ./kopjo a.txt b.txt. Programi i merr te main(int argc, char *argv[]): argc tregon sa janë, argv[0] është emri i programit dhe argv[1]… janë fjalët e tua.

Compilation stages

Fazat e kompajlimit

Nga kodi C te programi kalon katër faza: paraprocesori (zbaton #include dhe #define), kompajleri (C → assembly), assembler-i (assembly → kod makine, skedar .o), dhe linker-i (i bashkon të gjitha në një program).

Compiler warnings (-Wall -Wextra)

Paralajmërimet e kompajlerit

Paralajmërimet e kompajlerit të tregojnë kod që ndoshta është gabim, edhe pse kompajlohet — variabla pa vlerë, = në vend të ==, tipe të përziera. Ndize gjithmonë -Wall -Wextra dhe mos i injoro.

const with pointers

const me pointer-ët

Me pointer-ët, const mund të mbrojë dy gjëra: const int *p — s'mund ta ndryshosh vlerën përmes p-së; int *const p — s'mund ta drejtosh p-në gjetkë. Lexohet nga e djathta në të majtë.

Core dump

Kur një program rrëzohet keq (p.sh. segfault), sistemi mund të ruajë një „core dump“ — një fotografi të memories në momentin e rrëzimit. Me GDB e hap dhe sheh saktë ku ndodhi.

CS50

CS50 është kursi falas i Harvard-it për hyrje në shkencat kompjuterike, ndër më të ndjekurit në botë. Fillon me Scratch dhe C — pointer-ë, memorie, algoritme — pastaj kalon te Python, SQL dhe web. Shkëlqyeshëm për fillestarët që duan bazë të fortë.

ctype.h (isdigit, toupper)

Header-i <ctype.h> ka funksione për karaktere: isdigit() kontrollon nëse është shifër, isalpha() nëse është shkronjë, isspace() nëse është hapësirë, dhe toupper()/tolower() i kthejnë në të mëdha/të vogla.

Dangling pointer

Pointer i varur

Një pointer i varur tregon te memorie që është liruar ose që s'ekziston më — p.sh. pas free(), ose te një variabël lokale e një funksioni që ka mbaruar. Po e përdore, rezultati është i paparashikueshëm. Pas free(p), shkruaj p = NULL.

Designated initializers

Inicializuesit me emër

Që nga C99, mund t'i inicializosh fushat e një struct-i sipas emrit: struct Pika p = { .y = 4, .x = 3 };. Fushat që s'i përmend bëhen 0. Kodi lexohet shumë më qartë.

Double free & heap corruption

Lirimi i dyfishtë

Po e thirre free() dy herë për të njëjtin pointer, ose po shkrove jashtë bllokut të marrë me malloc, „prish“ strukturat e brendshme të heap-it. Programi mund të rrëzohet shumë më vonë, në një vend krejt tjetër.

Embedded systems

Sistemet e integruara

Sistemet e integruara janë kompjuterë të vegjël brenda pajisjeve — lavatriçe, vetura, ora smart, termostate. Programohen kryesisht në C, sepse kanë pak memorie dhe duhet të jenë shumë të shpejtë dhe të besueshëm. Arduino-ja është hapi i parë.

Endianness

Renditja e bajtëve

Endianness është rendi në të cilin ruhen bajtët e një numri të madh në memorie: little-endian (bajti më i vogël i pari, si te procesorët Intel dhe ARM) ose big-endian (bajti më i madh i pari, si në rrjet). Ka rëndësi kur lexon skedarë binarë ose të dhëna nga rrjeti.

enum in C

enum në C

enum në C u jep emra numrave konstantë: enum Dita { HENE, MARTE, ... } — HENE është 0, MARTE 1, e kështu me radhë. Kodi lexohet më mirë se me numra „magjikë“ të shpërndarë kudo.

errno & perror

Kur një funksion i sistemit dështon (p.sh. fopen), ai e vendos numrin e gabimit në variablën globale errno. perror() e shfaq këtë gabim me fjalë — p.sh. „No such file or directory“ — që ta kuptosh menjëhere çfarë shkoi keq.

Exit codes

Kodet e daljes

Kur një program mbaron, ia kthen sistemit një numër: 0 do të thotë „gjithçka mirë“, çdo numër tjetër „ndodhi një gabim“. Skriptet dhe CI-ja e lexojnë këtë numër për të vendosur nëse duhet të vazhdojnë. exit() e mbyll programin nga kudo.

extern

extern i thotë kompajlerit: „kjo variabël ekziston, por është krijuar në një skedar tjetër“. Kështu disa skedarë .c mund ta ndajnë të njëjtën variabël globale. Deklarimi me extern zakonisht shkon në header.

fgets

fgets() lexon një rresht të tërë teksti, por kurrë më shumë se sa nxë vargu yt — ndryshe nga gets() i vjetër, që ishte aq i rrezikshëm sa u hoq nga gjuha. Është mënyra e sigurt për të lexuar tekst nga përdoruesi.

File I/O in C (fopen, fprintf)

Skedarët në C

Në C, një skedar e hap me fopen() ("r" për lexim, "w" për shkrim, "a" për shtim), shkruan me fprintf(), lexon me fgets() ose fscanf(), dhe e mbyll me fclose(). Kontrollo gjithmonë nëse fopen ktheu NULL.

Format specifiers (%d, %f, %s)

Specifikuesit e formatit

Specifikuesit e formatit i tregojnë printf-it dhe scanf-it çfarë lloj vlere të presin: %d për int, %f për float (%lf te scanf për double), %c për një shkronjë, %s për tekst dhe %p për adresë memorieje. Po e përdore të gabuarin, del rezultat i çuditshëm.

Function pointers

Pointer-ët e funksioneve

Një pointer funksioni mban adresën e një funksioni, që ta thërrasësh më vonë ose t'ia japësh një funksioni tjetër. Është mënyra e C-së për callback-e — p.sh. qsort() merr funksionin tënd të krahasimit.

Function-like macros

Makrot si funksione

#define KATROR(x) ((x) * (x)) duket si funksion, por paraprocesori thjesht zëvendëson tekstin. Pa kllapa shtesë, KATROR(1 + 2) jep 5 në vend të 9. Në C modern, preferohen funksionet inline.

Functions in C

Funksionet në C

Një funksion në C ka tipin e kthimit, emrin dhe parametrat: int mblidh(int a, int b) { return a + b; }. Duhet të jetë i deklaruar para se ta përdorësh — prandaj prototipet shkojnë lart ose në header.

GDB

GDB-ja (dhe LLDB-ja në macOS) është debugger-i i terminalit për C dhe C++: e ndal programin në një rresht (break), e ekzekuton hap pas hapi (next, step) dhe t'i tregon vlerat e variablave (print). Me bt sheh rrugën deri te një rrëzim.

getchar, putchar & puts

getchar() lexon një karakter nga hyrja dhe putchar() shkruan një; puts() shkruan një rresht të tërë bashkë me \n. Ciklet si while ((c = getchar()) != EOF) lexojnë gjithë hyrjen deri në fund.

Global vs local variables (C)

Variablat globale dhe lokale në C

Një variabël lokale jeton brenda funksionit ose bllokut ku krijohet; një globale deklarohet jashtë çdo funksioni dhe e sheh i gjithë skedari. Globalet e shumta e bëjnë kodin të vështirë për t'u ndjekur — përdori me kujdes.

goto

goto e çon programin direkt te një etiketë tjetër në të njëjtin funksion. Përdorimi i tepërt e bën kodin spageti, prandaj zakonisht shmanget — por në C ndonjëhere përdoret për pastrim në një vend të vetëm kur ndodh gabim.

Implicit conversions & integer promotion

Konvertimet automatike në C

C-ja i konverton vetë tipet gjatë llogaritjeve: char dhe short kthehen në int, dhe kur përzien int me double, rezultati është double. Me unsigned mund të dalin surpriza — p.sh. -1 > 0u është e vërtetë!

Integer division

Pjesëtimi me numra të plotë

Në C (dhe C++, Java), kur pjesëton dy int, rezultati është int — pjesa pas presjes thjesht hidhet: 7 / 2 jep 3, jo 3.5. Që ta marrësh 3.5, të paktën njëri numër duhet të jetë double: 7.0 / 2.

K&R (The C Programming Language)

„The C Programming Language“ nga Brian Kernighan dhe Dennis Ritchie (krijuesi i C-së), i quajtur thjesht K&R, është libri klasik për C-në. I shkurtër dhe i qartë, nga ai vjen tradita e programit të parë „hello, world“.

limits.h (INT_MAX)

Header-i <limits.h> tregon kufijtë e tipeve në kompjuterin tënd: INT_MAX (zakonisht 2 147 483 647), INT_MIN, LONG_MAX, CHAR_BIT. Të ndihmon të shmangësh tejmbushjen.

Linked list in C

Lista e lidhur në C

Në C, lista e lidhur ndërtohet me struct-e që kanë një vlerë dhe një pointer drejt nyjës tjetër, dhe çdo nyje e krijon me malloc. Është ushtrimi klasik për të kuptuar pointer-ët.

Loops in C (for, while, do-while)

Ciklet në C

C-ja ka tre cikle: for kur e di sa herë (for (int i = 0; i < 10; i++)), while kur përsërit derisa një kusht bëhet false, dhe do-while që ekzekutohet të paktën një herë.

main function in C

Funksioni main në C

Çdo program C fillon te int main(void). Kompjuteri e ekzekuton nga lart poshtë, dhe numri që kthen në fund (return 0) i tregon sistemit nëse programi mbaroi mirë (0) apo me gabim (diçka tjetër).

malloc & free

malloc() kërkon një copë memorie në heap gjatë ekzekutimit dhe të kthen një pointer drejt saj; free() e kthen kur s'të duhet më. Kontrollo gjithmonë nëse malloc ktheu NULL, dhe mos harro free — përndryshe ke memory leak.

math.h (sqrt, pow)

Header-i <math.h> ka funksione matematikore: sqrt(), pow(), fabs(), sin(), round(). Në Linux duhet t'i thuash kompajlerit ta lidhë librarinë me -lm, përndryshe del gabim „undefined reference to sqrt“.

memcpy, memset & memcmp

Këto funksione punojnë me bajtë të papërpunuar: memcpy() kopjon një bllok memorie, memset() e mbush me një vlerë (shpesh 0), memcmp() krahason dy blloqe. memmove() përdoret kur blloqet mbivendosen.

Memory alignment & padding

Rreshtimi i memories

Procesori lexon më shpejt kur të dhënat fillojnë në adresa „të rrumbullakëta“ (shumëfisha të 4 ose 8). Prandaj kompajleri shton bajtë bosh (padding) brenda struct-eve — dhe sizeof i një struct-i mund të dalë më i madh se shuma e fushave.

Memory layout (text, data, heap, stack)

Ndarja e memories së programit

Kur nis një program C, memoria e tij ndahet në pjesë: text (kodi), data dhe bss (variablat globale dhe static), heap (memoria me malloc, rritet lart) dhe stack (variablat lokale, rritet poshtë).

NULL (C)

NULL është makroja e C-së për një pointer që s'tregon askund. Funksionet si malloc() dhe fopen() e kthejnë NULL kur dështojnë, prandaj kontrollo gjithmonë: if (p == NULL).

Null terminator ('\0')

Karakteri përfundues

'\0' është karakteri me vlerë zero që shënon fundin e çdo teksti në C. Funksionet si printf dhe strlen ecin shkronjë pas shkronje derisa e gjejnë. Po mungoi, vazhdojnë të lexojnë memorie që s'i takon tekstit.

Online compilers

Kompajlerët online

Faqe si OnlineGDB, Replit ose Compiler Explorer (godbolt.org) të lejojnë të shkruash dhe ekzekutosh C, C++ e gjuhë të tjera direkt në shfletues, pa instaluar asgjë. Ideale kur je në kompjuterin e shkollës.

Operator precedence

Përparësia e operatorëve

Përparësia vendos cili veprim bëhet i pari: * dhe / para + dhe -, krahasimet para && dhe ||. Kur s'je i sigurt, vendos kllapa — kodi bëhet edhe më i lexueshëm.

Optimization flags (-O2)

Optimizimi i kompajlerit

Me -O2 ose -O3, kompajleri e rishkruan kodin tënd që të ekzekutohet më shpejt — heq llogaritjet e panevojshme, i fut funksionet e vogla direkt. Për debug përdoret -O0 -g, që kodi të ndjekë rreshtat e tu.

Output buffering (fflush)

Buffer-i i daljes

printf-i s'e shkruan menjëherë tekstin në ekran: e mban në një buffer dhe e nxjerr kur mbushet ose kur vjen \n. Nëse programi rrëzohet, teksti mund të humbasë. fflush(stdout) e detyron ta nxjerrë menjëherë.

Passing by pointer

Kalimi me pointer

C-ja i kalon gjithmonë parametrat si kopje. Që një funksion ta ndryshojë një variabël të jashtme, i jep adresën e saj (&x) dhe funksioni punon me *. Shembulli klasik është funksioni swap që ndërron dy numra.

Pointer arithmetic

Aritmetika e pointer-ëve

Kur i shton 1 një pointer-i, ai s'lëviz 1 bajt, por te elementi tjetër — për një int*, 4 bajtë më tej. Kështu p + 2 tregon elementin e tretë të vargut, dhe *(p + 2) është njësoj si p[2].

Pointer to pointer (**)

Pointer drejt pointer-it

Një pointer drejt pointer-it (int **pp) mban adresën e një pointer-i tjetër. Përdoret kur një funksion duhet ta ndryshojë vetë pointer-in (p.sh. ta drejtojë te memorie e re), ose për vargje dydimensionale dinamike.

POSIX & unistd.h

POSIX-i është standardi që përcakton si flasin programet me sistemet e ngjashme me Unix (Linux, macOS): funksione për skedarë, procese, thread-e dhe sinjale. Në C i merr nga header-a si <unistd.h> — p.sh. sleep(), fork(), read().

POSIX threads (pthreads)

pthreads është libraria standarde për thread-e në C në Linux dhe macOS: pthread_create() nis një thread, pthread_join() pret ta mbarojë, dhe pthread_mutex mbron të dhënat e përbashkëta.

printf

printf() është funksioni i C-së për të shfaqur tekst në ekran. Teksti mund të ketë „vende bosh“ si %d ose %s, që mbushen me vlerat që i jep pas presjes.

qsort

qsort() nga <stdlib.h> rendit çdo varg në C. I jep vargun, numrin e elementeve, madhësinë e secilit dhe një funksion krahasimi që kthen negativ, zero ose pozitiv.

rand & srand

rand() jep një numër „të rastësishëm“ nga <stdlib.h>, dhe me % e kufizon — rand() % 6 + 1 jep 1–6. Por pa srand(time(NULL)) në fillim, programi jep të njëjtat numra çdo here që e nis!

scanf

scanf() lexon atë që shkruan përdoruesi në tastierë dhe e ruan në variabla. Duhet t'i japësh adresën e variablës me & — p.sh. scanf("%d", &mosha) — që të dijë ku ta vendosë vlerën.

Signals (SIGINT, signal.h)

Sinjalet

Sinjalet janë njoftime që sistemi i dërgon programit — p.sh. SIGINT kur shtyp Ctrl+C, SIGSEGV kur ndodh segfault. Me signal() mund të vendosësh çfarë ndodh, p.sh. ta ruash punën para se të mbyllesh.

signed & unsigned

Një numër signed mund të jetë pozitiv ose negativ; një unsigned vetëm ≥ 0, por arrin dy here më lart. P.sh. një unsigned char shkon nga 0 në 255. <stdint.h> jep tipe me madhësi të saktë si uint8_t dhe int32_t.

size_t

size_t është tipi pa shenjë që përdoret për madhësi dhe numërime në C — sizeof dhe strlen() e kthejnë atë. Printohet me %zu. Meqë s'mund të jetë negativ, kujdes me ciklet që zbresin drejt zeros.

Sockets

Socket-et

Socket-et janë mënyra si programet komunikojnë në rrjet. Një server bën socket(), bind() në një portë, listen() dhe accept() për klientët; klienti bën connect(). Çdo shfletues dhe server ueb i përdor nga poshtë.

sprintf & snprintf

sprintf() e shkruan tekstin e formatuar në një varg në vend të ekranit. Por mund të tejkalojë madhësinë — prandaj përdor gjithmonë snprintf(), që s'shkruan kurrë më shumë se sa i thua.

Stack frame & call stack

Korniza e stack-ut

Sa here thërritet një funksion, në stack krijohet një „kornizë“ me parametrat, variablat lokale dhe adresën ku duhet të kthehet. Kur funksioni mbaron, korniza hiqet. Rekursioni pa fund i mbush këto korniza derisa ndodh stack overflow.

Standard headers (stdio.h, stdlib.h)

Header-at standardë të C-së

Libraria standarde e C-së është e ndarë në header-a që i fut me #include: <stdio.h> për hyrje/dalje (printf, scanf), <stdlib.h> për memorie dhe numra të rastësishëm, <string.h> për tekst, <math.h> për matematikë.

Static & shared libraries (.a, .so, .dll)

Libraritë statike dhe të përbashkëta

Një librari statike (.a, .lib) futet brenda programit tënd gjatë lidhjes — programi bëhet më i madh, por s'ka nevojë për gjë tjetër. Një librari e përbashkët (.so në Linux, .dll në Windows) ngarkohet kur nis programi dhe e ndajnë shumë programe.

Static analysis (clang-tidy, cppcheck)

Analiza statike

Analiza statike e kontrollon kodin pa e ekzekutuar dhe gjen gabime të mundshme: pointer-ë null, memorie e paliruar, kod i paarritshëm. Mjete si clang-tidy dhe cppcheck shkojnë më thellë se paralajmërimet e kompajlerit.

static in C

static në C

Në C, static ka dy kuptime: një variabël lokale static e mban vlerën mes thirrjeve të funksionit (s'rifillon nga zero), dhe një funksion ose variabël globale static shihet vetëm brenda skedarit të vet.

stdin, stdout & stderr

Çdo program ka tri „kanale“: stdin (hyrja, zakonisht tastiera), stdout (dalja normale) dhe stderr (për gabimet). Mesazhet e gabimit shkruaji në stderr me fprintf(stderr, ...), që të mos përzihen me rezultatet.

Storage duration (automatic, static, allocated)

Jetëgjatësia e variablave

Çdo variabël në C ka një jetëgjatësi: automatike (lokale — zhduket kur mbaron funksioni), static (jeton gjatë gjithë programit) dhe e alokuar (me malloc — jeton derisa ta lirosh me free).

string.h functions (strlen, strcpy, strcmp)

Funksionet e string.h

Meqë teksti në C është varg shkronjash, punët me tekst bëhen me funksione nga <string.h>: strlen() numëron shkronjat, strcpy() kopjon, strcat() bashkon dhe strcmp() krahason (kthen 0 kur janë të barabartë). Kujdes që vargu i destinacionit të jetë mjaft i madh.

Strings in C (char arrays)

Teksti në C

C-ja s'ka tip string: teksti është thjesht një varg shkronjash (char[]) që mbaron me një karakter të veçantë '\0'. Prandaj s'mund t'i krahasosh me == ose t'i bashkosh me + — përdor funksionet e <string.h>.

strtok

strtok() e ndan një tekst në copa sipas ndarësve — p.sh. presjeve. Herën e parë i jep tekstin, pastaj NULL për copat e tjera. Kujdes: e ndryshon tekstin origjinal.

struct in C

Struct-et në C

Një struct i bashkon disa vlera të lidhura në një tip të ri — p.sh. emri, mosha dhe nota e një nxënësi. Fushat i lexon me pikë (s.emri), ose me shigjetë (p->emri) kur ke një pointer. C-ja s'ka klasa; struct-et janë mjeti kryesor.

switch & fall-through (C)

switch në C

switch-i në C zgjedh një case sipas vlerës — por kujdes: pa break, programi vazhdon edhe te case-i tjetër („fall-through“). Shumë gabime vijnë nga një break i harruar.

System call

Thirrje sistemi

Një thirrje sistemi është mënyra si një program i kërkon kernel-it të bëjë diçka që s'mund ta bëjë vetë — të lexojë një skedar, të krijojë një proces të ri (fork), të dërgojë të dhëna në rrjet. printf-i në fund të fundit përdor thirrjen write().

The scanf newline problem

Problemi i Enter-it pas scanf

Pas scanf("%d", &n), Enter-i (\n) mbetet në hyrje — dhe fgets() ose getchar() i radhës e lexon menjëherë si rresht bosh. Zgjidhje: scanf(" %c") me hapësirë, ose lexo gjithçka me fgets dhe pastaj konverto.

time.h (time, clock)

Header-i <time.h> punon me kohën: time(NULL) jep sekondat që nga 1 janari 1970, clock() mat kohën e procesorit (për të parë sa zgjat kodi), dhe strftime() e formaton datën.

Type casting in C

Konvertimi i tipit në C

Në C e konverton një vlerë duke shkruar tipin në kllapa: (double)shuma / n. Kujdes: (int)3.99 jep 3 — pjesa pas presjes thjesht pritet, s'rrumbullakoset.

typedef

typedef i jep një emër të ri një tipi ekzistues. Përdoret shumë me struct-et, që të shkruash thjesht Nxenes në vend të struct Nxenes, ose për t'i dhënë kuptim një tipi — typedef unsigned char Bajt;.

union

Një union është si struct, por të gjitha fushat e tij ndajnë të njëjtin vend në memorie — mund të përdorësh vetëm njërën në një kohë. Kursen memorie, sidomos në pajisje të vogla, por duhet ta dish vetë cila fushë është aktive.

Valgrind

Valgrind-i e ekzekuton programin tënd dhe e kontrollon memorien: të tregon memory leak-et, leximin jashtë kufijve dhe përdorimin e memories pas free(). Mjet i domosdoshëm për projektet C në fakultet.

Variadic functions (...)

Funksionet me numër të ndryshueshëm argumentesh

Një funksion variadic pranon sa argumente të duash, si printf(). Në C shkruhet me ... dhe argumentet lexohen me va_start, va_arg dhe va_end nga <stdarg.h>.

void

void do të thotë „asgjë“. Një funksion void s'kthen vlerë; int main(void) do të thotë që main s'merr parametra; dhe void* është pointer pa tip.

void pointer (void*)

Pointer-i void

void* është një pointer „pa tip“ — mund të tregojë te çdo lloj të dhëne. malloc() kthen void*, dhe funksione si qsort() e përdorin që të punojnë me çdo tip. Para se ta lexosh vlerën, duhet ta kthesh në tipin e saktë.

volatile

volatile i thotë kompajlerit: „kjo variabël mund të ndryshojë jashtë kodit tënd — mos e optimizo, lexoje gjithmonë nga memoria“. Përdoret në pajisje elektronike, për regjistra harduerike ose variabla që i ndryshon një ndërprerje.

Wide characters & UTF-8 in C

Shkronjat speciale në C

Në C, një char është vetëm 1 bajt, por shkronjat si ë dhe ç në UTF-8 zënë 2 bajtë — prandaj strlen("ë") jep 2! Për të punuar me to si shkronja të plota, përdoren wchar_t dhe setlocale(), ose librari për UTF-8.