Đầu ra của mã C này là 49 nhưng ai đó có thể giải thích cho tôi làm thế nào? [bản sao]

Jan 20 2021
#include <stdio.h>

#define CUBE(x) (x * x * x)

int main() {
    printf("%d", CUBE(4+5));
    return 0;
}

Trả lời

5 MarkSouls Jan 20 2021 at 14:31

Macro sẽ chuyển mã thành:

printf("%d", (4+5 * 4+5 * 4+5));

hiệu quả là:

printf("%d", 4 + (5*4) + (5*4) + 5); // 29

Nếu bạn muốn lập phương 9để có được 729, bạn nên viết CUBE((4+5)).

9 chqrlie Jan 20 2021 at 14:34

Đây là cách macro được mở rộng trong quá trình biên dịch:

printf("%d", (4+5 * 4+5 * 4+5));

*có mức độ ưu tiên cao hơn +, biểu thức này được đánh giá là (4 + (5 * 4) + (5 * 4) + 5), tạo ra 49thay vì mong đợi 729.

Để tránh các vấn đề về ưu tiên toán tử như vậy, tất cả các đối số macro phải được đặt trong ngoặc đơn trong định nghĩa macro cũng như bản thân biểu thức:

#define CUBE(x)  ((x) * (x) * (x))

Tuy nhiên, lưu ý rằng việc mở rộng này CUBEđánh giá xnhiều lần, đây là một vấn đề nếu đối số macro có tác dụng phụ, chẳng hạn như CUBE(i++).

Để tránh tất cả những vấn đề này, hãy sử dụng một hàm và để trình biên dịch tối ưu hóa nó:

int cube(int x) {
    return x * x * x;
}

Bạn có thể thêm static inlinevào trước định nghĩa hàm này, nhưng các trình tối ưu hóa hiện đại vẫn sẽ nội dòng hàm mà không có định nghĩa này.

3 Tecto Jan 20 2021 at 14:32

Bộ tiền xử lý C theo nghĩa đen sẽ thay thế tất cả các trường hợp của x cho 4 + 5, dẫn đến đoạn mã sau:

i = 4+5*4+5*4+5;

(nhân trước, sau đó cộng)

3 SahadatHossain Jan 20 2021 at 14:31

bạn cần cung cấp đầu vào như CUBE((4+5))nếu bạn muốn thêm các số và sau đó gửi đến CUBE. Nguyên nhân CUBE(4+5)về cơ bản được mở rộng thành 4+5*4+5*4+5vì nó đặt toàn bộ 4+5vào vị trí của x. Vì vậy, 4+5*4+5*4+5= 4+20+20+5khi phép nhân đến trước và sau đó cộng chúng sẽ cho 49.

Xác định macro giống như #define CUBE(x) ((x)*(x)*(x))nó thực sự đầu tiên tiến hành (4+5)hoạt động cho mọi (x)và sau đó thực hiện *hoạt động.

Một cách khác là chỉ sử dụng CUBE((4+5))trong khi gọi macro, về cơ bản, trước tiên nó thêm hai số và (4+5)= 9và sau đó thực hiện CUBE(9), như:

#include<stdio.h>
#define CUBE(x) (x * x * x)

int main( )
{
    printf("%d", CUBE((4+5)));
    return 0;
}
1 BasileStarynkevitch Jan 20 2021 at 14:29

Đọc Modern C , sau đó là bản dự thảo tiêu chuẩn C n1570 và tài liệu về GCC , GDB và CPP . Xem thêm trang web tham khảo C này .

Lấy cảm hứng từ các dự án mã nguồn mở hiện có, ví dụ như trên github hoặc phần mềm GNU .

Với trình biên dịch GCC gần đây , hãy gọi nó là gcc -Wall -Wextra -g. Cũng sử dụng các -C -Etùy chọn để lấy biểu mẫu được xử lý trước.

Bạn cũng có thể quan tâm bởi những tuyên bố-expr mở rộng của GCC.

Bạn CUBE(4+5)là vĩ mô mở rộng để 4+5*4+5*4+5có được tính như 4+(5*4)+(5*4)+5theo thứ tự ưu tiên của các nhà khai thác C .

Cân nhắc mã hóa một static inlinechức năng như

static inline int cube(int x) { return x*x*x; }

hoặc nếu bạn cần một macro, ít nhất

#define CUBE(X) ((X)*(X)*(X))

điều này sẽ không hoạt động tốt CUBE(i++)(trong khi với inlinehàm, cube(i++)thực hiện những gì bạn muốn nó làm: tăng imột lần!).

BTW, bạn có thể sử dụng GPP , hoặc GNU m4 , (hoặc bộ tạo của riêng bạn, hoặc GNU bison ) để tạo một số mã C. Theo nguyên tắc chung, hãy nghĩ với AST : khi bạn tạo mã C, hãy tạo ra rất nhiều dấu ngoặc đơn vô dụng, như trong Chicken Scheme , SWIG , hoặc trong CAIA hoặc trong manydl.c của tôi

Bạn cũng có thể sử dụng trình phân tích tĩnh Clang trên mã của mình (và có thể là Frama-C ).

Bạn có thể quan tâm đến việc đọc một số hướng dẫn mã hóa như MISRA C hoặc GNU .