Macro là (chính thức) hiệu quả hơn, vì nó không liên quan đến một cuộc gọi chức năng. Nó có thể được tối ưu hóa dễ dàng hơn, vì nó chỉ liên quan đến việc tra cứu bù con trỏ.
Lệnh gọi cho phép liên kết với cùng một thư viện ngay cả khi chương trình được biên dịch mà không có định nghĩa macro - nếu nó được biên dịch với một tiêu đề khác hoặc chỉ với một khai báo giả mạo bên trong tệp nguồn. Ví dụ, nếu bạn có một trình biên dịch có phiên bản ctype.h "được cải tiến" của ai đó mà không có macro, hàm vẫn sẽ tồn tại trong thời gian chạy để sử dụng.
Nếu chúng ta nhìn vào tiêu chuẩn:
c99
7.1.4 Sử dụng các chức năng của thư viện
Bất kỳ chức năng nào được khai báo trong tiêu đề đều có thể được triển khai bổ sung dưới dạng macro giống như chức năng trong tiêu đề, do đó, nếu chức năng thư viện được khai báo rõ ràng khi bao gồm tiêu đề của nó, có thể sử dụng một trong các kỹ thuật được hiển thị bên dưới để đảm bảo không khai báo bị ảnh hưởng bởi một vĩ mô như vậy. Bất kỳ định nghĩa vĩ mô nào của hàm đều có thể bị loại bỏ cục bộ bằng cách đặt tên của hàm trong ngoặc đơn, vì tên này sau đó không được đặt theo dấu ngoặc đơn bên trái cho biết mở rộng tên hàm macro. Với cùng một lý do cú pháp, nó được phép lấy địa chỉ của hàm thư viện ngay cả khi nó cũng được định nghĩa là một macro.
Điều đó có nghĩa là nếu bạn viết:
int b = (isdigit)(c);
hoặc là
int (*f)(int) = &isdigit;
int b = f(c);
sau đó bạn đang gọi hàm thực tế, không phải macro. Bạn cũng có thể viết hợp pháp:
#undef isdigit
int b = isdigit(c);
hoặc (trong tệp nguồn không có #include <ctype.h>
trực tiếp hoặc quá cảnh):
extern int isdigit(int);
int b = isdigit(c);