main. Είναι η συνάρτηση από την οποία θα ξεκινήσει η εκτέλεση του προγράμματος.(⟨τυπικές παράμετροι⟩)int.void, τον “ κενό” τύπο. Ακόμα και αν έχουμε ορίσει μία συνάρτηση να επιστρέφει κάποιο τύπο, όχι void, δεν είναι τελικά υποχρεωτικό να το κάνει, και αν το κάνει, δεν είναι υποχρεωτικό για την καλούσα συνάρτηση να χρησιμοποιήσει την επιστρεφόμενη τιμή.return ⟨παράσταση⟩. Υπολογίζεται η τιμή που έχει η ⟨παράσταση⟩, επιστρέφεται και η συνάρτηση τερματίζει. Με μία απλή εντολή return τερματίζει χωρίς να επιστραφεί κάποια τιμή.main μπορεί να ορίζεται
main αν το πρόγραμμα εκτελέσθηκε με ορίσματα στη γραμμή εντολής και, αν ναι, με ποια. Περισσότερα, γι’ αυτό το θέμα, αργότερα.Η main επιστρέφει τιμή τύπου int, η οποία είναι διαθέσιμη στο περιβάλλον του λειτουργικού συστήματος από το οποίο εκτελέσθηκε το πρόγραμμα. Τελικά, ο απολύτως σωστός τρόπος για να ορίσουμε τη συνάρτηση main χωρίς τυπικές παραμέτρους, τον οποίο θα υιοθετήσουμε από εδώ και πέρα, είναι ο εξής (το void υποδηλώνει την έλλειψη τυπικών παραμέτρων):
int main(void)
main, με την εντολή return (τυπικά το 0, σε περίπτωση επιτυχούς τερματισμού του προγράμματος)./* File: powers.c */
#include <stdio.h>
#define MAXM 4 /* Maximum base of powers to compute */
#define MAXN 6 /* Maximum exponent */
int power(int, int); /* Prototype of power */
int main(void)
{ int m, n, p;
for (m=2 ; m <= MAXM ; m++) /* Start from base 2 */
for (n=2 ; n <= MAXN ; n++) { /* Start from exponent 2 */
p = power(m,n); /* Call power function */
printf("%d^%d = %d\n", m, n, p);
}
return 0;
}
int power(int base, int n)
{ int p;
for (p=1 ; n > 0 ; n--) /* base^n equals to */
p *= base; /* base * base * ... * base (n times) */
return p; /* Return result */
}
% gcc -o powers powers.c
% ./powers
2^2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
3^2 = 9
3^3 = 27
3^4 = 81
3^5 = 243
3^6 = 729
4^2 = 16
4^3 = 64
4^4 = 256
4^5 = 1024
4^6 = 4096
%
/* File: factorial.c */
#include <stdio.h>
#define MAXN 12 /* Compute factorials up to MAXN */
int factorial(int n) /* No prototype needed */
{ int f;
for (f=1 ; n > 0 ; n--) /* Initialize factorial to 1 */
f *= n; /* Multiply into factorial n, n-1, ..., 1 */
return f; /* Return result */
}
int main(void)
{ int n; /* For all n from 1 to MAXN */
for (n=1 ; n <= MAXN ; n++) /* Call function and */
printf("%2d! = %d\n", n, factorial(n)); /* print result */
return 0;
}
% gcc -o factorial factorial.c
% ./factorial
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
%
Αν ένα πρόγραμμα είναι διασπασμένο σε πολλά αρχεία και θέλουμε να έχουμε μία εξωτερική μεταβλητή που να είναι ορατή από τις συναρτήσεις σε όλα τα αρχεία, τότε πρέπει σε ακριβώς ένα αρχείο να δώσουμε τον ορισμό της μεταβλητής, για παράδειγμα
int sp;
ενώ σε καθένα από τα άλλα αρχεία πρέπει να κάνουμε μία δήλωση της μεταβλητής, προτάσσοντας τον προσδιοριστή extern, για παράδειγμα
extern int sp;
Ουσιαστικά, ο μεταγλωττιστής δεσμεύει μνήμη για μία εξωτερική μεταβλητή όταν δει τον ορισμό της (γι’ αυτό πρέπει να υπάρχει αυτός ακριβώς μία φορά) και ενημερώνεται για τον τύπο μίας μεταβλητής όταν δει μία δήλωσή της με extern (θυμηθείτε ότι αν ένα πρόγραμμα είναι διασπασμένο σε πολλά αρχεία, τα αρχεία αυτά μεταγλωττίζονται ξεχωριστά).
Αν θέλουμε η εμβέλεια μίας εξωτερικής μεταβλητής να είναι μόνο το αρχείο στο οποίο ορίζεται και να μην συγχέεται με κάποια εξωτερική μεταβλητή με το ίδιο όνομα, αλλά σε άλλο αρχείο, μπορούμε να προτάξουμε του ορισμού της τον προσδιοριστή static, για παράδειγμα
static double sum;
static μπορεί να εφαρμοσθεί και σε μεταβλητές που ορίζονται μέσα σε συνάρτηση, όμως με άλλη σημασία. Η εμβέλεια μίας τοπικής μεταβλητής που έχει ορισθεί σαν static μέσα σε συνάρτηση, είναι η συνάρτηση αυτή, αλλά η μεταβλητή δεν είναι αυτόματη. Διατηρείται, όπως και η τιμή της, και μετά τον τερματισμό της συνάρτησης. Σε νέα κλήση της συνάρτησης, η μεταβλητή έχει την τιμή που πήρε μετά την προηγούμενη κλήση.while). Αν υπάρχουν πολλαπλοί ορισμοί για το ίδιο όνομα μεταβλητής σε διάφορα μπλοκ, μέσα σε καθένα απ’ αυτά ισχύει ο ορισμός που έγινε σ’ αυτό, ή, αν δεν υπάρχει, αυτός που έγινε στο αμέσως πιο εξωτερικό του, ή, αν δεν υπάρχει, στο πιο εξωτερικό, κ.ο.κ.Παράδειγμα:
int count;
float y;
double myfun(int y)
{ int i;
..............
while (......) {
int i, j;
..........
for (.......) {
int count;
..........
}
}
}
Ποιες μεταβλητές ισχύουν πού;
static μέσα σε συναρτήσεις). Ο χώρος αυτός είναι των στατικών (καθολικών) δεδομένων και είναι εκ των προτέρων γνωστός και δεσμευμένος μέσα στο εκτελέσιμο πρόγραμμα και αντιστοιχεί στο χώρο που θα καταληφθεί στη μνήμη όταν φορτωθεί το πρόγραμμα για να εκτελεσθεί./* File: recfact.c */
#include <stdio.h>
#define MAXN 12 /* Compute factorials up to MAXN */
int recfact(int); /* Prototype of recfact */
int main(void)
{ int n; /* For all n from 0 to MAXN */
for (n=0 ; n <= MAXN ; n++) /* Call function and */
printf("%2d! = %d\n", n, recfact(n)); /* print result */
return 0;
}
int recfact(int n)
{ if (!n) /* If n == 0 */
return 1; /* 0! = 1 */
else
return n*recfact(n-1); /* n! = n * (n-1)! */
}
% gcc -o recfact recfact.c
% ./recfact
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
%
/* File: convdecbin.c */
#include <stdio.h>
#define ERROR -1 /* Return value for illegal character */
int getinteger(int base)
{ char ch; /* No need to declare ch as int - no EOF handling */
int val = 0; /* Initialize return value */
while ((ch = getchar()) != '\n') /* Read up to new line */
if (ch >= '0' && ch <= '0'+base-1) /* Legal character? */
val = base*val + (ch-'0'); /* Update return value */
else
return ERROR; /* Illegal character read */
return val; /* Everything OK - Return value of number read */
}
int main(void)
{ int n, digs[32], ind = 0;
printf("Please, give a binary number: ");
n = getinteger(2); /* Read binary number */
if (n == ERROR) {
printf("Sorry, illegal character\n"); return 1; }
else /* Print decimal value of number */
printf("Decimal equivalent is: %d\n", n);
printf("Please, give a decimal number: ");
n = getinteger(10); /* Read decimal number */
if (n == ERROR) {
printf("Sorry, illegal character\n"); return 1; }
else { /* Convert number to binary digits */
while (n) { /* Repeat until number equals to 0 */
digs[ind++] = n%2; /* New digit is number mod 2 */
n = n/2; /* New number is number/2 */
}
printf("Binary equivalent is: ");
while (ind--) /* Print digits in reverse order */
printf("%d", digs[ind]);
printf("\n");
}
return 0;
}
% gcc -o convdecbin convdecbin.c
% ./convdecbin
Please, give a binary number: 1000100101111010001001001
Decimal equivalent is: 18019401
Please, give a decimal number: 18019401
Binary equivalent is: 1000100101111010001001001
% ./convdecbin
Please, give a binary number: 10011101
Decimal equivalent is: 157
Please, give a decimal number: 65535
Binary equivalent is: 1111111111111111
%
getinteger είναι γενικής χρησιμότητας, τι ακριβώς θα έπρεπε να βάλουμε σ’ ένα πηγαίο αρχείο getinteger.c και τι σ’ ένα αρχείο επικεφαλίδας getinteger.h, ώστε να χρησιμοποιούμε τη συνάρτηση αυτή και σε άλλα προγράμματα;