పాయింటర్లు, అర్రేస్, Double Pointers & కాల్‌బ్యాక్స్

⚡ Modern C (C99 / C11 / C17 Standards) 🟢 Chapter 16 of 20 📂 Phase 04: అర్రేస్, స్ట్రింగ్స్ & పాయింటర్లు 📅 2026 Academic Edition
📌 Covered in this chapter: ట్రెజర్ హంట్ ఎనాలజీ · arr[i] == *(arr + i) సీక్రెట్ · i[arr] విచిత్రం · పాయింటర్ vs అర్రే తేడాలు · Array of Pointers · డబుల్ పాయింటర్లు (**ptr) · కమాండ్ లైన్ argc & argv · ఫంక్షన్ పాయింటర్లు · qsort కాల్‌బ్యాక్స్ · ప్లగ్-అండ్-ప్లే ఇంజిన్ · ఇంటరాక్టివ్ క్విజ్

ఒక సాహసోపేతమైన నిధుల వేటను (Treasure Hunt) ఊహించుకోండి. మీరు అడవిలో మొదటి చెక్క పెట్టెను కనుగొని తెరిచారు. కానీ లోపల బంగారం ఉండదు; దానికి బదులుగా "నిధి ఉన్న రెండవ పెట్టె ఏ చెట్టు కింద ఉందో తెలిపే మ్యాప్" కనిపిస్తుంది (సింగిల్ పాయింటర్ *ptr). ఇప్పుడు ఆ మ్యాప్‌ను మీ చేతికి ఇచ్చిన గైడ్ బుక్ మీ వద్ద ఉందనుకుందాం — ఆ గైడ్ బుక్ నేరుగా నిధిని చూపించదు; అది మ్యాప్ ఉన్న పెట్టెను చూపిస్తుంది, ఆ మ్యాప్ అసలైన నిధిని చూపిస్తుంది! ఇది కంప్యూటర్ ప్రోగ్రామింగ్‌లోని డబుల్ పాయింటర్ (Pointer to Pointer - **ptr)!

ఇంతటితో ఆగకుండా, C లాంగ్వేజ్‌లోని అత్యంత అద్భుతమైన అంతర్గత రహస్యం మరొకటి ఉంది: మనం నిత్యం వాడే arr[i] అనేది అసలు C కంపైలర్ దృష్టిలో అర్రేనే కాదు! అది కేవలం ఒక తీపి పైపూత (Syntactic Sugar) మాత్రమే! కంపైలర్ దానిని తెరవెనుక నేరుగా *(arr + i) అనే పాయింటర్ అరిథ్‌మెటిక్‌గా మారుస్తుంది! అందుకే C లో arr[2] అని రాసినా లేదా 2[arr] అని రాసినా కంపైలర్ ఏమాత్రం తడబడకుండా ఒకే ఫలితాన్ని ఇస్తుంది!

ఈ పదహారవ అధ్యాయంతో మనం Phase 04 (అర్రేస్, స్ట్రింగ్స్ & పాయింటర్లు) ను విజయవంతంగా ముగించబోతున్నాం. ఇందులో అర్రే-పాయింటర్ ఈక్వివలెన్స్, డబుల్ పాయింటర్లు, టెర్మినల్ కమాండ్ లైన్ ఆర్గుమెంట్స్ (argc, argv), మరియు ఫంక్షన్లను వేరియబుల్స్‌లా పాస్ చేసే అడ్వాన్స్‌డ్ ఫంక్షన్ పాయింటర్లు & కాల్‌బ్యాక్స్ (Function Pointers & Callbacks) ను సమగ్రంగా మాస్టర్ చేద్దాం!

1ఈ Chapter లో మీరు నేర్చుకునే సమగ్ర అంశాలు (Roadmap)

