short int ή short (συνήθως 2 bytes)int (συνήθως 4, σπανιότερα 2 ή 8, bytes, ανάλογα με το μέγεθος λέξης του επεξεργαστή)long int ή long (συνήθως 4, μερικές φορές 8, bytes)long long int ή long long (συνήθως 8 bytes)char (1 byte)float (απλής ακρίβειας, συνήθως 4 bytes)double (διπλής ακρίβειας, συνήθως 8 bytes)long double (εκτεταμένης ακρίβειας, συνήθως 16 bytes)int):237, -12345, 22431L (το L συμβολίζει ότι επιθυμούμε να θεωρηθεί η σταθερά τύπου long), 0224 (ο οκταδικός αριθμός 224), 0x1C (ο δεκαεξαδικός αριθμός 1C)'A' (ο ASCII κωδικός του χαρακτήρα A, δηλαδή 65)'\n' (ο ASCII κωδικός για την αλλαγή γραμμής)'\t' (ο ASCII κωδικός για τον στηλογνώμονα, tab)'0' (ο ASCII κωδικός του χαρακτήρα 0, δηλαδή 48)'\0' (ο χαρακτήρας με ASCII κωδικό 0)'\145' (ο χαρακτήρας με ASCII κωδικό τον οκταδικό αριθμό 145)'\xA2' (ο χαρακτήρας με ASCII κωδικό τον δεκαεξαδικό αριθμό A2)double):23.78, -1.24e-14 (δηλαδή \(-1.24 \cdot 10^{-14}\))", για παράδειγμα "Hello world\n". Πρόκειται, ουσιαστικά, για έναν πίνακα χαρακτήρων, χωρίς τα ", με τελευταίο στοιχείο του πίνακα το '\0' (παρόλο που δεν σημειώνεται στη διατύπωση της συμβολοσειράς μέσα στα ").Με μία δήλωση ενημερώνεται ο μεταγλωττιστής για την πρόθεσή μας να χρησιμοποιήσουμε στο πρόγραμμά μας κάποια ή κάποιες μεταβλητές συγκεκριμένου τύπου, τις οποίες μπορούμε να αρχικοποιήσουμε και με σταθερές του τύπου αυτού, αν θέλουμε, και αντιστοιχεί σ’ αυτές κατάλληλες θέσεις μνήμης. Παραδείγματα:
int i, j, k;
char ch;
float x, y = 2.34;
long count, cost;
double pi = 3.14159;
_.if, float, for, κλπ.) για ονόματα μεταβλητών._, γιατί τέτοια ονόματα χρησιμοποιούνται για τις μεταβλητές από τις βιβλιοθήκες και ενδέχεται να δημιουργηθεί πρόβλημα.#define, για να τις διαχειριστεί ο προεπεξεργαστής.unsigned, που δηλώνει ότι οι αριθμοί που φυλάσσονται στη μεταβλητή πρέπει να ερμηνευθούν σαν θετικοί (ή μηδέν).signed, ή δεν υπάρχει κανένας, το περιεχόμενο της μεταβλητής θεωρείται ακέραιος με πρόσημο (θετικό ή αρνητικό).Παραδείγματα:
signed char ch;
unsigned char uch;
short i;
unsigned long int k;
ch φυλάσσονται αριθμοί από \(-128\) (\(=-2^7\)) έως \(127\) (\(=2^7-1\)), ενώ στην uch από \(0\) έως \(255\) (\(=2^8-1\))i φυλάσσονται αριθμοί από \(-32768\) (\(=-2^{15}\)) έως \(32767\) (\(=2^{15}-1\)), ενώ στην k από \(0\) έως \(4294967295\) (\(=2^{32}-1\))Σε δήλωση μεταβλητής, με ταυτόχρονη αρχικοποίηση, μπορεί να εφαρμοσθεί ο προσδιοριστής const, που εξασφαλίζει ότι η τιμή της μεταβλητής δεν θα αλλάξει. Παράδειγμα:
const double e = 2.71828;
;).= ⟨παράσταση⟩= και την ανάθεση της τιμής αυτής στη μεταβλητή στο αριστερό μέλος του =.+, -, *, / και % (υπόλοιπο διαίρεσης).int και double δίνει αποτέλεσμα double.i είναι ακέραιου τύπου, η έκφραση (double) i αναφέρεται στην τιμή της i σαν πραγματικό αριθμό διπλής ακρίβειας.Δύο πολύ χρήσιμοι τελεστές είναι οι τελεστές μοναδιαίας αύξησης (++) και μείωσης (--). Όταν εφαρμόζονται επάνω σε μία μεταβλητή, είτε στα αριστερά είτε στα δεξιά της, έχουν σαν αποτέλεσμα την αύξηση, ή μείωση αντίστοιχα, της τιμής της μεταβλητής κατά 1. Για παράδειγμα, η ακολουθία εντολών
x = 2;
y = 9;
x++;
--y;
++x;
x--;
y--;
++y;
θα έχει σαν τελικό αποτέλεσμα οι μεταβλητές x και y να έχουν τελικά σαν τιμές τις 3 και 8, αντίστοιχα. Στο παράδειγμα αυτό, δεν είχε κάποια σημασία η τοποθέτηση των τελεστών αριστερά ή δεξιά της μεταβλητής.
Παράδειγμα:
x = 4;
y = 7;
z = ++y;
y = z - (x++);
z = x - (--y);
Τι τιμή θα έχουν οι μεταβλητές x, y και z μετά από αυτές τις εντολές; 2
>, <, >=, <=, == (ίσο) και != (διάφορο).&& (ΚΑΙ), || (Ή) και ! (ΟΧΙ).Ουσιαστικά, οι συνθήκες δεν είναι κάτι διαφορετικό από τις παραστάσεις. Μία αληθής συνθήκη είναι μία παράσταση με τιμή ίση με 1, ενώ μία ψευδής συνθήκη θεωρείται ότι έχει τιμή 0. Αντίστοιχα, μία παράσταση με τιμή διάφορη του 0 μπορεί να παίξει τον ρόλο μίας αληθούς συνθήκης, ενώ αν η τιμή της είναι 0, είναι ισοδύναμη με μία ψευδή συνθήκη. Για παράδειγμα, γράφοντας
if (myvar != 0) { ........
είναι ακριβώς το ίδιο με το
if (myvar) { ........
&: ΚΑΙ|: Ή^: αποκλειστικό Ή<<: ολίσθηση αριστερά>>: ολίσθηση δεξιά~: συμπλήρωμα ως προς έναΠαράδειγμα:
unsigned char x;
x = 178;
x = x & 074;
x = x | 0xD6;
x = x ^ 104;
x = x >> 3;
x = x << 2;
x = ~x;
Ποια θα είναι η τελική τιμή της μεταβλητής x; 3
Κάθε διμελής τελεστής (+, -, *, /, %, &, |, ^, <<, >>) μπορεί να χρησιμοποιηθεί και με ένα σύντομο τρόπο σε μία εντολή αντικατάστασης, ως εξής:
⟨μεταβλητή⟩ ⟨τελεστής⟩= ⟨παράσταση⟩
Αυτή η εντολή είναι ισοδύναμη με την:
⟨μεταβλητή⟩ = ⟨μεταβλητή⟩ ⟨τελεστής⟩ ⟨παράσταση⟩
Για παράδειγμα, η εντολή
sum += x;
είναι ισοδύναμη με την
sum = sum + x;
Μερικές φορές, είναι χρήσιμες και οι παραστάσεις υπό συνθήκη, σαν την
⟨συνθήκη⟩ ? ⟨παράσταση⟩\(_1\) : ⟨παράσταση⟩\(_2\)
Η τιμή αυτής της παράστασης είναι αυτή που έχει η ⟨παράσταση⟩\(_1\), αν η ⟨συνθήκη⟩ είναι αληθής (δηλαδή, αν έχει τιμή διάφορη του 0, θεωρώντας την ως παράσταση και αυτή), ή αυτή που έχει η ⟨παράσταση⟩\(_2\), αν η ⟨συνθήκη⟩ είναι ψευδής (δηλαδή ίση με 0). Παράδειγμα:
z = (a > b) ? a : b;
Με την εντολή αυτή, η τιμή της z θα γίνει ίση με τη μεγαλύτερη τιμή από τις a και b.
Φυσικά, πρέπει να αποφεύγονται υπερβολές. Στην εντολή
x = y + z*w;
δεν χρειάζονται παρενθέσεις αν θέλουμε η παράσταση στο δεξιό μέλος να είναι η y + (z*w) (λόγω της αναμενόμενης μεγαλύτερης προτεραιότητας του * έναντι του +, που όντως ισχύει). Βέβαια, η παράσταση (y+z) * w είναι διαφορετική από την προηγούμενη.
Κάθε εντολή αντικατάστασης μπορεί να θεωρηθεί και σαν παράσταση με τιμή αυτήν την τιμής της παράστασης που αναθέτουμε στη μεταβλητή. Έτσι, ο κορμός του προγράμματος capitalize.c
ch = getchar();
while (ch != EOF) {
if (ch >= 'a' && ch <= 'z')
ch = ch - ('a'-'A');
putchar(ch);
ch = getchar();
}
θα μπορούσε να γραφεί πιο συμπυκνωμένα ως εξής:
while ((ch = getchar()) != EOF) {
if (ch >= 'a' && ch <= 'z')
ch = ch - ('a'-'A');
putchar(ch);
}
Προσέξτε, στη συμπυκνωμένη εκδοχή, τις παρενθέσεις γύρω από την εντολή αντικατάστασης ch = getchar(). Είναι απαραίτητες γιατί ο τελεστής != έχει μεγαλύτερη προτεραιότητα από τον =. Αν δεν τις βάζαμε, τι θα γινόταν;
/* File: gcdlcm.c */
#include <stdio.h>
#include <stdlib.h> /* Header file for srand and rand functions */
#include <time.h> /* Header file for time function */
#define COMPUTATIONS 8 /* Pairs of numbers to compute GCD and LCM */
#define MAXNUMB 1000 /* Maximum number */
int main()
{ int i, m, n, large, small, gcd, rem;
long curtime, lcm;
curtime = time(NULL); /* Current time (in seconds since 1/1/1970) */
printf("Current time is %ld\n\n", curtime);
srand((unsigned int) curtime); /* Seed for random number generator */
for (i=0 ; i < COMPUTATIONS ; i++) {
m = rand() % MAXNUMB + 1; /* Select 1st number in [1,MAXNUMB] */
n = rand() % MAXNUMB + 1; /* Select 2nd number in [1,MAXNUMB] */
if (m > n) { /* Which number is larger? */
large = m; /* Larger is m */
small = n;
}
else {
large = n; /* Larger is n */
small = m;
}
while (small) { /* While small is not 0 */
rem = large % small; /* Find remainder of large/small */
large = small; /* New large is previous small */
small = rem; /* New small is remainder found */
}
gcd = large; /* GCD of m and n equals to final value of large */
lcm = (m*n)/gcd; /* LCM(m,n) * GCD(m,n) = m * n */
printf("GCD(%3d,%3d) = %2d LCM(%3d,%3d) = %6ld\n",
m, n, gcd, m, n, lcm);
}
}
% gcc -o gcdlcm gcdlcm.c
% ./gcdlcm
Current time is 1130666309
GCD(855,405) = 45 LCM(855,405) = 7695
GCD(125,139) = 1 LCM(125,139) = 17375
GCD(996,467) = 1 LCM(996,467) = 465132
GCD(191,890) = 1 LCM(191,890) = 169990
GCD(548,612) = 4 LCM(548,612) = 83844
GCD(378,531) = 9 LCM(378,531) = 22302
GCD(837,127) = 1 LCM(837,127) = 106299
GCD(938,656) = 2 LCM(938,656) = 307664
%
rand, η οποία κάθε φορά που καλείται επιστρέφει ένα (ψευδο)τυχαίο αριθμό. Η αρχικοποίηση της γεννήτριας (ψευδο)τυχαίων αριθμών γίνεται καλώντας τη συνάρτηση srand, δίνοντάς της σαν παράμετρο την τρέχουσα χρονική στιγμή, όπως αυτή επιστρέφεται από τη συνάρτηση time (η παράμετρος NULL που δίνουμε στην time θα συζητηθεί στο μέλλον).