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

XVI. Söû duïng con troû

Noäi dung:

 

Pheùp tính soá hoïc con troû

Trong C, ta coù theå chuyeån vò trí con troû baèng caùch coäng hoaëc tröø soá nguyeân töø vò trí cuûa con troû. Format chung:

pointer_name + n

Vôùi n laø soá integer (+) hoaêc (-); pointer_name ñöôïc ñònh nghóa bôûi

data_type_specifier *pointer_name;

Pheùp toaùn soá hoïc treân seõ dòch chuyeån con troû ñeán vò trí môùi öùng vôùi

pointer_name + n * sizeof(data_type_specifier)

Ví duï:

1:  /* Pointer arithmetic */
2:  #include <stdio.h>
3:
4:  main()
5:  {
6:     char *ptr_ch;
7:     int *ptr_int;
8:     double *ptr_db;
9:     /* char pointer ptr_ch */
10:    printf("Current position of ptr_ch: 0x%p\n", ptr_ch);
11:    printf("The position after ptr_ch + 1: 0x%p\n", ptr_ch + 1);
12:    printf("The position after ptr_ch + 2: 0x%p\n", ptr_ch + 2);
13:    printf("The position after ptr_ch - 1: 0x%p\n", ptr_ch - 1);

14:    printf("The position after ptr_ch - 2: 0x%p\n", ptr_ch - 2);
15:    /* int pointer ptr_int */
16:    printf("Current position of ptr_int: 0x%p\n", ptr_int);
17:    printf("The position after ptr_int + 1: 0x%p\n", ptr_int + 1);
18:    printf("The position after ptr_int + 2: 0x%p\n", ptr_int + 2);
19:    printf("The position after ptr_int - 1: 0x%p\n", ptr_int - 1);
20:    printf("The position after ptr_int - 2: 0x%p\n", ptr_int - 2);
21:    /* double pointer ptr_ch */
22:    printf("Current position of ptr_db: 0x%p\n", ptr_db);
23:    printf("The position after ptr_db + 1: 0x%p\n", ptr_db + 1);
24:    printf("The position after ptr_db + 2: 0x%p\n", ptr_db + 2);
25:    printf("The position after ptr_db - 1: 0x%p\n", ptr_db - 1);
26:    printf("The position after ptr_db - 2: 0x%p\n", ptr_db - 2);
27:
28:    return 0;
29: }
 
Ñaùp soá:
 
Current position of ptr_ch: 0x000B
The position after ptr_ch + 1: 0x000C
The position after ptr_ch + 2: 0x000D
The position after ptr_ch - 1: 0x000A
The position after ptr_ch - 2: 0x0009
Current position of ptr_int: 0x028B
The position after ptr_int + 1: 0x028D
The position after ptr_int + 2: 0x028F
The position after ptr_int - 1: 0x0289
The position after ptr_int - 2: 0x0287
Current position of ptr_db: 0x0128
The position after ptr_db + 1: 0x0130
The position after ptr_db + 2: 0x0138
The position after ptr_db - 1: 0x0120
The position after ptr_db - 2: 0x0118
 

Caûnh baùo

Con troû laø moät coâng cuï laäp trình raát maïnh, nhöng neáu söû duïng khoâng thaønh thuïc vaø caån thaän raát deã sinh ra nhöõng loãi chöông trình raát khoù tìm. Ví duï: ta thöôøng gaùn noäi dung bieán cho moät pointer thay vì ñòa chæ cuûa noù, nhöng phaàn lôùn caùc compiler C thoâng baùo loãi naøy.

Moät ví duï khaùc: söû duïng pointer khoâng xaùc ñònh tröôùc.

        int x, ptr_int;
        x = 8;
        *ptr_int = x;

Ptr_int khoâng ñöôïc xaùc ñònh tröôùc, neáu ta gaùn noäi dung 8 cho noù, coù theå noù seõ cheùp choàng leân moät vò trí naøo ñoù chöa bieát trong boä nhôù laøm sai döõ lieäu cuûa moät bieán naøo löu vaøo vò trí ñoù tröôùc ñaây.