అడ్వాన్స్‌డ్ C ప్రోగ్రామింగ్‌లో పాయింటర్లు మరియు అర్రేల సమన్వయం అనేది సాఫ్ట్‌వేర్ ఆర్కిటెక్ట్‌లకు అత్యంత కీలకమైన ఆయుధం. ఈ అధ్యాయంలో కవర్ చేయబడే ప్రధానాంశాలు:

  • అర్రే-పాయింటర్ అంతర్గత బంధం: arr[i] == *(arr + i) గణిత సమానత్వం మరియు i[arr] వింత ప్రవర్తన.
  • అర్రే వర్సెస్ పాయింటర్ కీలక తేడాలు: కాన్స్టాంట్ పాయింటర్ రీ-అసైన్‌మెంట్ పరిమితులు మరియు sizeof వ్యత్యాసాలు.
  • అర్రే ఆఫ్ పాయింటర్స్ (Array of Pointers - int *arr[]): పాయింటర్ల వరుస మరియు ర్యాగ్డ్ అర్రేస్ (Ragged Arrays).
  • డబుల్ పాయింటర్లు (Double Pointers - **ptr): పాయింటర్ యొక్క మెమరీ అడ్రస్‌ను పట్టుకునే లెవల్-2 ఇండైరెక్షన్.
  • ఫంక్షన్లలో పాయింటర్ మోడిఫికేషన్: ఫంక్షన్ లోపల కాలర్ యొక్క పాయింటర్‌ను మార్చడానికి డబుల్ పాయింటర్లు ఎందుకు తప్పనిసరి?
  • కమాండ్ లైన్ ఆర్గుమెంట్స్ (Command-Line Arguments): argc మరియు argv (అర్రే ఆఫ్ స్ట్రింగ్స్ char**) విశ్లేషణ.
  • సమగ్ర తులనాత్మక పట్టిక: *arr[] (అర్రే ఆఫ్ పాయింటర్స్) vs (*arr)[] (పాయింటర్ టు యాన్ అర్రే).
  • ఫంక్షన్ పాయింటర్లు (Function Pointers): కోడ్ సెగ్మెంట్‌లో ఫంక్షన్ల మెమరీ అడ్రస్‌లు మరియు సింటాక్స్ డీకోడింగ్.
  • కాల్‌బ్యాక్ ఫంక్షన్స్ (Callback Architecture): లైబ్రరీలకు ఫంక్షన్లను పాస్ చేయడం మరియు C స్టాండర్డ్ qsort() ఇంజిన్.
  • డైనమిక్ 2D అర్రేస్ పరిచయం: డబుల్ పాయింటర్లతో రన్‌టైమ్ గ్రిడ్ నిర్మాణం.
  • సమగ్ర రియల్ వరల్డ్ ప్రాజెక్ట్: ప్లగ్-అండ్-ప్లే ఫంక్షన్ పాయింటర్ మ్యాథమెటికల్ క్యాలిక్యులేటర్ ఇంజిన్.
  • బిగినర్స్ చేసే టాప్ 5 అడ్వాన్స్‌డ్ తప్పులు: బ్రాకెట్స్ మిస్సింగ్, డబుల్ పాయింటర్ అన్‌ఇనిషియలైజ్డ్ సెగ్‌ఫాల్ట్స్.
  • స్వీయ మూల్యాంకన క్విజ్: 5 లోతైన విశ్లేషణాత్మక ప్రశ్నలు & గేట్ ఎగ్జామ్ కాన్సెప్ట్స్.
2అర్రే-పాయింటర్ అంతర్గత బంధం — arr[i] == *(arr + i) సీక్రెట్

C లాంగ్వేజ్‌లో ఒక ప్రాథమిక సూత్రం ఉంది: "An array name evaluates to the address of its first element." (అర్రే పేరు అనగా దాని మొదటి ఎలిమెంట్ యొక్క బేస్ అడ్రస్ &arr[0]). మీరు స్క్వేర్ బ్రాకెట్లతో రాసే ఇండెక్సింగ్ సింటాక్స్ కంపైలర్ కోసం కేవలం ఒక పాయింటర్ అరిథ్‌మెటిక్ మాత్రమే:

$$ ext{arr}[i] iff *( ext{arr} + i)$$

కూడిక అనేది స్థిత్యంతర ధర్మాన్ని (Commutative Property: $A + B = B + A$) పాటిస్తుంది కాబట్టి:

$$*( ext{arr} + i) iff *(i + ext{arr}) iff i[ ext{arr}]$$
C — Array and Pointer Equivalence Proof (i[arr] Demo)
#include <stdio.h>

