c. Các ví dụ về dùng hàm đệ qu i:
4.4.1 Con trỏ và mảng một chiều:
Trong C có mối quan hệ chặt chẽ giữa con trỏ và mảng : các phần tử của mảng có thể được xác định nhờ chỉ số hoặc thông qua con trỏ.
Phép toán lấy địa chỉ :
Phép toán này chỉ áp dụng cho các phần tử của mảng một chiều. Giả sử ta có khai báo : double b[20];
Khi đó phép tốn : &b[9] sẽ cho địa chỉ của phần tử b[9]. Tên mảng là một hằng địa chỉ :
Khi khai báo : float a[10];
máy sẽ bố trí bố trí cho mảng a mười khoảng nhớ liên tiếp, mỗi khoảng nhớ là 4 byte. Như vậy, nếu biết địa chỉ của một phần tử nào đó của mảng a, thì ta có thể dễ dàng suy ra địa chỉ của các phần tử khác của mảng.
Với C ta có :
a tương đương với &a[0] a+i tương đương với &a[i] *(a+i) tương đương với a[i]
Con trỏ trỏ tới các phần tử của mảng một chiều : Khi con trỏ pa trỏ tới phần tử a[k] thì :
pa+i trỏ tới phần tử thứ i sau a[k], có nghĩa là nó trỏ tới a[k+i]. pa-i trỏ tới phần tử thứ i trước a[k], có nghĩa là nó trỏ tới a[k-i]. *(pa+i) tương đương với pa[i].
Như vậy, sau hai câu lệnh : float a[20],*p; p=a;
thì bốn cách viết sau có tác dụng như nhau : a[i] *(a+i) p[i] *(p+i)
Cách 1: #include "stdio.h" main() { float a[4],tong; int i; for (i=0;i<4;++i) { printf("\n a[%d]=",i); scanf("%f",a+i); } tong=0; for (i=0;i<4;++i) tong+=a[i];
printf("\n Tong cac phan tu mang la :%8.2f ",tong); }
Cách 2 :
#include "stdio.h" main()
{
float a[4],tong, *troa; int i; troa=a; for (i=0;i<4;++i) { printf("\n a[%d]=",i); scanf("%f",&troa[i]); } tong=0; for (i=0;i<4;++i) tong+=troa[i];
printf("\n Tong cac phan tu mang la :%8.2f ",tong); }
Cách 3 :
#include "stdio.h" main()
float a[4],tong,*troa; int i; troa=a; for (i=0;i<4;++i) { printf("\n a[%d]=",i); scanf("%f",troa+i); } tong=0; for (i=0;i<4;++i) tong+=*(troa+i);
printf("\n Tong cac phan tu mang la :%8.2f ",tong);
}
Chú ý :
Mảng một chiều và con trỏ tương ứng phải cùng kiểu. 4.4.2 Con trỏ và mảng nhiều chiều
Việc sử lý mảng nhiều chiều phức tạp hơn so với mảng một chiều. Không phải mọi qui tắc đúng với mảng một chiều đều có thể áp dụng cho mảng nhiều chiều.
Phép lấy địa chỉ :
Phép lấy địa chỉ đối với các phần tử mảng hai chiều chỉ có thể áp dụng khi các phần tử mảng hai chiều có kiểu ngun, cịn lại thì phép lấy địa chỉ cho các phần tử mảng nhiều chiều là khơng thực hiện được .Ví dụ như ta có thể lấy địa chỉ &a[1][2] khi a là mảng nguyên.
Phép cộng địa chỉ trong mảng hai chiều:
Giả sử ta có mảng hai chiều a[2][3] có 6 phần tử úng với sáu địa chỉ liên tiếp trong bộ nhớ được xếp theo thứ tự sau :
Phần tử a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
Địa chỉ 1 2 3 4 5 6
Tên mảng a biểu thị địa chỉ đầu tiên của mảng. Phép cộng địa chỉ ở đây được thực hiện như sau :
C coi mảng hai chiều là mảng ( một chiều ) của mảng, như vậy khai báo float a[2][3];
thì a là mảng mà mỗi phần tử của nó là một dãy 3 số thực ( một hàng của mảng ). Vì vậy :
a trỏ phần tử thứ nhất của mảng : phần tử a[0][0]
a+1 trỏ phần tử đầu hàng thứ hai của mảng : phần tử a[1][0]
Con trỏ và mảng hai chiều :
Để lần lượt duyệt trên các phần tử của mảng hai chiều ta có thể dùng con trỏ như minh hoạ ở ví dụ sau :
float *pa,a[2][3]; pa=(float*)a; lúc đó :
pa trỏ tới a[0][0] pa+1 trỏ tới a[0][1] pa+2 trỏ tới a[0][2] pa+3 trỏ tới a[1][0] pa+4 trỏ tới a[1][1] pa+5 trỏ tới a[1][2] Ví dụ :
Dùng con trỏ để vào số liệu cho mảng hai chiều. Cách 1 : #include "stdio.h" main() { float a[2][3],*pa; int i; pa=(float*)a; for (i=0;i<6;++i) scanf("%f",pa+i); } Cách 2 : #include "stdio.h" main() { float a[2][3],*pa; int i; for (i=0;i<6;++i) scanf("%f",(float*)a+i); } 4.5. Con trỏ tới hàm
a. Cách khai báo con trỏ hàm và mảng con trỏ hàm :
Ta sẽ trình bày quy tắc khai báo thơng qua các ví dụ : Ví dụ 1:
Câu lệnh :
float (*f)(float),(*mf[50])(int); Để khai báo :
f là con trỏ hàm kiểu float có đối là float
mf là mảng con trỏ hàm kiểu float có đối kiểu int ( có 50 phần tử ) Ví dụ 2:
Câu lệnh :
double (*g)(int, double),(*mg[30])(double, float); Để khai báo :
g là con trỏ hàm kiểu double có các đối kiểu int và double
mg là mảng con trỏ hàm kiểu double có các đối kiểu double và float ( có 30 phần tử )