Cho neân, nhaát thieát phaûi khai baùo tröôùc, chaúng haïn:

int x, ptr_int;
x = 8;
ptr_int = &x;   /* initialize the pointer */

PheÙp hieäu con troû

ptr_str2 - ptr_str1

Pheùp hieäu treân cho ta offset ñòa chæ öùng vôùi ñòa chæ 2 con troû ptr_str1 vaø ptr_str2. Taát nhieân chæ coù caùc con troû coù cuøng kieåu döõ lieäu môùi thöïc hieän ñöôïc.

Ví duï:

1:  /* Pointer subtraction */
2:  #include <stdio.h>
3:
4:  main()
5:  {
6:     int *ptr_int1, *ptr_int2;
7:
8:     printf("The position of ptr_int1: 0x%p\n", ptr_int1);
9:     ptr_int2 = ptr_int1 + 5;
10:    printf("The position of ptr_int2 = ptr_int1 + 5: 0x%p\n", ptr_int2);
11:    printf("The subtraction of ptr_int2 - ptr_int1: %d\n", ptr_int2 -
               Âptr_int1);
12:    ptr_int2 = ptr_int1 - 5;
13:    printf("The position of ptr_int2 = ptr_int1 - 5: 0x%p\n", ptr_int2);
14:    printf("The subtraction of ptr_int2 - ptr_int1: %d\n", ptr_int2 -
       Âptr_int1);
15:
16:    return 0;
17: }
 
Ñaùp soá:
 
The position of ptr_int1: 0x0128
The position of ptr_int2 = ptr_int1 + 5: 0x0132
The subtraction of ptr_int2 - ptr_int1: 5
The position of ptr_int2 = ptr_int1 - 5: 0x011E
The subtraction of ptr_int2 - ptr_int1: -5

Con troû vaø maûng

Bôûi vì teân maûng khoâng coù chæ soá ñöôïc hieåu nhö laø con troû chæ ñeán phaàn töû ñaàu tieân cuûa maûng, ta coù theå tieáp caän ñeán maûng thoâng qua con troû ñoù ñeå truy caäp phaàn töû ñaàu tieân vaø caùc phaàn töû tieáp theo thoâng qua pheùp tính soá hoïc con troû.

ptr_array = array;

vaø array[n] töông ñöông vôùi

 
*(ptr_array + n)

Ví duï:

