Moät soá kieán thöùc cô sôû veà laäp trình baèng ngoân ngöõ C

Phaâàn tröôùc | Muïc luïc | Phaâàn sau

XIV. Phaïm vi cuûa bieán vaø lôùp boä nhôù

Noäi dung:

Khi laäp trình chuùng ta coù theå gaëp nhöõng vaán ñeà veà söï truøng laëp caùc bieán trong nhöõng ñoaïn chöông trình khaùc nhau. Ñeå bieát caùch xaùc ñònh phaïm vò hoaït ñoäng cuûa chuùng, ta tìm hieåu:

 

Trong C, ta coù theå khai baùo moät bieán vaø chæ ñònh phaïm vi tieáp caän noù baèng caùch xaùc ñònh phaïm vi cuûa noù. Caùc bieán vôùi phaïm vi cuïc boä chæ coù theå tieáp caän ñöoïc trong khoái maø noù ñöôïc khai baùo. Ta phaân bieät caùc phaïm vi sau:

Phaïm vi khoái

Trong C, moät khoái ñöôïc giôùi haïn bôûi ngoaëc {}. Bieán khai baùo trong khoái ñoù coù phaïm vi khoái, nghóa laø noù chæ hoaït ñoäng trong khoái ñoù maø thoâi. Phaïm vi naøy coøn goïi laø cuïc boä, vaø bieán ñöoïc goïi laø bieán cuïc boä.

Ví duï:

int main()
{
   int i;   /* block scope */
   .
   .
   .
   return 0;
}

hoaëc ví duï trong moät khoái loàng vaøo nhau:

Ví duï:

 
1:  /* Scopes in nested block */
2:  #include <stdio.h>
3:
4:  main()
5:  {
6:     int i = 32;   /* block scope 1*/
7:
8:     printf("Within the outer block: i=%d\n", i);
9:
10:    {    /* the beginning of the inner block */
11:      int i, j;    /* block scope 2, int i hides the outer int i*/
12:
13:      printf("Within the inner block:\n");
14:      for (i=0, j=10; i<=10; i++, j--)
15:          printf("i=%2d, j=%2d\n", i, j);
16:    }   /* the end of the inner block */
17:    printf("Within the outer block:  i=%d\n", i);
18:    return 0;
19: }
 
Keát quaû:
 
Within the outer block: i=32
Within the inner block:
i= 0, j=10
i= 1, j= 9
i= 2, j= 8
i= 3, j= 7
i= 4, j= 6
i= 5, j= 5
i= 6, j= 4
i= 7, j= 3
i= 8, j= 2
i= 9, j= 1
i=10, j= 0
Within the outer block: i=32

Phaïm vi haøm

Phaïmvi haøm chæ ñònh moät bieán coù phaïm vi hoaät ñoäng tö ñaàu ñeán cuoái moät haøm (khoâng nhaàm laãn vôùi bieán coù phaïm vi khoái). Trong C, chæ coù nhaõn (label) ñ/v leânh goto laø coù phaïm vi haøm.

int main()
{
   int i;   /* block scope */
   .
   .
   .
   start:   /* A goto label has function scope */
   .
   .
   .
   goto  start;  /* the goto statement */
   .
   .
   .
   return 0;
}

Phaïm vi chöông trình

Bieán coù phaïm vi chöông trình khi noù ñöôïc khai baùo beân ngoaøi caùc haøm. Ví duï:

int x = 0;        /* program scope */
float y = 0.0;    /* program scope */
int main()
{
   int i;   /* block scope */
   .
   .
   .
   return 0;
}

Bieán naøy coøn ñöôïc goïi laø bieán toaøn cuïc.

Ví duï:

1:  /* Program scope vs block scope */
2:  #include <stdio.h>
3:
4:  int x = 1234;         /* program scope */
5:  double y = 1.234567;  /* program scope */
6:
7:  void function_1()
8:  {
9:     printf("From function_1:\n  x=%d, y=%f\n", x, y);
10: }
11:
12: main()
13: {
14:    int x = 4321;   /* block scope 1*/
15:
16:    function_1();
17:    printf("Within the main block:\n  x=%d, y=%f\n", x, y);
18:    /* a nested block */
19:    {
20:       double y = 7.654321;  /* block scope 2 */
21:       function_1();
22:       printf("Within the nested block:\n  x=%d, y=%f\n", x, y);
23:    }
24:    return 0;
25: }

Keát quaû:
 
From function_1:
  x=1234, y=1.234567
Within the main block:
  x=4321, y=1.234567
From function_1:
  x=1234, y=1.234567
Within the nested block:
  x=4321, y=7.654321
 

TIP

Bieán toaøn cuïc maëc duø ñöôïc nhìn thaáy ôû moïi haøm trong toaøn chöông trình, nhöng khoâng neân khai baùo söû duïng nhieàu neáu khoâng caàn thieát, vì noù seõ gaây trôû ngaïi cho quaù trình doø tìm loãi khi debug chöông trình.

 

Caùc ñaëc taû lôùp boä nhôù

Trong C, lôùp boä nhôù cuûa moät bieán laø ñeà caäp ñeán phaïm vi hieäu duïng cuûa bieán veà khoâng gian laãn thôøi gian. Chính caùc phaïm vi treân ñaëc tröng cho tính khoâng gian, coøn veà tính thôøi gian (töùc laø hoaït ñoäng cuûa bieán trong suoát thôøi gian chöông trình chaïy) seõ ñöoïc chæ ñònh bôûi caùc ñaëc taû sau:

Ñaëc taû auto

