2013-06-04 27 views
5

GCC có awesome ternary expression extension to C cho phép chúng ta tạo ra một tuyên bố như thế này:Tại sao không phân công hỗ trợ mở rộng ba kỳ của GCC?

int x = some_var ?: 10; // expands to some_var ? some_var : 10 

Đó là thực sự tốt đẹp, và trong khi nó không phải là đặc biệt trực quan, nó làm việc. Hầu hết các nhà khai thác nhị phân bằng ngôn ngữ C có một nhà điều hành thêm liên kết với chúng, cho phép chuyển nhượng:

x = x + 2; 

// instead, we can say 
x += 2; 

Vì đây là trường hợp, và các tiêu chuẩn cho hầu hết các nhà khai thác nhị phân C (+, -, *, /, %, |, &, ^), tại sao không phải là trường hợp này cho các nhà điều hành mở rộng ternary:

int x = ...; 
x ?:= 2; // error: Expected expression before '=' token 

// which would expand to 
x = x ?: 2; 

các nhà khai thác duy nhất không hỗ trợ điều này trong tiêu chuẩn C là các toán tử logic (||, &&), mà chắc chắn ternary không thuộc, vậy tại sao chúng ta không thể làm điều này?

Tôi thực sự muốn làm một khuôn mặt cười với mái tóc mát mẻ trong mã của tôi, nhưng tôi không thể! Đây có phải là sự giám sát trong việc thiết kế nhà điều hành, hay cố ý và ghi lại một nơi nào đó? Có phải đó là kết quả của toán tử đoản mạch toán hạng của nó hay cái gì khác hoàn toàn không?

+0

Không chắc chắn những gì 'x?: = 2;' có nghĩa là, nhưng có thể 'x?= ValueWhenXTrue: ValueWhenXFalse; '. – chux

+1

Tôi không thấy câu hỏi này 'không mang tính xây dựng' như thế nào. Nó hoàn toàn theo chủ đề, thảo luận về hành vi của một toán tử cụ thể trong GNU C. Nó được gắn thẻ đúng cách, đưa ra các ví dụ đơn giản, cụ thể và có một câu trả lời dứt khoát. –

+0

@chux Trong con người nói, nó sẽ có nghĩa là 'nếu x là số không, đặt nó là 2'. –

Trả lời

6

Để trả lời câu hỏi, tôi tin rằng có một số câu hỏi khác cần được trả lời.

Tại sao lại có một nhà điều hành ?: bằng ngôn ngữ C và tại sao nó tốt hơn hơn if-else?

Theo như tôi biết, không ai có thể trả lời câu hỏi đó, mà không chỉ nêu rõ ý kiến ​​chủ quan của chính họ. K & R 2.11 nói rằng

"Cụm từ có điều kiện thường dẫn đến mã ngắn gọn".

và sau đó họ minh họa điều này với dòng

printf("%6d%c", a[i], (i%10==9 || i==n-1) ? '\n' : ' '); 

đó là chủ quan của riêng mình, quan điểm của bùn. Cá nhân, tôi tin rằng

printf("%6d", a[i]); 

if(i%10==9 || i==n-1) 
    printf("\n"); 
else 
    printf(" "); 

là xa, xa rõ ràng hơn kể từ khi tôi có thể đọc và hiểu mã đó trong 10 giây, như trái ngược với 1 phút để đọc và hiểu các phiên bản K & R. Ngoài ra, mã của tôi phân tách in số nguyên từ định dạng không liên quan. Nhưng tất nhiên, đó là của tôi ý kiến ​​chủ quan, không có quyền rõ ràng hoặc sai.

Đối với nguồn chính thức, phiên bản hợp lý C99 5.10, 6.5.15 không thực sự đề cập đến lý do tại sao toán tử ?: là cần thiết.Nó chủ yếu chỉ khẳng định rằng hành vi của các nhà điều hành đã bị thay đổi trong tiêu chuẩn mới:

Các hạn chế cú pháp trên các toán hạng giữa nhà điều hành có điều kiện đã được nới lỏng để bao gồm nhiều hơn là chỉ logic-OR-biểu : một số triển khai hiện có đã áp dụng thực tiễn này.

Loại biểu thức toán tử có điều kiện có thể bị vô hiệu, cấu trúc hoặc liên kết; hầu hết các nhà khai thác khác không xử lý các loại như vậy . Các quy tắc cho kiểu cân bằng giữa con trỏ và số nguyên có, tuy nhiên, được siết chặt, vì bây giờ chỉ hằng số 0 có thể được gắn là bị ép buộc với một con trỏ.

Vì vậy, nếu ai đó có yêu cầu thực hiện số học về cấu trúc hoặc loại công đoàn, thì:: được cho là tiện lợi hơn nếu-else. Tôi thấy không có lợi ích rõ ràng từ điều này, nhưng ít nhất nó là một số lý do cho các nhà điều hành để tồn tại.

Câu hỏi tiếp theo sau đó sẽ là:

Tại sao lại có một phần mở rộng trình biên dịch cho ?: toán hạng trong GCC biên dịch?

Câu trả lời cho điều này được đề cập here:

Khi nó trở nên hữu ích là khi toán hạng đầu tiên thực hiện, hoặc có thể (nếu nó là một đối số vĩ mô), chứa một tác dụng phụ. Sau đó, lặp lại toán hạng ở giữa sẽ thực hiện tác dụng phụ hai lần. Bỏ qua toán hạng giữa sử dụng giá trị đã được tính mà không có các hiệu ứng không mong muốn khi tính toán lại nó.

Vì vậy, phần mở rộng GCC này không liên quan đến khả năng đọc hoặc tính nhất quán của ngôn ngữ, nó chỉ được thêm vào để tránh các tác dụng phụ không mong muốn.

Sau đó, để cố gắng trả lời câu hỏi ban đầu:

Tại sao không phân công hỗ trợ mở rộng ternary GCC không?

Có thể vì việc truy cập vào giá trị trong điều kiện gán thường không mang lại bất kỳ tác dụng phụ không mong muốn nào. x = x ? : 2; sẽ chỉ có tác dụng phụ không mong muốn nếu x được khai báo là volatile - đọc biến dễ bay hơi là tác dụng phụ. Vì vậy, chỉ sử dụng thực tế tôi có thể thấy với x ?:= 2; sẽ là để ngăn chặn một người nào đó truy cập vào cùng một biến biến động hai lần trong cùng một biểu thức điều kiện.

Và đó là một tính năng có giá trị rất hẹp và có giới hạn. Nó có lẽ sẽ hữu ích trong một số trường hợp hệ thống nhúng đặc biệt nơi bạn đọc các thanh ghi phần cứng trong một hệ thống thời gian thực đòi hỏi ... ngoài việc đó, tôi không thấy sử dụng cho nó.

Tôi cũng không thể tìm thấy bất kỳ nguồn chính thức hoặc chính tắc nào cho biết bất kỳ việc sử dụng nào đối với toán tử?:, Ngoài các tùy chọn kiểu mã hóa truyền thống và chủ quan.

+1

Bất thường có lẽ, chúng tôi đang trong thỏa thuận ;-) K & R quản lý để bắn mình trong bàn chân bằng cách sử dụng một ví dụ mà có lẽ ít rõ ràng hơn so với thay thế. '?:' thực sự có thể làm cho mã ngắn gọn và rõ ràng hơn - ví dụ của chúng tuy nhiên không phải là một trong số chúng! Toán tử cho phép sử dụng một biểu thức trong đó luồng điều khiển nếu không cần thiết - và điều đó đôi khi hữu ích. – Clifford

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