1:  /* Accessing arrays via pointers */
2:  #include <stdio.h>
3:
4:  main()
5:  {
6:     char str[] = "It's a string!";
7:     char *ptr_str;
8:     int list[] = {1, 2, 3, 4, 5};
9:     int *ptr_int;
10:
11:    /* access char array */
12:    ptr_str = str;
13:    printf("Before the change, str contains: %s\n", str);
14:    printf("Before the change, str[5] contains: %c\n", str[5]);
15:    *(ptr_str + 5) = `A';
16:    printf("After the change, str[5] contains: %c\n", str[5]);
17:    printf("After the change, str contains: %s\n", str);
18:    /* access int array */
19:    ptr_int = list;
20:    printf("Before the change, list[2] contains: %d\n", list[2]);
21:    *(ptr_int + 2) = -3;
22:    printf("After the change, list[2] contains: %d\n", list[2]);
23:
24:    return 0;
25: }
 
Ñaùp soá:
 
Before the change, str contains: It's a string!
Before the change, str[5] contains: a
After the change, str[5] contains: A
After the change, str contains: It's A string!
Before the change, list[2] contains: 3
After the change, list[2] contains: -3

Con troû vaø Haøm

Chuyeån maûng cho haøm

Ñeå chuyeån maûng cho haøm, ta taïo ñoái soá chính baèng maûng ñoù vôùi caùch vieát  FunctionName(datatype listname[]).

Ví duï:

1:  /* Passing arrays to functions */
2:  #include <stdio.h>
3:
4:  int AddThree(int list[]);
5:
6:  main()
7:  {
8:     int sum, list[3];
9:
10:    printf("Enter three integers separated by spaces:\n");
11:    scanf("%d%d%d", &list[0], &list[1], &list[2]);
12:    sum = AddThree(list);
13:    printf("The sum of the three integers is: %d\n", sum);
14:
15:    return 0;
16: }
17:
18: int AddThree(int list[])
19: {
20:    int i;
21:    int result = 0;
22:
23:    for (i=0; i<3; i++)
24:       result += list[i];
25:    return result;
26: }
 
Ñaùp soá:
 
Enter three integers separated by spaces:
10  20  30
The sum of the three integers is: 60
 

Chuyeån con troû cho haøm

Moät maûng khoâng chæ soá ñöôïc hieåu nhö moät con troû chæ ñeán phaàn töû ñaàu tieân. Cho neân ta cuõng coù theå chuyeån maûng cho haøm baèng caùch chuyeån con troû töông ñöông cho haøm.

Ví duï:

1:  /* Passing pointers to functions */
2:  #include <stdio.h>
3:
4:  void ChPrint(char *ch);
5:  int DataAdd(int *list, int max);
6:  main()
7:  {
8:     char str[] = "It's a string!";
9:     char *ptr_str;
10:    int list[5] = {1, 2, 3, 4, 5};
11:    int *ptr_int;
12:
13:    /* assign address to pointer */
14:    ptr_str = str;
15:    ChPrint(ptr_str);
16:    ChPrint(str);
17:
18:    /* assign address to pointer */
19:    ptr_int = list;
20:    printf("The sum returned by DataAdd(): %d\n",
21:            DataAdd(ptr_int, 5));
22:    printf("The sum returned by DataAdd(): %d\n",
23:            DataAdd(list, 5));
24:    return 0;
25: }
26: /* function definition */
27: void ChPrint(char *ch)
28: {
29:    printf("%s\n", ch);
30: }
31: /* function definition */
32: int DataAdd(int *list, int max)
33: {
34:    int i;
35:    int sum = 0;
36:
37:    for (i=0; i<max; i++)
38:       sum += list[i];
39:    return sum;
40: }
 
Ñaùp soá:
 
It's a string!
It's a string!
The sum returned by DataAdd(): 15
The sum returned by DataAdd(): 15

Chuyeån maûng ña chieàu nhö ñoái soá

Chuyeån maûng ña chieàu cho haøm cuõng töông töï nhö chuyeån maûng 1 chieàu cho haøm, nhöng caàn chuù yù caùch tieáp caän ñeán töøng phaàn töû sao cho traùnh söï sai leäch goïi khoâng ñuùng.

Ví duï:

1:  /* Passing multidimensional arrays to functions */
2:  #include <stdio.h>
3:  /* function declarations */
4:  int DataAdd1(int list[][5], int max1, int max2);
5:  int DataAdd2(int *list, int max1, int max2);
6:  /* main() function */
7:  main()
8:  {
9:     int list[2][5] = {1, 2, 3, 4, 5,
10:                      5, 4, 3, 2, 1};
11:    int *ptr_int;
12:
13:    printf("The sum returned by DataAdd1(): %d\n",
14:            DataAdd1(list, 2, 5));
15:    ptr_int = &list[0][0];
16:    printf("The sum returned by DataAdd2(): %d\n",
17:            DataAdd2(ptr_int, 2, 5));
18:
19:    return 0;
20: }
21: /* function definition */
22: int DataAdd1(int list[][5], int max1, int max2)
23: {
24:    int i, j;
25:    int sum = 0;
26:
27:    for (i=0; i<max1; i++)
28:       for (j=0; j<max2; j++)
29:       sum += list[i][j];
30:    return sum;
31: }
32: /* function definition */
33: int DataAdd2(int *list, int max1, int max2)
34: {
35:    int i, j;
36:    int sum = 0;
37:
38:    for (i=0; i<max1; i++)
39:       for (j=0; j<max2; j++)
40:       sum += *(list + i*max2 + j);
41:    return sum;
42: }
 
Ñaùp soá:
 
The sum returned by DataAdd1(): 30
The sum returned by DataAdd2(): 30

Maûng con troû

Ví duï:

int *ptr_int[3];

bieán ptr_int laø moät maûng 3 phaàn töû con troû chæ ñeán soá nguyeân. 

 
int x1 = 10;
int x2 = 100;
int x3 = 1000;
ptr_int[0] = &x1;
ptr_int[1] = &x2;
ptr_int[2] = &x3;

Ví duï:

1:  /* Using an array of pointers */
2:  #include <stdio.h>
3:  /* function declarations */
4:  void StrPrint1(char **str1, int size);
5:  void StrPrint2(char *str2);
6:  /* main() function */
7:  main()
8:  {
9:     char *str[4] = {"There's music in the sighing of a reed;",
10:                    "There's music in the gushing of a rill;",
11:                    "There's music in all things if men had ears;",
12:                    "There earth is but an echo of the spheres.\n"
13:                   };
14:    int i, size = 4;
15:
16:    StrPrint1(str, size);
17:    for (i=0; i<size; i++)
18:       StrPrint2(str[i]);
19:
20:    return 0;
21: }
22: /* function definition */
23: void StrPrint1(char **str1, int size)
24: {
25:    int i;
26:    /* Print all strings in an array of pointers to strings */
27:    for (i=0; i<size; i++)
28:       printf("%s\n", str1[i]);
29: }
30: /* function definition */
31: void StrPrint2(char *str2)
32: {
33:     /* Prints one string at a time */
34:    printf("%s\n", str2);
35: }
 
Ñaùp soá:
 
There's music in the sighing of a reed;
There's music in the gushing of a rill;
There's music in all things if men had ears;
There earth is but an echo of the spheres.
There's music in the sighing of a reed;
There's music in the gushing of a rill;
There's music in all things if men had ears;
There earth is but an echo of the spheres.

Con troû chæ ñeán haøm

Töông töï nhö maûng, teân haøm khoâng coù ñoái soá ñöôïc hieåu nhö con troû chæ ñeán phaàn boä nhôù chöùa giaù trò cuûa haøm. Ta coù theå khai baùo con troû chæ ñeán giaù trò cuûa haøm vaø tieáp caän haøm ñoù thoâng qua con troû vöøa khai baùo.

Ví duï:

1:  /* Pointing to a function */
2:  #include <stdio.h>
3:  /* function declaration */
4:  int StrPrint(char *str);
5:  /* main() function */
6:  main()
7:  {
8:     char str[24] = "Pointing to a function.";
9:     int (*ptr)(char *str);
10:
11:    ptr = StrPrint;
12:    if (!(*ptr)(str))
13:       printf("Done!\n");
14:
15:    return 0;
16: }
17: /* function definition */
18: int StrPrint(char *str)
19: {
20:    printf("%s\n", str);
21:    return 0;
22: }
 
Ñaùp soá:
 
Pointing to a function.
Done!

Baøi taäp

  1. Ta phaûi coâng theâm bao nhieâu byte cho caùc pheùp tính sau?
  2. Cho ñoaïn khai baùo sau:
char ch[] = {`a', `b', `c', `d', `A', `B', `C', `D'};
char *ptr;
ptr = &ch[1];

caùc bieåu thöùc sau ñaây cho keát quaû gì?

  1. Cho maûng kyù töï sau:
char str[2][15] = { "You know what,", "C is powerful." };

vieát chöông trình chuyeån ñòa chæ khôûi ñaàu cuûa str cho haøm roài in noäi dung str leân maøn aûnh.

 

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