Trong hướng dẫn này - là một phần của loạt hướng dẫn lập trình C đang diễn ra - chúng ta sẽ thảo luận về khái niệm typedef. Như tên gọi của nó (hãy nghĩ về typedef như type+def), typedef là một tiện ích do C cung cấp để định nghĩa tên mới cho các kiểu dữ liệu hiện có.
Dòng trên - bắt đầu bằng từ khóa 'typedef' - đặt tên mới cho kiểu dữ liệu 'int': 'my_int'. Vì vậy, một đoạn mã như thế này:
Có thể được viết như sau khi sử dụng ví dụ typedef mà chúng ta vừa thảo luận:
Bây giờ, một câu hỏi mà một số người có thể hỏi là sự khác biệt giữa typedef và #define là gì? Vâng, trong khi cả hai dường như đều làm những việc tương tự nhau, thì thực tế có khá nhiều điểm khác biệt giữa hai lệnh này.
Trước hết, typedef được trình biên dịch diễn giải, trong khi #define không bao giờ đạt đến giai đoạn biên dịch vì nó được diễn giải ở chính giai đoạn tiền xử lý. Sau đó, typedef tuân theo các quy tắc phạm vi, trong khi #define thì không. Sau đây là một ví dụ về điều này:
Khi đoạn mã này được thực thi, bạn sẽ nhận được lỗi sau:
Vì vậy, như bạn có thể thấy, trình biên dịch không thể nhận dạng kiểu 'my_int' trong hàm 'my_func', vì phạm vi mà typedef hợp lệ là phạm vi của hàm 'main'.
Sau đó, có một số khác biệt khác giữa typedef và #define. Ví dụ, khi sử dụng #define, bạn cũng có thể tạo bí danh cho các giá trị hằng số - ý tôi là, bạn có thể làm điều gì đó như '#define PIE 3.14'. Ngoài ra, như bạn đã thấy, #define không được kết thúc bằng dấu chấm phẩy trong khi typedef thì được.
Bây giờ, người ta vẫn sẽ hỏi tại sao chúng ta cần 'typedef'. Hay nói cách khác, typedef thực sự hữu ích ở đâu? Vâng, giả sử có một đoạn mã với các hàm trả về 'con trỏ tới một hàm chấp nhận hai số nguyên làm đối số khi trả về một giá trị ký tự'.
Trong trường hợp bạn chưa biết, một con trỏ như vậy được khai báo theo cách sau:
Trong đó fn_ptr là tên của một con trỏ như vậy.
Vì vậy, thay vì phải sử dụng loại khai báo dài dòng và phức tạp này nhiều lần như kiểu trả về của các hàm khác, bạn có thể chỉ cần biến fn_ptr thành một kiểu bằng cách sử dụng typedef:
Và bây giờ bạn chỉ cần sử dụng 'fn_ptr' và nó sẽ biểu thị một con trỏ có kiểu này.
Một cách sử dụng khác của typedef liên quan đến việc sử dụng trong mã một kiểu dữ liệu do người dùng xác định tương ứng với kiểu gốc do nền tảng cơ bản mà mã chạy trên đó cung cấp. Theo cách này, typedef giúp dễ hiểu và bảo trì bất kỳ đoạn mã nào được phát triển để chạy trên nhiều nền tảng.
Bạn nên thử các ví dụ mà chúng tôi sử dụng ở đây cũng như phát triển thêm các ví dụ để hiểu rõ hơn về typedef và như mọi khi, trong trường hợp có bất kỳ nghi ngờ hoặc thắc mắc nào, hãy để lại bình luận bên dưới.
Typedef trong Ngôn ngữ lập trình C
Sau đây là một ví dụ cho thấy cách sử dụng typedef:
Mã:
typedef int my_int
Mã:
#include
int main()
{
int a = 10;
printf("Giá trị của a là: %d", a);
return 0;
}
Mã:
#include
typedef int my_int;
int main()
{
my_int a = 10;
printf("Giá trị của a là: %d", a);
return 0;
}
Trước hết, typedef được trình biên dịch diễn giải, trong khi #define không bao giờ đạt đến giai đoạn biên dịch vì nó được diễn giải ở chính giai đoạn tiền xử lý. Sau đó, typedef tuân theo các quy tắc phạm vi, trong khi #define thì không. Sau đây là một ví dụ về điều này:
Mã:
#include
void my_func();
int main()
{
typedef int my_int;
my_int a = 10;
printf("Giá trị của a là: %d", a);
my_func();
return 0;
}
void my_func()
{
my_int b = 20;
printf("Giá trị của a là: %d", b);
return;
}
Mã:
main.c: Trong hàm ‘my_func’:
main.c:25:5: lỗi: tên kiểu không xác định ‘my_int’
my_int b = 20;
^
Sau đó, có một số khác biệt khác giữa typedef và #define. Ví dụ, khi sử dụng #define, bạn cũng có thể tạo bí danh cho các giá trị hằng số - ý tôi là, bạn có thể làm điều gì đó như '#define PIE 3.14'. Ngoài ra, như bạn đã thấy, #define không được kết thúc bằng dấu chấm phẩy trong khi typedef thì được.
Bây giờ, người ta vẫn sẽ hỏi tại sao chúng ta cần 'typedef'. Hay nói cách khác, typedef thực sự hữu ích ở đâu? Vâng, giả sử có một đoạn mã với các hàm trả về 'con trỏ tới một hàm chấp nhận hai số nguyên làm đối số khi trả về một giá trị ký tự'.
Trong trường hợp bạn chưa biết, một con trỏ như vậy được khai báo theo cách sau:
Mã:
char (*fn_ptr) (int, int);
Vì vậy, thay vì phải sử dụng loại khai báo dài dòng và phức tạp này nhiều lần như kiểu trả về của các hàm khác, bạn có thể chỉ cần biến fn_ptr thành một kiểu bằng cách sử dụng typedef:
Mã:
typedef char (*fn_ptr) (int, int);
Một cách sử dụng khác của typedef liên quan đến việc sử dụng trong mã một kiểu dữ liệu do người dùng xác định tương ứng với kiểu gốc do nền tảng cơ bản mà mã chạy trên đó cung cấp. Theo cách này, typedef giúp dễ hiểu và bảo trì bất kỳ đoạn mã nào được phát triển để chạy trên nhiều nền tảng.
Kết luận
Vì vậy, trong hướng dẫn này, chúng ta đã thảo luận về những điều cơ bản của typedef, bao gồm typedef thực hiện chức năng gì, typedef khác với chỉ thị #define như thế nào và typedef có thể giúp bạn tiết kiệm thời gian bằng cách làm cho mã dễ đọc, dễ hiểu cũng như dễ bảo trì như thế nào.Bạn nên thử các ví dụ mà chúng tôi sử dụng ở đây cũng như phát triển thêm các ví dụ để hiểu rõ hơn về typedef và như mọi khi, trong trường hợp có bất kỳ nghi ngờ hoặc thắc mắc nào, hãy để lại bình luận bên dưới.