int main() {
    int arr[4] = {10, 20, 30, 40};

    // ఈ 4 పద్ధతులు పూర్తిగా ఒకే ఒక్క విలువను ఇస్తాయి!
    printf("1. సాధారణ ఇండెక్సింగ్ arr[2]   = %d\n", arr[2]);
    printf("2. పాయింటర్ నోటేషన్ *(arr + 2) = %d\n", *(arr + 2));
    printf("3. తిరగరాసిన పాయింటర్ *(2 + arr) = %d\n", *(2 + arr));
    printf("4. విచిత్రమైన ఇండెక్సింగ్ 2[arr]    = %d (పూర్తిగా చెల్లుతుంది!)\n", 2[arr]);

    return 0;
}
💡 ఇంటర్వ్యూ సీక్రెట్: ఇంటర్వ్యూయర్ మిమ్మల్ని గందరగోళ పరచడానికి 2[arr] అని కోడ్ ఇస్తే భయపడకండి! అది arr[2] తో సమానం. అయితే ప్రొడక్షన్ కోడ్‌లో రీడబిలిటీ కోసం ఎల్లప్పుడూ ప్రామాణిక arr[i] మాత్రమే వాడాలి.
3పాయింటర్ vs అర్రే మధ్య గల కీలక తేడాలు

అర్రే పేరు పాయింటర్‌లా ప్రవర్తించినప్పటికీ, అర్రే మరియు పాయింటర్ ఒకటి కావు! వాటి మధ్య రెండు భారీ సాంకేతిక వ్యత్యాసాలు ఉన్నాయి:

1. కాన్స్టాంట్ పాయింటర్ (Re-assignment):

పాయింటర్ అనేది ఒక సాధారణ వేరియబుల్, దానిని వేరొక అడ్రస్‌కి మార్చవచ్చు (ptr = &y;). కానీ అర్రే పేరు ఒక స్థిరమైన కాన్స్టాంట్ పాయింటర్! దానిని వేరొక అడ్రస్‌కి మార్చలేము (arr = ptr; // ❌ COMPILE ERROR!).

2. sizeof ఆపరేటర్ ప్రవర్తన:

int arr[5]; పై sizeof(arr) లెక్కిస్తే మొత్తం 20 బైట్లు (5 * 4) వస్తుంది. కానీ int *ptr = arr; పై sizeof(ptr) లెక్కిస్తే కేవలం 8 బైట్లు (పాయింటర్ సైజు) మాత్రమే వస్తుంది!

4అర్రే ఆఫ్ పాయింటర్స్ (Array of Pointers - int *arr[])

సాధారణ అర్రే సంఖ్యలను దాచుకుంటే, అర్రే ఆఫ్ పాయింటర్స్ మెమరీ చిరునామాలను (Pointers) ఒక వరుసలో నిల్వ చేస్తుంది. వేర్వేరు పొడవులు గల స్ట్రింగ్స్‌ను మెమరీ వేస్ట్ కాకుండా నిల్వ చేయడానికి ఇది అద్భుతంగా పనిచేస్తుంది:

C — Array of String Pointers
#include <stdio.h>

int main() {
    // 4 స్ట్రింగ్ పాయింటర్ల అర్రే (Array of 4 char pointers)
    const char *districts[] = {
        "హైదరాబాద్",
        "విశాఖపట్నం",
        "విజయవాడ",
        "వరంగల్"
    };

    printf("=== అర్రే ఆఫ్ పాయింటర్స్ డిస్‌ప్లే ===\n");
    for (int i = 0; i < 4; i++) {
        printf("జిల్లా #%d: %s (అడ్రస్: %p)\n", i + 1, districts[i], (void*)districts[i]);
    }

    return 0;
}
5డబుల్ పాయింటర్లు (Pointer to Pointer - **ptr) & వాడకం

ఒక పాయింటర్ కూడా RAM లో ఉండే సాధారణ వేరియబుల్ మాత్రమే కాబట్టి దానికి కూడా ఒక మెమరీ అడ్రస్ ఉంటుంది. ఆ పాయింటర్ యొక్క అడ్రస్‌ను పట్టుకునే పాయింటర్‌ను డబుల్ పాయింటర్ (**ptr) అంటారు.

డబుల్ పాయింటర్ ఎప్పుడు అవసరం?

ఒక ఫంక్షన్ లోపల సాధారణ వేరియబుల్ విలువను మార్చడానికి మనం సింగిల్ పాయింటర్ (&x) పాస్ చేస్తాం కదా? అదే విధంగా, ఒక ఫంక్షన్ లోపల ఒక పాయింటర్ పట్టుకున్న అడ్రస్‌నే మార్చాల్సి వస్తే, ఆ పాయింటర్ యొక్క అడ్రస్‌ను (డబుల్ పాయింటర్ &ptr) పాస్ చేయాలి!

C — Modifying a Pointer via Double Pointer
#include <stdio.h>

int numA = 100;
int numB = 200;

// ఫంక్షన్ లోపల పాయింటర్‌ను numA నుండి numB కి మారుస్తున్నాం
void changeTarget(int **doublePtr) {
    *doublePtr = &numB; // కాలర్ యొక్క పాయింటర్ అడ్రస్ మార్చబడింది!
}

int main() {
    int *myPtr = &numA;
    printf("ఫంక్షన్ కాల్ కి ముందు: *myPtr = %d (numA)\n", *myPtr);

    changeTarget(&myPtr); // పాయింటర్ అడ్రస్ (&myPtr) ని పాస్ చేస్తున్నాం

    printf("ఫంక్షన్ కాల్ తర్వాత : *myPtr = %d (numB కి మారింది!)\n", *myPtr);
    return 0;
}
6కమాండ్ లైన్ ఆర్గుమెంట్స్ అనాటమీ (argc & argv)

మనం టెర్మినల్‌లో gcc main.c -o app అని కమాండ్స్ రన్ చేస్తాం కదా? ఇక్కడ main.c, -o, app అనేవి కమాండ్ లైన్ ఆర్గుమెంట్స్. C ప్రోగ్రామ్‌లు టెర్మినల్ నుండి ఇన్‌పుట్ అందుకోవడానికి main() ఫంక్షన్‌కు రెండు పారామీటర్లు ఉంటాయి:

  • int argc (Argument Count): టెర్మినల్ నుండి పాస్ చేసిన మొత్తం పదాల సంఖ్య (ప్రోగ్రామ్ పేరుతో సహా, ఎల్లప్పుడూ ≥ 1).
  • char *argv[] (Argument Vector): ఆ పదాల స్ట్రింగ్ పాయింటర్ల అర్రే (డబుల్ పాయింటర్ char**).
C — Command-Line Arguments Parser
#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("=== కమాండ్ లైన్ ఆర్గుమెంట్స్ అనలిటిక్స్ ===\n");
    printf("మొత్తం ఆర్గుమెంట్ల సంఖ్య (argc) = %d\n", argc);

    for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
    }

    return 0;
}
7సమగ్ర తులనాత్మక పట్టిక (*arr[] vs (*arr)[])

