C ఫంక్షన్స్, ఫార్వర్డ్ డిక్లరేషన్ & కాల్ స్టాక్ ఆర్కిటెక్చర్
ఒక పెద్ద 5-స్టార్ రెస్టారెంట్ యొక్క వంటగదిని (Kitchen) ఊహించుకోండి. అక్కడ హెడ్ చెఫ్ (Head Chef) ఉన్నారు. ఆ హెడ్ చెఫ్ స్వయంగా మార్కెట్కు వెళ్లి కూరగాయలు తేవడం, ఉల్లిపాయలు కోయడం, పిండి కలపడం, పొయ్యి వెలిగించడం, బిరియానీ వండడం, ప్లేట్లలో సర్వ్ చేయడం, చివరకు బిల్లు వేయడం... అన్నీ ఒక్కరే చేస్తే ఏమవుతుంది? గంటల తరబడి సమయం వృధా అవుతుంది, కిచెన్ అస్తవ్యస్తమవుతుంది, ఆర్డర్లు ఆలస్యమై రెస్టారెంట్ మూతపడుతుంది!
కానీ నిజమైన వంటగదిలో బాధ్యతల విభజన (Division of Labor / Modularity) ఉంటుంది: కూరగాయలు కోయడానికి ఒక సహాయకుడు (chopVegetables()), మసాలాలు రుబ్బడానికి మరొకరు (grindSpices()), సూప్ తయారు చేయడానికి ప్రత్యేక నిపుణుడు ఉంటారు. హెడ్ చెఫ్ (మన ప్రోగ్రామ్లోని main() ఫంక్షన్ లాంటి వారు) కేవలం వారికి ఆదేశాలు ఇస్తూ, ఫలితాలను పర్యవేక్షిస్తారు. దీనివలన పని వేగవంతంగా, శుభ్రంగా మరియు ఎటువంటి గందరగోళం లేకుండా పూర్తవుతుంది.
కంప్యూటర్ ప్రోగ్రామింగ్లో కూడా వేలాది లైన్ల కోడ్ను ఒకే main() లో గుప్పించకూడదు. ప్రోగ్రామ్ను చిన్న చిన్న స్వతంత్ర భాగాలుగా విభజించే కళనే ఫంక్షన్స్ (Functions / Modular Architecture) అంటారు. ఈ తొమ్మిదవ అధ్యాయంతో మనం Phase 03 (ఫంక్షన్స్, స్కోప్ & రికర్షన్) లోకి అడుగుపెడుతున్నాం. ఇందులో ఫంక్షన్ ప్రొటోటైప్స్, RAM లోని CPU కాల్ స్టాక్ (Call Stack), స్టాక్ ఫ్రేమ్స్ (Activation Records) మరియు పూర్తి స్థాయి శాలరీ & ట్యాక్స్ మేనేజ్మెంట్ ఇంజిన్ను నిర్మిద్దాం!
సిస్టమ్స్ ప్రోగ్రామింగ్లో ఫంక్షన్స్ అనేవి కోడ్ రీయూజబిలిటీకి మరియు ఆర్కిటెక్చర్ క్లీన్నెస్కు పునాది రాళ్ళు. ఈ అధ్యాయంలో కవర్ చేయబడే లోతైన అంశాలు:
- మోడ్యులర్ ప్రోగ్రామింగ్ & DRY సూత్రం: "Don't Repeat Yourself" ఫిలాసఫీ మరియు కోడ్ రీయూజబిలిటీ.
- ఫంక్షన్ అనాటమీ (Anatomy of a Function): Return Type, Function Name, Parameter List, మరియు Body.
- ఫంక్షన్ డిక్లరేషన్ (Function Prototype / Forward Declaration): C కంపైలర్కు ఇచ్చే ముందస్తు అగ్రిమెంట్.
- ప్రొటోటైప్ ఎందుకు తప్పనిసరి? C సింగిల్-పాస్ కంపైలేషన్ (Single-Pass Compilation) మరియు
implicit declarationఎర్రర్స్. - పారామీటర్స్ vs ఆర్గుమెంట్స్: Formal Parameters మరియు Actual Arguments మధ్య సాంకేతిక వ్యత్యాసం.
- void ఫంక్షన్స్ & return స్టేట్మెంట్: విలువను వెనక్కి పంపే మరియు పంపని పద్ధతులు.
- హార్డ్వేర్ లెవల్ CPU కాల్ స్టాక్ (RAM Call Stack): స్టాక్ మెమరీ, పుష్ (Push) మరియు పాప్ (Pop) ఆపరేషన్లు.
- స్టాక్ ఫ్రేమ్స్ (Activation Records): లోకల్ వేరియబుల్స్, పారామీటర్స్ మరియు రిటర్న్ అడ్రస్ (Return Address) నిల్వ అయ్యే విధానం.
- LIFO (Last-In, First-Out) ఎగ్జిక్యూషన్ ఆర్డర్: ఫంక్షన్ చైన్డ్ కాల్స్ మెమరీలో ఎలా నడుస్తాయి?
- సమగ్ర వర్గీకరణ పట్టిక: 4 రకాల ఫంక్షన్ల కాంబినేషన్స్ (With/Without Return Type, With/Without Arguments).
- సమగ్ర రియల్ వరల్డ్ ప్రాజెక్ట్: మోడ్యులర్ ఎంప్లాయ్ శాలరీ, అలవెన్సులు & ఇన్కమ్ ట్యాక్స్ కాలిక్యులేటర్.
- బిగినర్స్ చేసే టాప్ 5 తప్పులు: ప్రొటోటైప్ సెమికోలన్ మిస్సింగ్, లోకల్ వేరియబుల్ అడ్రస్ రిటర్న్ చేయడం వంటి ప్రమాదాలు.
- స్వీయ మూల్యాంకన క్విజ్: 5 లోతైన ఇంటర్వ్యూ & గేట్ ఎగ్జామ్ ప్రశ్నలు.
సాఫ్ట్వేర్ ఇంజనీరింగ్లో అత్యంత పవిత్రమైన నియమం: DRY — Don't Repeat Yourself. ఒకే లాజిక్ను మీ ప్రోగ్రామ్లో పదేపదే కాపీ-పేస్ట్ చేయకూడదు. కాపీ-పేస్ట్ చేసిన కోడ్లో ఏదైనా బగ్ వస్తే, దాన్ని ఫిక్స్ చేయడానికి మీరు కోడ్లోని పది చోట్ల మార్చాల్సి ఉంటుంది!
ఫంక్షన్స్ అందించే 4 అద్భుత ప్రయోజనాలు:
- రీయూజబిలిటీ (Code Reusability): ఒకసారి ఫంక్షన్ రాసి, దానిని మీ ప్రాజెక్ట్లో వందల సార్లు పిలుచుకోవచ్చు.
- మెయింటెనెన్స్ (Easy Maintenance): లాజిక్లో మార్పు చేయాల్సి వస్తే కేవలం ఆ ఒక్క ఫంక్షన్ను సరిచేస్తే చాలు.
- రీడబిలిటీ & అబ్స్ట్రాక్షన్ (Readability):
main()ఫంక్షన్ చదవడానికి ఒక పుస్తకం ఇండెక్స్లా సులభంగా అర్థమవుతుంది. - టీమ్వర్క్ (Team Collaboration): వేర్వేరు డెవలపర్లు వేర్వేరు ఫంక్షన్లపై ఒకే సమయంలో స్వతంత్రంగా పనిచేయవచ్చు.
C లాంగ్వేజ్లో ఒక ఫంక్షన్ను విజయవంతంగా ఉపయోగించాలంటే 3 కీలక దశలు (Three Sacred Steps) ఉంటాయి:
1. డిక్లరేషన్ (Prototype)
ఫంక్షన్ పేరు, రిటర్న్ టైప్, పారామీటర్ల గురించి కంపైలర్కు ఇచ్చే ముందస్తు నోటీస్ (ముగింపులో సెమికోలన్ ; ఉంటుంది).
2. ఫంక్షన్ డెఫినిషన్ (Definition)
ఆ ఫంక్షన్ చేయవలసిన అసలైన పనిని కర్లీ బ్రేసెస్ { ... } లోపల రాసే అసలైన బాడీ కోడ్.
3. ఫంక్షన్ కాల్ (Function Call)
main() లో లేదా వేరే ఫంక్షన్లో ఆ ఫంక్షన్ పేరును పిలిచి ఆర్గుమెంట్లను పాస్ చేసి ఎగ్జిక్యూట్ చేయడం.
ఫంక్షన్ సింటాక్స్ అనాటమీ:
// ఫంక్షన్ బాడీ (స్టేట్మెంట్స్)
return ఫలితం;
}
#include <stdio.h>
// 1. Function Prototype (ముందస్తు డిక్లరేషన్)
int calculateSum(int a, int b);
int main() {
int num1 = 25, num2 = 15;
// 2. Function Call (పిలుపు)
int total = calculateSum(num1, num2);
printf("రెండు సంఖ్యల మొత్తం: %d\n", total);
return 0;
}
// 3. Function Definition (అసలైన బాడీ)
int calculateSum(int a, int b) {
int result = a + b;
return result; // కాలింగ్ ఫంక్షన్కు విలువను రిటర్న్ చేయి
}
చాలా మంది కొత్త ప్రోగ్రామర్లకు ఒక ప్రశ్న వస్తుంది: "ఫంక్షన్ బాడీని కింద రాసి, పైన మళ్లీ ఫంక్షన్ ప్రొటోటైప్ (Function Prototype) లైన్ ఎందుకు రాయాలి? ఇది అనవసరమైన డబుల్ వర్క్ కాదా?"
ది C సింగిల్-పాస్ కంపైలర్ ఆర్కిటెక్చర్ (Single-Pass Compilation):
C కంపైలర్ (GCC / Clang) మీ సోర్స్ కోడ్ను పైనుండి కిందికి (Top-to-Bottom) ఒకేసారి మాత్రమే చదువుతుంది (Single Pass). మీరు main() లో ఒక ఫంక్షన్ను పిలిచే సమయానికి, ఆ ఫంక్షన్ అసలైన బాడీ కింద ఉంటే — కంపైలర్కు ఆ ఫంక్షన్ అసలు ఉందో లేదో తెలియదు! దాని రిటర్న్ టైప్ ఏమిటో, ఎన్ని పారామీటర్లు తీసుకోవాలో తెలియక కంపైలర్ కంగారుపడుతుంది. అందుకే ఫైల్ మొదట్లోనే Function Prototype (Forward Declaration) పెట్టి కంపైలర్తో అగ్రిమెంట్ కుదుర్చుకుంటాం: "ఓ కంపైలర్! కింద ఈ పేరుతో, ఇన్ని పారామీటర్లతో ఒక ఫంక్షన్ రాస్తున్నాను, గుర్తుపెట్టుకో!" అని తెలియజేస్తాం.
main() కింద ఫంక్షన్ రాస్తే, పాత C89 కంపైలర్ ఆ ఫంక్షన్ రిటర్న్ టైప్ డీఫాల్ట్గా int అనుకుంటుంది. ఒకవేళ అది float లేదా double రిటర్న్ చేస్తే డేటా పూర్తిగా కరప్ట్ అవుతుంది! ఆధునిక C99/C11 లో GCC warning: implicit declaration of function లేదా కంపైలేషన్ ఎర్రర్ను విసురుతుంది!
ఇంటర్వ్యూలలో తరచుగా అడిగే ప్రాథమిక సాంకేతిక వ్యత్యాసం ఇది:
| అంశం | ఆర్గుమెంట్స్ (Actual Arguments) | పారామీటర్స్ (Formal Parameters) |
|---|---|---|
| నిర్వచనం | ఫంక్షన్ను కాల్ చేసేటప్పుడు పాస్ చేసే అసలైన విలువలు. | ఫంక్షన్ హెడర్లో ఆ విలువలను అందుకోవడానికి డిక్లేర్ చేసిన వేరియబుల్స్. |
| ఎక్కడ ఉంటాయి? | కాలింగ్ ఫంక్షన్ లోపల (ఉదా: add(10, 20); లేదా add(x, y);) |
ఫంక్షన్ డెఫినిషన్ హెడర్లో (ఉదా: int add(int a, int b)) |
| మెమరీ కేటాయింపు | కాలింగ్ ఫంక్షన్ యొక్క స్టాక్ ఫ్రేమ్లో ఉంటాయి. | కాల్డ్ ఫంక్షన్ యొక్క స్టాక్ ఫ్రేమ్లో కొత్త మెమరీ స్థానాలు కేటాయించబడతాయి. |
| విలువ మార్పిడి | C లో డీఫాల్ట్గా ఆర్గుమెంట్ల కాపీ మాత్రమే పారామీటర్లకు వెళ్తుంది (Call by Value). | పారామీటర్ను మారిస్తే ఒరిజినల్ ఆర్గుమెంట్ విలువ మారదు! |
ఒక ఫంక్షన్ పని పూర్తి చేసిన తర్వాత తిరిగి ఏ విలువనూ ఇవ్వాల్సిన అవసరం లేనప్పుడు (ఉదాహరణకు కేవలం స్క్రీన్ పై మెసేజ్ ప్రింట్ చేయడం లేదా సౌండ్ ప్లే చేయడం), దాని రిటర్న్ టైప్ను void గా డిక్లేర్ చేస్తారు.
Early Return టెక్నిక్ (గార్డ్ క్లాజ్):
void ఫంక్షన్లలో కూడా return; స్టేట్మెంట్ను ఒంటరిగా వాడవచ్చు! ఏదైనా తప్పుడు కండిషన్ ఎదురైనప్పుడు ఫంక్షన్ను మధ్యలోనే ఆపేసి బయటకు రావడానికి (Early Exit Guard Clause) ఇది ఉపయోగపడుతుంది:
#include <stdio.h>
void printUserCard(int age, const char* name) {
if (age < 18) {
printf("⛔ యాక్సెస్ నిరాకరించబడింది! %s మైనర్ (వయస్సు %d).\n", name, age);
return; // ఫంక్షన్ ఇక్కడితో ఆగిపోతుంది! కింద ఉన్న కోడ్ రన్ కాదు.
}
printf("===============================\n");
printf(" వెల్కమ్ క్లబ్ మెంబర్: %s\n", name);
printf(" ధృవీకరించబడిన వయస్సు: %d\n", age);
printf("===============================\n");
}
int main() {
printUserCard(16, "రాహుల్");
printUserCard(24, "సురేష్");
return 0;
}
ఒక C ప్రోగ్రామ్ రన్ అవుతున్నప్పుడు కంప్యూటర్ RAM లో ఏమి జరుగుతుంది? ఇది ప్రతి ప్రొఫెషనల్ సాఫ్ట్వేర్ ఇంజనీర్ తెలుసుకోవాల్సిన అత్యంత కీలకమైన అంశం. ప్రోగ్రామ్ మెమరీలో ఒక ప్రత్యేక విభాగం ఉంటుంది, దానినే కాల్ స్టాక్ (Call Stack) అంటారు.
ప్లేట్ల దొంతర ఎనాలజీ (Stack of Plates):
ఒక వివాహ భోజనశాలలో ప్లేట్లను ఒకదానిపై ఒకటి అమర్చిన దొంతరను (Stack of plates) గమనించండి. కొత్త ప్లేట్ను ఎల్లప్పుడూ పైనే పెడతారు (PUSH). ఎవరైనా ప్లేట్ తీసుకోవాలంటే అందరికంటే పైన ఉన్న ప్లేట్ను మాత్రమే ముందుగా తీయగలరు (POP). దీనినే కంప్యూటర్ సైన్స్లో LIFO — Last-In, First-Out అంటారు. చివరగా వచ్చినది ముందుగా బయటకు వెళ్తుంది!
స్టాక్ ఫ్రేమ్ (Stack Frame / Activation Record) లోపల ఏముంటుంది?
ప్రోగ్రామ్లో ఒక ఫంక్షన్ కాల్ జరిగిన ప్రతిసారీ, RAM కాల్ స్టాక్ పై ఆ ఫంక్షన్ కోసం ఒక బ్లాక్ మెమరీ కేటాయించబడుతుంది. దీనిని స్టాక్ ఫ్రేమ్ (Stack Frame) అంటారు. ఇందులో మూడు ముఖ్యమైన విషయాలుంటాయి:
- ఫార్మల్ పారామీటర్లు (Parameters): కాలర్ పంపిన విలువల కాపీలు.
- లోకల్ వేరియబుల్స్ (Local Variables): ఆ ఫంక్షన్ లోపల డిక్లేర్ చేయబడిన వేరియబుల్స్.
- రిటర్న్ అడ్రస్ (Return Address): ఫంక్షన్ పూర్తయిన తర్వాత CPU తిరిగి
main()లో ఏ లైన్ వద్దకు వెళ్లి పని ప్రారంభించాలో తెలిపే మెమరీ అడ్రస్!
క్రింది కోడ్లో main() ఫంక్షన్ calculateTotal() ను పిలుస్తుంది, అది మళ్లీ applyTax() ను పిలుస్తుంది. ఈ చైన్డ్ కాల్స్ మెమరీలో ఎలా స్టాక్ అవుతాయో స్టెప్-బై-స్టెప్ చూద్దాం:
#include <stdio.h>
double applyTax(double amount) {
double tax = amount * 0.18; // 18% GST
printf(" [3. applyTax Frame] పన్ను లెక్కించబడింది: రూ. %.2f\n", tax);
return amount + tax;
}
double calculateTotal(int qty, double price) {
printf(" [2. calculateTotal Frame] బేస్ మొత్తం లెక్కించబడుతోంది...\n");
double baseTotal = qty * price;
double finalWithTax = applyTax(baseTotal); // చైన్డ్ కాల్!
return finalWithTax;
}
int main() {
printf("[1. main Frame] బిల్లింగ్ ప్రారంభమైంది...\n");
double bill = calculateTotal(3, 500.0);
printf("[1. main Frame] తుది బిల్లు: రూ. %.2f\n", bill);
return 0;
}
RAM కాల్ స్టాక్ యొక్క PUSH & POP దశలు:
[దశ 2]: calculateTotal() కాల్ అయింది ➔ స్టాక్ పై [calculateTotal Frame] PUSH అయింది.
[దశ 3]: applyTax() కాల్ అయింది ➔ స్టాక్ పై [applyTax Frame] PUSH అయింది (ఇప్పుడు టాప్ లో ఉంది).
[దశ 4]: applyTax() ముగిసింది ➔ [applyTax Frame] POP అయి మెమరీ డిలీట్ అయింది!
[దశ 5]: calculateTotal() ముగిసింది ➔ [calculateTotal Frame] POP అయింది!
[దశ 6]: main() ముగిసింది ➔ [main Frame] POP అయి ప్రోగ్రామ్ మెమరీ క్లీన్ అయింది!
ఆర్గుమెంట్లు మరియు రిటర్న్ టైప్స్ ఆధారంగా C లో ఫంక్షన్లను నాలుగు ప్రాథమిక వర్గాలుగా విభజించవచ్చు:
| రకం / కేటగిరీ | ఆర్గుమెంట్స్ ఉన్నాయా? | రిటర్న్ టైప్ ఉందా? | వాడుక సందర్భం (Real Use-Case) |
|---|---|---|---|
| 1. No Arg, No Return | లేదు (void) |
లేదు (void) |
కన్సోల్ హెడర్ బ్యానర్లు, హెల్ప్ మెనూలు ప్రింట్ చేయడానికి (ఉదా: printWelcomeBanner()). |
| 2. With Arg, No Return | ఉన్నాయి (int, float...) |
లేదు (void) |
డేటాను ఫార్మాట్ చేసి డిస్ప్లే చేయడానికి లేదా లాగ్లోకి రాయడానికి (ఉదా: logError(code)). |
| 3. No Arg, With Return | లేదు (void) |
ఉంది (int, double...) |
యూజర్ నుండి ఇన్పుట్ చదవడం లేదా సిస్టమ్ కరెంట్ సమయం తీసుకోవడం (ఉదా: getSecurityPin()). |
| 4. With Arg, With Return | ఉన్నాయి | ఉంది | గణిత సమీకరణాలు, బ్యాంకింగ్ లావాదేవీల లెక్కింపులు (ఉదా: calculateEMI(P, R, N)). |
ఫంక్షన్ కాల్ జరిగిన ప్రతిసారీ CPU స్టాక్ ఫ్రేమ్ను నిర్మించడం, రిటర్న్ అడ్రస్ను సేవ్ చేయడం, జంప్ చేయడం వంటి ప్రక్రియల్లో కొంత సమయం (Function Call Overhead) ఖర్చవుతుంది. చాలా చిన్న ఫంక్షన్లు (ఉదాహరణకు రెండు సంఖ్యలలో గరిష్ట విలువను కనుగొనే 1 లైన్ ఫంక్షన్) లక్షలాది సార్లు లూప్లో రన్ అవుతుంటే, ఈ ఓవర్హెడ్ పర్ఫార్మెన్స్ను తగ్గిస్తుంది.
ఆధునిక C99 స్టాండర్డ్ లో దీనిని అధిగమించడానికి inline కీవర్డ్ ప్రవేశపెట్టబడింది. ఫంక్షన్ ముందు inline అని పెడితే, కంపైలర్ ఫంక్షన్ కాల్ జంప్ చేయకుండా, ఆ కోడ్ను నేరుగా కాల్ చేసిన ప్రదేశంలోనే అతికిస్తుంది (Inline Expansion)!
#include <stdio.h>
// Inline Function: ఫంక్షన్ కాల్ ఓవర్హెడ్ లేకుండా మెరుపు వేగంతో రన్ అవుతుంది
static inline int findMax(int a, int b) {
return (a > b) ? a : b;
}
int main() {
int x = 45, y = 82;
int maximum = findMax(x, y); // కంపైలర్ దీన్ని (x > y) ? x : y గా మారుస్తుంది
printf("గరిష్ట సంఖ్య: %d\n", maximum);
return 0;
}
ఇప్పటివరకు నేర్చుకున్న ఫంక్షన్ ప్రొటోటైప్స్, మోడ్యులర్ డిజైన్, మల్టిపుల్ ఆర్గ్యుమెంట్స్ మరియు రిటర్న్ టైప్స్ను కలిపి ఒక కార్పొరేట్ కంపెనీ ఉద్యోగుల జీతం & పన్ను గణన వ్యవస్థను (Payroll & Tax Engine) నిర్మిద్దాం. ఇందులో ప్రతి పనికి ఒక ప్రత్యేక ఫంక్షన్ ఉంటుంది:
#include <stdio.h>
// ============================================
// 1. ఫంక్షన్ ప్రొటోటైప్స్ (Forward Declarations)
// ============================================
void printCompanyHeader(void);
double calculateHRA(double basicSalary);
double calculateDA(double basicSalary);
double calculateGrossSalary(double basic, double hra, double da);
double calculateIncomeTax(double annualGross);
void generatePaySlip(const char* empName, double basic);
int main() {
printCompanyHeader();
// ఇద్దరు ఉద్యోగులకు పే-స్లిప్స్ జనరేట్ చేద్దాం
generatePaySlip("అర్జున్ వర్మ", 65000.0);
generatePaySlip("స్నిగ్ధ శర్మ", 95000.0);
return 0;
}
// ============================================
// 2. మోడ్యులర్ ఫంక్షన్ డెఫినిషన్స్
// ============================================
void printCompanyHeader(void) {
printf("====================================================\n");
printf(" మన టెక్నాలజీస్ ప్రైవేట్ లిమిటెడ్ (Mana Payroll 2026)\n");
printf("====================================================\n");
}
// HRA: బేసిక్ పే లో 40% ఇంటి అద్దె భత్యం
double calculateHRA(double basicSalary) {
return basicSalary * 0.40;
}
// DA: బేసిక్ పే లో 20% కరువు భత్యం
double calculateDA(double basicSalary) {
return basicSalary * 0.20;
}
// స్థూల జీతం (Gross Salary)
double calculateGrossSalary(double basic, double hra, double da) {
return basic + hra + da;
}
// వార్షిక ఆదాయ పన్ను స్లాబ్లు
double calculateIncomeTax(double annualGross) {
if (annualGross <= 500000.0) {
return 0.0; // రూ. 5 లక్షల వరకు 0% పన్ను
} else if (annualGross <= 1000000.0) {
return (annualGross - 500000.0) * 0.10; // 10% స్లాబ్
} else {
return (500000.0 * 0.10) + ((annualGross - 1000000.0) * 0.20); // 20% స్లాబ్
}
}
// పూర్తి శాలరీ స్లిప్ ముద్రించే కో-ఆర్డినేటర్ ఫంక్షన్
void generatePaySlip(const char* empName, double basic) {
double hra = calculateHRA(basic);
double da = calculateDA(basic);
double monthlyGross = calculateGrossSalary(basic, hra, da);
double annualGross = monthlyGross * 12.0;
double annualTax = calculateIncomeTax(annualGross);
double monthlyTax = annualTax / 12.0;
double netMonthlyTakeHome = monthlyGross - monthlyTax;
printf("\n[పే-స్లిప్] ఉద్యోగి పేరు: %s\n", empName);
printf("----------------------------------------------------\n");
printf(" బేసిక్ పే (Basic Salary) : రూ. %10.2f\n", basic);
printf(" ఇంటి భత్యం (HRA - 40%%) : రూ. %10.2f\n", hra);
printf(" కరువు భత్యం (DA - 20%%) : రూ. %10.2f\n", da);
printf(" నెలవారీ స్థూల జీతం (Gross): రూ. %10.2f\n", monthlyGross);
printf(" వార్షిక ఆదాయం (Annual) : రూ. %10.2f\n", annualGross);
printf(" నెలవారీ TDS పన్ను మినహాయింపు: రూ. %10.2f\n", monthlyTax);
printf("----------------------------------------------------\n");
printf(" 👉 చేతికి అందే నికర జీతం (Net Pay): రూ. %10.2f\n", netMonthlyTakeHome);
printf("====================================================\n");
}
int add(int a, int b) అని రాసి సెమికోలన్ పెట్టకపోతే, కంపైలర్ దాని కింద ఉన్న కోడ్ను ఫంక్షన్ బాడీ అనుకుని భారీ ఎర్రర్స్ ఇస్తుంది.
int add(int a, int b); { return a + b; } అని రాస్తే బాడీ ఫంక్షన్ నుండి విడిపోయి స్వతంత్ర బ్లాక్ అయిపోతుంది!
ఫంక్షన్ ముగియగానే దాని స్టాక్ ఫ్రేమ్ మెమరీ నుండి నాశనం అవుతుంది. లోపల ఉన్న లోకల్ వేరియబుల్ పాయింటర్ను రిటర్న్ చేస్తే మెమరీ క్రాష్ అవుతుంది!
int రిటర్న్ టైప్ పెట్టి లోపల return రాయకపోతే గార్బేజ్ వాల్యూ రిటర్న్ అవుతుంది (Undefined Behavior).
ఫంక్షన్
(int, double) ఆశిస్తుంటే మీరు (double, int) పాస్ చేస్తే డేటా ట్రంకేట్ లేదా టైప్ కాస్టింగ్ సమస్యలు వస్తాయి.
ఈ పాఠంలోని లోతైన అంశాలను క్రింది 5 ప్రాక్టికల్ ప్రశ్నల ద్వారా పరీక్షించుకోండి:
❓ ప్రశ్న 1: C లో Function Prototype ను ఎందుకు ఉపయోగిస్తారు?
main() లో ఫంక్షన్ను పిలవడానికి ముందే దాని పేరు, రిటర్న్ టైప్ మరియు పారామీటర్ల సంఖ్యను కంపైలర్కు ధృవీకరించడానికి (Forward Declaration) ప్రొటోటైప్ తప్పనిసరి.
❓ ప్రశ్న 2: RAM కాల్ స్టాక్ (Call Stack) ఏ ఆర్డర్ ప్రకారం పనిచేస్తుంది?
❓ ప్రశ్న 3: ఒక స్టాక్ ఫ్రేమ్ (Activation Record) లోపల ఏ వివరాలు ఉంటాయి?
❓ ప్రశ్న 4: void ఫంక్షన్ లోపల return స్టేట్మెంట్ రాయవచ్చా?
return; అని మాత్రమే రాయాలి. కండిషన్ విఫలమైనప్పుడు ఫంక్షన్ను మధ్యలోనే ఆపేయడానికి (Early Exit) దీనిని ఉపయోగిస్తారు.
❓ ప్రశ్న 5: inline ఫంక్షన్ యొక్క ముఖ్య ప్రయోజనం ఏమిటి?
పైన వివరించిన పేరోల్ & ట్యాక్స్ సిస్టమ్ కోడ్ను మన ఆన్లైన్ C కంపైలర్లో ఓపెన్ చేసి స్వయంగా రన్ చేయండి. కొత్త భత్యాలు (ఉదా: మెడికల్ అలవెన్స్, బోనస్) లెక్కించే కొత్త ఫంక్షన్లను జోడించి టెస్ట్ చేయండి!
📌 అధ్యాయ సారాంశం (Quick Summary):
- ఫంక్షన్స్: సంక్లిష్ట సమస్యలను చిన్న చిన్న పనులుగా విభజించే మోడ్యులర్ ఇంజిన్లు.
- DRY సూత్రం: కోడ్ డూప్లికేషన్ను అరికట్టి రీయూజబిలిటీని పెంచుతుంది.
- ప్రొటోటైప్: C సింగిల్-పాస్ కంపైలర్కు ఇచ్చే ముందస్తు కాంట్రాక్ట్.
- కాల్ స్టాక్: RAM లో ఫంక్షన్ ఫ్రేమ్లను LIFO పద్ధతిలో నిర్వహించే మెమరీ నిర్మాణం.
- స్టాక్ ఫ్రేమ్: పారామీటర్లు, లోకల్ వేరియబుల్స్ మరియు రిటర్న్ అడ్రస్ల సమాహారం.