C là một ngơn ngữ lập trình có cấu trúc, tuy vậy nó vẫn chứa một số câu lệnh làm phá vớ cấu trúc của chương trình:
Bài 9 Hàm Mục tiêu:
9.5 Các nguyên mẫu hàm
Một nguyên mẫu hàm là một khai báo hàm trong đó xác định rõ kiểu dữ liệu của các đối số và trị trả về. Thông thường, các hàm được khai báo bằng cách xác định kiểu của giá trị được trả về bởi hàm, và tên hàm. Tuy nhiên, chuẩn ANSI C cho phép số lượng và kiểu dữ liệu của các đối số hàm được khai báo. Một hàm abc() có hai đối số kiểu int là x và y, và trả về một giá trị kiểu char, có thể được khai báo như sau:
char abc();
hoặc
char abc(int x, nt y);
Cách định nghĩa sau được gọi là nguyên mẫu hàm. Khi các ngun mẫu được sử dụng, C có thể tìm và thơng báo bất kỳ kiểu dữ liệu không hợp lệ khi chuyển đổi giữa các đối số được dùng để gọi một hàm với sự định nghĩa kiểu của các tham số. Một lỗi sẽ được thơng báo ngay khi có sự khác nhau giữa số lượng các đối số được sử dụng để gọi hàm và số lượng các tham số khi định nghĩa hàm.
Cú pháp tổng quát của một nguyên mẫu hàm:
type function_name(type parm_namel,type parm_name2,..type parm_nameN);
Khi hàm được khai báo khơng có các thơng tin ngun mẫu, trình biên dịch cho rằng khơng có thơng tin về các tham số được đưa ra. Một hàm khơng có đối số có thể gây ra lỗi khi khai báo khơng có thơng tin nguyên mẫu. Để tránh điều này, khi một hàm khơng có tham số, nguyên mẫu của nó sử dụng int trong cặp dấu ngoặc (). Như đã nói ở trên, int cũng được sử dụng để khai báo
tường minh một hàm khơng có giá trị trả về.
Ví dụ, nếu một hàm noparam() trả về kiểu dữ liệu char và khơng có các tham số được gọi, có thể được khai báo như sau
char noparam(int);
Khai báo trên chỉ ra rằng hàm khơng có tham số, và bất kỳ lời gọi có truyền tham số đến hàm đó là khơng đúng.
Khi một hàm khơng ngun mẫu được gọi tất cả các kiểu char được đổi thành kiểu int và tất cả kiểu float được đổi thành kiểu double. Tuy nhiên, nếu một hàm là nguyên mẫu, thì các kiểu đã đưa ra trong nguyên mẫu được giữ ngun và khơng có sự tăng cấp kiểu xảy ra.
9.6 Các biến
Như đã thảo luận, các biến là những vị trí được đặt tên trong bộ nhớ, được sử dụng để chứa giá trị có thể hoặc khơng thể được sửa đổi bởi một chương trình hoặc một hàm. Có ba loại biến cơ bản:
biến cục bộ, tham số hình thức, và biến toàn cục.
1. Biến cục bộ là những biến được khai báo bên trong một hàm.
2. Tham số hình thức được khai báo trong một định nghĩa hàm như là các tham số.
3. Biến toàn cục được khai báo bên ngoài các hàm. 9.6.1 Biến cục bộ
Biến cục bộ còn được gọi là biến động, từ khoá auto được sử dụng để khai báo chúng. Chúng chỉ được tham chiếu đến bởi các lệnh bên trong của khối lệnh mà biến được khai báo. Để rõ hơn, một biến cục bộ được tạo ra trong lúc vào một khối và bị huỷ trong lúc đi ra khỏi khối đó. Khối lệnh thơng thường nhất mà trong đó một biến cục bộ được khai báo chính là hàm.
Xem đoạn mã lệnh sau:
int blkl(int) /* int denotes no value returned*/ { char ch; ch = ‘a’; . . } int blk2(int) { char ch; ch = ‘b’; . . }
Biến ch được khai báo hai lần, trong blk1() và blk2(). ch trong blk1() khơng có liên quan đến ch trong blk2() bởi vì mỗi ch chỉ được biết đến trong khối lệnh mà nó được khai báo.
Vì các biến cục bộ được tạo ra và huỷ đi trong một khối mà chúng được khai báo, nên nội dung của chúng bị mất bên ngoài phạm vi của khối. Điều này có nghĩa là chúng khơng thể duy trì giá trị của chúng giữa các lần gọi hàm.
Từ khóa auto có thể được dùng để khai báo các biến cục bộ, nhưng thường nó khơng được dùng vì mặc nhiên các biến khơng tồn cục được xem như là biến cục bộ.
Các biến cục bộ được sử dụng bởi các hàm thường được khai báo ngay sau dấu ngoặc mở ‘{‘ của hàm và trước tất cả các câu lệnh. Tuy nhiên, các khai báo có thể ở bên trong một khối của một hàm. Ví dụ, int blk1(int) { int t; t = 1; if(t > 5) { char ch; . . } . }
Trong ví dụ trên biến ch được tạo ra và chỉ hợp lệ bên trong khối mã lệnh if’. Nó khơng thể được tham chiếu đến trong một phần khác của hàm blk1().
Một trong những thuận lợi của sự khai báo một biến theo cách này đó là bộ nhớ sẽ chỉ được cấp phát cho nó khi nếu điều kiện để đi vào khối lệnh if được thoả. Điều này là bởi vì các biến cục bộ
chỉ được khai báo khi đi vào khối lệnh mà các biến được định nghĩa trong đó.
Chú ý: Điều quan trọng cần nhớ là tất cả các biến cục bộ phải được khai báo tại điểm bắt đầu của
khối mà trong đó chúng được định nghĩa, và trước tất cả các câu lệnh thực thi. Ví dụ sau có thể khơng làm việc với một số các trình biên dịch.
int blk1(int) {
int len; len = 1;
char ch; /* This will cause an error */ ch = ‘a’;
. . }