C ఇంటర్వ్యూలలో అడిగే అత్యంత కఠినమైన బ్రాకెట్ ప్రిసిడెన్స్ ప్రశ్న:

డిక్లరేషన్ సాంకేతిక అర్థం మెమరీ స్వభావం ప్రధాన ఉపయోగం
int *arr[5]; Array of 5 Pointers (5 పాయింటర్ల అర్రే). 5 వేర్వేరు మెమరీ అడ్రస్‌లను భద్రపరుస్తుంది (5 × 8 = 40 బైట్లు). విభిన్న పొడవులు గల స్ట్రింగ్స్, ర్యాగ్డ్ అర్రేస్.
int (*arr)[5]; Pointer to an Array of 5 ints (5 ఎలిమెంట్స్ గల అర్రేను పాయింట్ చేసే ఒకే ఒక్క పాయింటర్). కేవలం ఒకే ఒక్క పాయింటర్ (8 బైట్లు). 2D మ్యాట్రిక్స్‌లను ఫంక్షన్లకు పాస్ చేసేటప్పుడు అడ్డు వరుసలను పాయింట్ చేయడానికి.
8ఫంక్షన్ పాయింటర్లు (Function Pointers) — కోడ్ సెగ్మెంట్ అడ్రస్లు

కంప్యూటర్ RAM లో కేవలం వేరియబుల్స్ మాత్రమే కాదు; మనం రాసిన ఫంక్షన్ల మెషీన్ కోడ్ కూడా ఒక మెమరీ అడ్రస్ లోనే నిల్వ ఉంటుంది (Code Segment / Text Segment)! ఆ ఫంక్షన్ యొక్క మెమరీ చిరునామాను పట్టుకునే పాయింటర్‌ను ఫంక్షన్ పాయింటర్ (Function Pointer) అంటారు!

ఫంక్షన్ పాయింటర్ సింటాక్స్ అనాటమీ:

రిటర్న్_టైప్ (*పాయింటర్_పేరు) ( పారామీటర్ల_జాబితా );
ఉదాహరణ: int (*operationPtr)(int, int);
C — Basic Function Pointer Invocation
#include <stdio.h>

int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }

int main() {
    // ఫంక్షన్ పాయింటర్ డిక్లరేషన్
    int (*mathFunc)(int, int);

    // 1. add ఫంక్షన్ అడ్రస్ ని అసైన్ చేస్తున్నాం
    mathFunc = add;
    printf("add ఫంక్షన్ మెమరీ అడ్రస్: %p\n", (void*)mathFunc);
    printf("mathFunc(10, 20) ఫలితం = %d\n", mathFunc(10, 20));

    // 2. రన్‌టైమ్‌లో multiply ఫంక్షన్‌కి మారుస్తున్నాం!
    mathFunc = multiply;
    printf("multiply మెమరీ అడ్రస్   : %p\n", (void*)mathFunc);
    printf("mathFunc(10, 20) ఫలితం = %d\n", mathFunc(10, 20));

    return 0;
}
9కాల్‌బ్యాక్ ఫంక్షన్స్ (Callback Architecture & qsort)

ఒక ఫంక్షన్‌కు మరొక ఫంక్షన్‌ను పారామీటర్‌గా పంపడాన్ని కాల్‌బ్యాక్ (Callback) అంటారు. C స్టాండర్డ్ లైబ్రరీలోని ప్రసిద్ధ qsort() అల్గారిథమ్ దీనికి అత్యుత్తమ ఉదాహరణ. సంఖ్యలను అసెండింగ్ లేదా డిసెండింగ్ ఆర్డర్‌లో ఎలా సార్ట్ చేయాలో మనం ఒక కాల్‌బ్యాక్ ఫంక్షన్ ద్వారా qsort కు అందిస్తాం:

C — qsort with Custom Comparator Callback
#include <stdio.h>
#include <stdlib.h>

// qsort కోసం కంపారేటర్ కాల్‌బ్యాక్ ఫంక్షన్
int compareAscending(const void *a, const void *b) {
    int valA = *(const int*)a;
    int valB = *(const int*)b;
    return valA - valB; // పాజిటివ్ అయితే స్వాప్ చేస్తుంది
}

int main() {
    int arr[] = {64, 25, 12, 22, 11};
    int n = sizeof(arr) / sizeof(arr[0]);

    printf("సార్టింగ్ చేయడానికి ముందు: ");
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");

    // qsort కు compareAscending ఫంక్షన్ పాయింటర్‌ను కాల్‌బ్యాక్‌గా పాస్ చేస్తున్నాం
    qsort(arr, n, sizeof(int), compareAscending);

    printf("సార్టింగ్ చేసిన తర్వాత   : ");
    for (int i = 0; i < n; i++) printf("%d ", arr[i]);
    printf("\n");

    return 0;
}
10డైనమిక్ 2D అర్రేస్ పరిచయం (Double Pointers ద్వారా)

సాధారణ 2D అర్రేలలో రోస్ మరియు కాలమ్స్ సంఖ్య కంపైల్-టైమ్‌లోనే స్థిరంగా ఉండాలి. కానీ డబుల్ పాయింటర్లు (int **matrix) మరియు malloc() ఉపయోగించి యూజర్ కోరిన సైజుతో రన్‌టైమ్‌లో ఫ్లెక్సిబుల్ 2D గ్రిడ్‌లను నిర్మించవచ్చు. దీనిని మనం Phase 05 లో డైనమిక్ మెమరీతో కలిపి మరింత లోతుగా నేర్చుకుంటాం.

11సమగ్ర రియల్ వరల్డ్ ప్రాజెక్ట్ — ప్లగ్-అండ్-ప్లే మ్యాథ్ ఇంజిన్ (Callbacks)

ఇప్పటివరకు నేర్చుకున్న ఫంక్షన్ పాయింటర్లు మరియు కాల్‌బ్యాక్స్ ఉపయోగించి ఒక ఎక్స్‌టెన్సిబుల్ ప్లగ్-అండ్-ప్లే మ్యాథమెటికల్ కంప్యూట్ ఇంజిన్ (Compute Engine) నిర్మిద్దాం. కోర్ ఇంజిన్ కోడ్‌ను మార్చకుండానే భవిష్యత్తులో కొత్త ఆపరేషన్లను జోడించవచ్చు:

C — Extensible Plug-and-Play Compute Engine
#include <stdio.h>

// ఫంక్షన్ పాయింటర్ టైప్‌డెఫ్ (Function Signature)
typedef double (*MathOperation)(double, double);

