2011-12-18 41 views
7

Tôi đã tự hỏi liệu có bất kỳ điều gì sai trái khi truyền con trỏ tới putchar hay bất kỳ hàm chuẩn nào khác có thể được thực hiện dưới dạng macro, chức năng chấp nhận một con trỏ hàm. Dưới đây là một ví dụ về những gì tôi đang làm.Chuyển một con trỏ tới hàm putchar đến một hàm nhận int (*) (int)

#include <stdio.h> 

static int print(const char *s, int (*printc)(int)) 
{ 
     int c; 

     while (*s != '\0') { 
       if ((c = printc(*s++)) < 0) 
         return c; 
     } 
     return printc('\n'); 
} 

int main(void) 
{ 
     print("Hello, world", putchar); 
     return 0; 
} 

Tôi không gặp phải bất kỳ vấn đề nào khi biên dịch với GCC và Clang dưới GNU/Linux, cũng như GCC theo OpenBSD. Tôi tự hỏi liệu nó sẽ có cùng một hành vi theo mọi tiêu chuẩn thực hiện tương thích khác, vì putchar có thể được thực hiện như một macro. Tôi đã tìm kiếm thông qua các tiêu chuẩn, đặc biệt là các phần trên con trỏ hàm và putchar, và đã không thể tìm thấy bất cứ điều gì mà chỉ định cho dù điều này là hợp pháp hay không.

Cảm ơn.

+0

Nếu "chức năng" của bạn thực sự là macro, thì mã của bạn sẽ không biên dịch. –

+0

Không chắc liệu đây có phải là tiêu chuẩn tuân thủ hay không, nhưng với 'gcc', hành vi này có vẻ như được mong đợi: http://gcc.gnu.org/onlinedocs/cpp/Function_002dlike-Macros.html – RageD

+0

Làm điều đó * chỉ * macro .. –

Trả lời

6

Tiếp theo từ tôi ý kiến ​​dựa trên với @pmg , Tôi đã tìm thấy phần có liên quan của tiêu chuẩn (C99, 7.1.4 p.1):

... nó được phép lấy các địa chỉ s của một chức năng thư viện ngay cả khi nó cũng được định nghĩa là một macro. 161)


161) Điều này có nghĩa rằng một thực hiện trách nhiệm cung cấp một chức năng thực tế cho mỗi chức năng thư viện, ngay cả khi nó cũng cung cấp một macro cho chức năng đó.

+0

+1 cho câu cá có liên quan thông qua Tiêu chuẩn :) – pmg

+0

@pmg: +1 cho câu trả lời của bạn nữa, vì đã giúp tôi học điều gì đó ngày hôm nay ... –

2

Điều này là hợp pháp vì nó đề cập đến chức năng thư viện chứ không phải macro. Khi nó được định nghĩa là macro, macro đó lấy một đối số và do đó putchar không có dấu ngoặc đơn sau đây không tham chiếu đến nó. Đây là một thể hiện của việc sử dụng một macro để nội tuyến chức năng, và không nên được thực hiện như là thực hành tốt ngay bây giờ mà nội tuyến được hỗ trợ bởi trình biên dịch.

2

Macro chỉ được "gọi" khi mã định danh của nó được theo sau bởi dấu ngoặc đơn mở (. Nếu không, hàm thực của cùng tên được gọi/được sử dụng.

nét
#include <stdio.h> 
#define macro(x) 42 
int (macro)(int x) { return x; } 
int main(void) { 
    printf("%d %d\n", macro(1), (macro)(1)); 
} 

Chức năng có "thêm" ngoặc để ngăn chặn sự vĩ mô từ được mở rộng

Xem mã chạy tại ideone: thảo luận http://ideone.com/UXvjX

+0

Thật vậy. Nhưng tôi không nghĩ điều đó thực sự giúp OP với vấn đề của anh ấy. –

+1

Tiêu chuẩn nêu rõ 'putchar' phải là hàm (nó cũng có thể là macro), do đó mã OP hoạt động. – pmg

+0

Ah vâng, bạn nói đúng, tôi vừa tìm thấy phần có liên quan của tiêu chuẩn. –

Các vấn đề liên quan