Bieåu thò tính taïm thôøi cuûa boä nhôù daønh cho bieán. Boä nhôù ñoù seõ töï ñoäng troáng (free) sau khi chöông trình ra khoûi moät khoái naøo ñoù. Tuy nhieân töø khoùa naøy ít duøng vì haàu heát caùc bieán cuïc boä maëc ñònh laø auto.

Ñaëc taû static

Khi moät bieán ñöôïc khai baùo static, boä nhôù daønh cho bieán ñoù seõ ñöôïc xaùc ñònh vónh vieãn daønh cho bieán. Cho neân duø ra vaøo caùc khoái khaùc nhau, giaù trò trong ñoù seõ khoâng bò xoùa hoaëïc thay ñoåi, neáu khoâng phaûi laø leänh chöông trình.

Ví duï:

int main()
{
   int i;         /* block scope and temporary duration */
   static int j;  /* block scope and permanent duration */
   .
   .
   return 0;
}

Ví duï:

1:  /* Using the static specifier */
2:  #include <stdio.h>
3:  /* the add_two function */
4:  int add_two(int x, int y)
5:  {
6:     static int counter = 1;
7:
8:     printf("This is the function call of %d,\n", counter++);
9:     return (x + y);
10: }
11: /* the main function */
12: main()
13: {
14:    int i, j;
15:
16:    for (i=0, j=5; i<5; i++, j--)
17:       printf("the addition of %d and %d is %d.\n\n",
18:              i, j, add_two(i, j));
19:    return 0;
20: }
 
Keát quaû:
 
This is the function call of 1,
the addition of 0 and 5 is 5.
 
This is the function call of 2,
the addition of 1 and 4 is 5.
 
This is the function call of 3,
the addition of 2 and 3 is 5.
 
This is the function call of 4,
the addition of 3 and 2 is 5.
 
This is the function call of 5,
the addition of 4 and 1 is 5.

Phaïm vi teäp

Trong C, bieán ñöôïc khai baùo laø toaøn cuïc vaø static ñöôïc goïi laø coù phaïm vi teäp.

int x = 0;             /* program scope */
static int y = 0;      /* file scope */
static float z = 0.0;  /* file scope */
int main()
{
   int i;   /* block scope */
   .
   .
   .
   return 0;
}

Ñaëc taû register

Register (thanh ghi) laø moät daïng boä nhôù trong CPU thöïc hieän caùc chöùc naêng ñaëc bieät trong tính toaùn vaø löu tröõ döõ lieäu taïm thôøi trong quaù trình xöû lyù. Vì naèm trong CPU neân döõ lieäu löu tröõ treân register seõ ñöôïc tieáp caän nhanh hôn. Cho neân, trong quaù trình laäp trình, coù moät soá thao taùc caàn xöû lyù nhanh, ta coù theå söû duïng thanh ghi. Vaø ngoân ngöõ C taïo ñieàu kieän cho ta coù theå khai baùo bieán treân thanh ghi baèng ñaëc taû register.

 
int main()
{
   /* block scope with the register specifier */
   register int i;
   . . .
   for (i=0; i<MAX_NUM; i++){
      /* some statements */
   }
   . . .
   return 0;
}

Ñaëc taû extern

Vôùi moät bieán toaøn cuïc ôû chöông trình A, ñoâi khi ta caàn söû duïng trong chöông trình B. Ngoân ngöõ C cho pheùp khai baùo daïng bieán nhö vaäy baèng ñaëc taû extern.

int x = 0;         /* a global variable */
extern int y;      /* an allusion to a global variable y */
int main()
{
   extern int z;  /* an allusion to a global variable z */
   int i;         /* a local variable */
   .
   .
   .
   return 0;
}

Töø khoùa const

Neá ta khai baùo moät bieán vôùi const , giaù trò cuûa noù seõ khoâng thay ñoåi trong suoát chöông trình.

const double circle_ratio = 3.141593;
const char str[] = "A string constant";
char const *ptr_str = "A string constant";

Töø khoùa volatile

Coù taùc duïng löu yù boä bieân dòch, laø bieán khai baùo vôùi volatile coù theå bò thay ñoåi moät caùch naøo ñoù ngoaøi chöông trình (ñoàng hoà maùy nhaûy töï ñoäng, boä nhôù thieát bò caûnh baùo…), vaø boä bieân dòch seõ khoâng kieåm tra traïng thaùi boä nhôù daønh cho bieán ñoù trong quaù trình thao taùc thöïc hieän chöông trình.

void read_keyboard()
{
   volatile char keyboard_ch;  /* a volatile variable */
   .
   .
   .
}

Baøi taäp

  1. Phaân loïai caùc bieán xuaát hieän trong ñoaïn chöông trình sau?
int x = 0;
float y = 0.0;
int myFunction()
{
   int i, j;
   float y;
   . . .
   {
      int x, y;
      . . .
   }
   . . .
}
  1. Haõy nhaän daïng caùc lôùp boä nhôù cuûa caùc khai baùo trong ñoaïn chöông trình sau:
int i = 0;
static int x;
extern float y;
int myFunction()
{
   int i, j;
   extern float z;
   register long s;
   static int index;
   const char str[] = "Warning message.";
   . . .
}
  1. Chaïy chöông trình sau ñaây, xem caùi gì xuaát hieän leân maøn aûnh vaø giaûi thích taïi sao?
#include <stdio.h>
int main()
{
   int i;
 
   for (i=0; i<5; i++){
      int x = 0;
      static int y = 0;
      printf("x=%d, y=%d\n", x++, y++);
   }
   return 0;
}
 
Phaâàn tröôùc | Muïc luïc | Phaâàn sau