// ఆపరేషన్లు
double opAdd(double a, double b) { return a + b; }
double opSubtract(double a, double b) { return a - b; }
double opPower(double base, double exp) {
    double res = 1.0;
    for (int i = 0; i < (int)exp; i++) res *= base;
    return res;
}

// కోర్ ఎగ్జిక్యూటర్ ఇంజిన్ (కాల్‌బ్యాక్ ద్వారా రన్ అవుతుంది)
void executeOperation(const char *opName, MathOperation func, double x, double y) {
    double result = func(x, y); // ఫంక్షన్ పాయింటర్ ద్వారా ఇన్వొకేషన్!
    printf("⚙️ [%-10s] ఇన్పుట్: (%.1f, %.1f) ➔ ఫలితం = %.2f\n", opName, x, y, result);
}

int main() {
    printf("====================================================\n");
    printf("   మనా ప్లగ్-అండ్-ప్లే కంప్యూట్ ఇంజిన్ (2026 Engine)\n");
    printf("====================================================\n");

    // రన్‌టైమ్‌లో వేర్వేరు ఫంక్షన్లను కాల్‌బ్యాక్‌లుగా పంపుతున్నాం
    executeOperation("కూడిక", opAdd, 45.0, 15.0);
    executeOperation("తీసివేత", opSubtract, 100.0, 35.0);
    executeOperation("ఘాతం (Power)", opPower, 2.0, 8.0);

    printf("====================================================\n");
    return 0;
}
12సాధారణంగా బిగినర్స్ చేసే టాప్ 5 అడ్వాన్స్‌డ్ తప్పులు
1. int *a[] vs int (*a)[] బ్రాకెట్స్ మిస్సింగ్:
బ్రాకెట్లు లేకపోతే అది అర్రే ఆఫ్ పాయింటర్స్ అవుతుంది; బ్రాకెట్లు ఉంటే పాయింటర్ టు యాన్ అర్రే అవుతుంది. ఇది భారీ కంపైలేషన్ ఎర్రర్లను ఇస్తుంది.
2. డబుల్ పాయింటర్‌ను సరైన ఇనిషియలైజేషన్ లేకుండా డీరిఫరెన్స్ చేయడం:
int **p; **p = 5; అని రాస్తే లెవల్ 1 అడ్రస్ ఖాళీగా ఉండి సెగ్మెంటేషన్ ఫాల్ట్ వస్తుంది.
3. అర్రే కాన్స్టాంట్ పాయింటర్‌కు రీ-అసైన్ చేయడానికి ప్రయత్నించడం:
arr = ptr; అని రాయకూడదు. అర్రే బేస్ అడ్రస్ స్థిరమైనది (Non-modifiable lvalue).
4. ఫంక్షన్ పాయింటర్ సిగ్నేచర్ మిస్‌మ్యాచ్:
ఫంక్షన్ పాయింటర్ (int, int) ఆశిస్తుంటే (double, double) ఫంక్షన్‌ను అసైన్ చేస్తే కంపైలర్ టైప్ ఎర్రర్ ఇస్తుంది.
5. argc చెక్ చేయకుండా argv[1] ని యాక్సెస్ చేయడం:
యూజర్ ఆర్గుమెంట్స్ ఇవ్వకుండా ప్రోగ్రామ్ రన్ చేస్తే argv[1] నల్ అవుతుంది. if (argc > 1) తనిఖీ తప్పనిసరి.
13స్వీయ మూల్యాంకన క్విజ్ & మీరే స్వయంగా Try చేయండి!

ఈ పాఠంలోని లోతైన అంశాలను క్రింది 5 ప్రాక్టికల్ ప్రశ్నల ద్వారా పరీక్షించుకోండి:

❓ ప్రశ్న 1: C లో arr[i] మరియు *(arr + i) మధ్య వ్యత్యాసం ఏమిటి?
సమాధానం: రెండింటి మధ్య ఎటువంటి వ్యత్యాసం లేదు! arr[i] అనేది కంపైలర్ కోసం *(arr + i) గా రూపాంతరం చెందే సింటాక్స్ షుగర్ మాత్రమే.
❓ ప్రశ్న 2: డబుల్ పాయింటర్ (**ptr) యొక్క పరిమాణం (sizeof) ఎంత ఉంటుంది?
సమాధానం: 64-బిట్ ఆర్కిటెక్చర్‌లో ఇది కూడా కేవలం ఒక మెమరీ అడ్రస్ మాత్రమే కాబట్టి సరిగ్గా 8 బైట్లు మాత్రమే ఉంటుంది.
❓ ప్రశ్న 3: కమాండ్ లైన్ లో argc కనీస విలువ ఎల్లప్పుడూ ఎంత ఉంటుంది?
సమాధానం: ఎల్లప్పుడూ కనీసం 1 ఉంటుంది. ఎందుకంటే ప్రోగ్రామ్ యొక్క స్వంత పేరు (ఉదా: ./app) మొదటి ఆర్గుమెంట్ argv[0] గా పరిగణించబడుతుంది.
❓ ప్రశ్న 4: ఫంక్షన్ పాయింటర్లు (Function Pointers) RAM లో ఏ సెగ్మెంట్‌లోని చిరునామాను పట్టుకుంటాయి?
సమాధానం: అవి Code Segment (Text Segment) లోని ఎగ్జిక్యూటబుల్ మెషీన్ ఇన్‌స్ట్రక్షన్ల మెమరీ అడ్రస్‌ను పట్టుకుంటాయి.
❓ ప్రశ్న 5: 'int *a[10]' మరియు 'int (*b)[10]' ల మధ్య ప్రధాన వ్యత్యాసం ఏమిటి?
సమాధానం: a అనేది 10 పాయింటర్ల అర్రే (Array of Pointers); b అనేది 10 ఎలిమెంట్స్ గల అర్రేను పాయింట్ చేసే ఒకే ఒక్క పాయింటర్ (Pointer to Array).
🚀 ప్లగ్-అండ్-ప్లే మ్యాథ్ ఇంజిన్‌ను మన ఆన్‌లైన్ C కంపైలర్‌లో రన్ చేయండి!

పైన వివరించిన ఫంక్షన్ పాయింటర్ కాల్‌బ్యాక్స్ ఇంజిన్ మరియు డబుల్ పాయింటర్ కోడ్‌లను మన ఆన్‌లైన్ C కంపైలర్‌లో ఓపెన్ చేసి స్వయంగా రన్ చేయండి. కొత్త మ్యాథ్ ఫంక్షన్లను (ఉదా: మాడ్యులో, వర్గమూలం) ప్లగ్-ఇన్ చేసి టెస్ట్ చేయండి!

👉 Our Compiler లో C Compiler try చేయండి

📌 Phase 04 ముగింపు సారాంశం (Phase 04 Wrap-Up):

  • డేటా స్ట్రక్చర్స్ & మెమరీ విజయం: అర్రేలు, 2D Matrices (Ch 13), స్ట్రింగ్స్, నల్ టెర్మినేటర్ (Ch 14), పాయింటర్లు, అరిథ్‌మెటిక్ (Ch 15), మరియు డబుల్ పాయింటర్లు & ఫంక్షన్ పాయింటర్లు (Ch 16) లపై సంపూర్ణ పట్టు సాధించారు!
  • arr[i]: అంతర్గతంగా *(arr + i) అనే పాయింటర్ అరిథ్‌మెటిక్.
  • డబుల్ పాయింటర్: మరొక పాయింటర్ యొక్క మెమరీ అడ్రస్‌ను నిల్వ చేసే లెవల్-2 పాయింటర్.
  • ఫంక్షన్ పాయింటర్లు: రన్‌టైమ్‌లో ఫంక్షన్లను డైనమిక్‌గా మార్చడానికి మరియు కాల్‌బ్యాక్ ఆర్కిటెక్చర్ నిర్మించడానికి ఉపయోగపడతాయి.
తర్వాతి అధ్యాయంలో (Phase 05 — స్ట్రక్చర్స్, డైనమిక్ మెమరీ & ఫైల్స్): విభిన్న డేటా టైప్స్‌ను కలిపి కొత్త యూజర్-డిఫైన్డ్ డేటా టైప్స్ సృష్టించే స్ట్రక్చర్స్ (Structures), యూనియన్స్ (Unions) మరియు మెమరీ ప్యాడింగ్ (Structure Padding) గురించి అత్యంత లోతుగా నేర్చుకుందాం!
← Prev: 15. పాయింటర్లు: బేసిక్స్ Next: 17. స్ట్రక్చర్స్ & యూనియన్స్ →
OC
Written by Our Compiler Technical Editorial Team
Reviewed for accuracy & tested on GCC 13+ / Clang 17 runtime · 2026 Academic Edition