Đoạn:
((int8_t) + (78));
là một ngôn luận, một trong đó có giá trị 78
, áp dụng unary +
, sau đó phôi đó để một kiểu int8_t
, trước khi ném nó đi. Không có gì khác biệt với các biểu thức pháp lý:
42;
a + 1;
cũng đánh giá các biểu thức sau đó sẽ loại bỏ kết quả nếu trình biên dịch có thể không có tác dụng phụ).
Các biểu thức "khỏa thân" này hoàn toàn hợp lệ trong C và thường hữu ích chỉ khi chúng có tác dụng phụ, chẳng hạn như với i++
, tính toán i
và ném nó đi với tác dụng phụ là nó tăng giá trị.
Cách bạn nên được sử dụng vĩ mô đó là hơn dọc theo dòng:
int8_t varname = INT8_C (somevalue);
Lý do cho sự +
hành unary dường như không cần thiết có thể được tìm thấy trong tiêu chuẩn. Trích dẫn C99 6.5.3.3 Unary arithmetic operators /1
:
Toán hạng của toán tử đơn hoặc + phải có loại số học;
Và, trong 6.2.5 Types, /18
:
Integer và loại nổi được gọi chung là các loại số học.
Nói cách khác, đơn nhất +
ngăn bạn sử dụng tất cả các loại dữ liệu khác trong macro, chẳng hạn như con trỏ, số phức hoặc cấu trúc.
Và, cuối cùng, lý do của bạn:
signed char + 78;
đoạn không hoạt động là bởi vì nó không phải là điều tương tự. Điều này đang bắt đầu tuyên bố một biến loại signed char
nhưng chokes khi nó được +
vì đó không phải là một tên biến pháp lý. Để làm cho nó tương đương với đoạn làm việc của bạn, bạn sẽ sử dụng:
(signed char) + 78;
đó là đúc giá trị +78
gõ signed char
.
Và, theo C99 7.8.14 Macros for integer constants /2
, bạn cũng nên cẩn thận với việc sử dụng phi hằng trong những macro, họ đang không được bảo đảm để làm việc:
Đối số trong bất kỳ trường hợp các macro sẽ là một hằng số nguyên không được trộn lẫn (như được định nghĩa trong 6.4.4.1) với một giá trị không vượt quá giới hạn cho loại tương ứng.
6.4.4.1
chỉ đơn giản là xác định các định dạng số nguyên khác nhau (thập phân/bát phân/hex) với hậu tố khác nhau (U
, UL
, ULL
, L
, LL
và chữ thường tương đương, tùy thuộc vào loại). Điểm mấu chốt là chúng phải là các hằng số thay vì các biến.
Ví dụ, glibc
có:
# define INT8_C(c) c
# define INT16_C(c) c
# define INT32_C(c) c
# if __WORDSIZE == 64
# define INT64_C(c) C## L
# else
# define INT64_C(c) C## LL
# endif
mà sẽ cho phép bạn INT8_C
vĩ mô để làm việc tốt nhưng văn bản INT64_C(val)
sẽ được pre-chế biến thành một trong hai valL
hoặc valLL
, không phải trong đó bạn muốn.
Cần lưu ý rằng định nghĩa này của 'INT8_C' là sai: 7.18.4 đoạn 3: "Mỗi lời gọi của một trong các macro này (CHÚ Ý: tham chiếu đến' INTN_C') sẽ mở rộng thành một biểu thức hằng số nguyên ** thích hợp để sử dụng trong các chỉ thị tiền xử lý '# if'. **" trong một chỉ thị tiền xử lý, vì các kiểu (và do đó phôi) không tồn tại trong quá trình tiền xử lý. Trình biên dịch/nền tảng nào bạn đang sử dụng? Bạn nên xem xét việc nộp báo cáo lỗi về vấn đề này. –
@ChrisLutz: Nó hợp lệ trong C99; nó đã trở thành không hợp lệ trong Corrigendum kỹ thuật 1, được kết hợp vào N1256. Điều này đã được đáp ứng với [DR # 209] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_209.htm). –
@KeithThompson - Ah. Tôi có một bản sao của TC2, và cho đến gần đây gần đây đã không thực sự nhận thức được về Chương trình kỹ thuật. –