Là `(i) = 1` bất hợp pháp trong tiêu chuẩn C?


8

Tôi đang viết một trình biên dịch C tuân theo tiêu chuẩn này và nếu tôi phân tích các câu như thế này:

int i;
(i) = 1;

trình biên dịch của tôi sẽ báo cáo một lỗi chỉ ra đó (i)là một giá trị và không nên gán.

Tôi đã kiểm tra mã và các quy tắc và tìm thấy điều này: trong ngữ nghĩa biểu thức gán:

Một toán tử gán sẽ có một giá trị có thể sửa đổi là toán hạng bên trái của nó.

Một biểu thức gán có giá trị của toán hạng bên trái sau khi gán, nhưng không phải là một giá trị.

Trong trường hợp của tôi, có hai biểu thức gán: (i) = 1itrong ngoặc đơn. Vì vậy, (i)nên là một giá trị.

Vì vậy, câu hỏi của tôi là: Có (i) = 1bất hợp pháp trong tiêu chuẩn C này?


1
Nó vẫn là một giá trị, các dấu ngoặc đơn không thay đổi điều đó.
Jeff Mercado

1
Xin chào, xin vui lòng chỉ ra quy tắc nào trong tiêu chuẩn nếu nó hợp pháp, Trình biên dịch của tôi gắn quy tắc chặt chẽ.
ravenisadesk

itrong ngoặc đơn không phải là biểu thức gán. Biểu thức chuyển nhượng không có nghĩa là "biểu thức liên quan đến một nhiệm vụ" hoặc bất cứ điều gì khác (i)sẽ đủ điều kiện. Biểu thức chuyển nhượng là bài tập .
user2357112 hỗ trợ Monica

@ user2357112 ilà một biểu hiện chuyển nhượng, cây AST được EXPRESSION-> ASSIGNMENT_EXPRESSION-> CONDITIONAL_EXPRESSION-> LOGICAL_OR_EXPRESSION-> CAST_EXPRESSION-> UNARY_EXPRESSION-> POSTFIX_EXPRESSION-> PRIMARY_EXPRESSION-> IDENTIFIER
ravenisadesk

@reavenisadesk: Một assignment-expressionngữ pháp nonterminal không giống với biểu thức gán. Một cách thô bạo, an assignment-expressionlà một biểu thức gán hoặc bất cứ thứ gì có độ ưu tiên cao hơn.
user2357112 hỗ trợ Monica

Câu trả lời:


8

Để trích dẫn n1570 (bản dự thảo tiêu chuẩn C11 cuối cùng trước khi xuất bản):

6.5.1 Biểu thức chính (nhấn mạnh của tôi)

5 Một biểu thức được ngoặc đơn là một biểu thức chính. Loại và giá trị của nó giống hệt với biểu thức không được liên kết . Nó là một giá trị, một chỉ định hàm hoặc một biểu thức void nếu biểu thức không được liên kết tương ứng là một lvalue, một chỉ định hàm hoặc một biểu thức void.

ilà một giá trị, vì vậy theo như trên là như vậy (i). Và để trả lời câu hỏi của bạn, biểu thức (i) = 1là hợp lệ C.


Tôi có vấn đề, chúng ta hãy xem các BNF của biểu thức chính ngoặc: ( expression ), vì vậy các loại và giá trị là giống hệt nhau để expression, và expressionlà một assignment expression, và assignment expressionlà một primary expression, đơn giản, isẽ được điều trị như assignment expressioncuối cùng, vì vậy nó nên làm theo các quy tắc của assignment expressiontại cuối cùng, vì vậy nó nên là một giá trị, tôi nghĩ.
ravenisadesk

1
@reavenisadesk - Ngoại trừ nó khá rõ ràng, màu đen trắng, không phải là một giá trị. Hay bạn đang nói i = 1là không hợp lệ quá?
Người kể chuyện - Unslander Monica

Tôi nghĩ i = 1là hợp lệ vì điều này : assignment-expression: unary-expression assignment-operator assignment-expression, trong trường hợp i = 1, tôi được coi là unary-expression, đó là một giá trị, không assignment expression, tôi nghĩ rằng i = 1ví dụ của bạn không phải là trường hợp.
ravenisadesk

2
@reavenisadesk: Ngữ pháp không nói những gì là giá trị hoặc giá trị. Các ngữ nghĩa làm. Đối với một biểu thức gán, C 6.5.16 3 (ngay dưới tiêu đề Sem Semantics ') cho biết một biểu thức gán (là cụm từ mô tả biểu thức được tạo bằng toán tử gán, không phải là biểu thức gán , là mã thông báo trong ngữ pháp ) không phải là một giá trị. Nó không nói mã thông báo ngữ pháp biểu thức chuyển nhượng không phải là một giá trị.
Eric Postpischil

1
@reavenisadesk - Eric giải thích nó hùng hồn hơn nhiều so với tôi có thể. Hơn nữa, dường như với tôi bạn đang chọn (i)bất công ở đây. Điểm giống nhau về ngữ nghĩa áp dụng cho mọi loại biểu thức.
Người kể chuyện - Unslander Monica

0

StoryTeller đã giải thích ở đâu trong tiêu chuẩn tại sao cho ví dụ của bạn, biểu thức (i)vẫn là một giá trị, nhưng tôi tin rằng bạn đang bị treo lên thông số kỹ thuật mà không có lý do nào cho phép tôi cố gắng giải quyết mối quan tâm của bạn.

Tôi đã kiểm tra mã và các quy tắc và tìm thấy điều này: trong ngữ nghĩa biểu thức gán:

Một toán tử gán sẽ có một giá trị có thể sửa đổi là toán hạng bên trái của nó.

Một biểu thức gán có giá trị của toán hạng bên trái sau khi gán, nhưng không phải là một giá trị.

Toàn bộ trích dẫn đề cập đến toàn bộ biểu thức chuyển nhượng, không phải là lhs hoặc rhs.

"Một toán tử gán sẽ có một giá trị có thể sửa đổi là toán hạng bên trái của nó." nói rằng các lhs phải là một giá trị có thể sửa đổi.

"Một biểu thức gán có giá trị của toán hạng bên trái sau khi gán, nhưng không phải là giá trị." nói rằng toàn bộ biểu thức gán chính nó là kết quả có giá trị của lhs và bản thân nó là một giá trị.

Vì vậy, những điều sau đây đều đúng:

int i;
  i <- modifiable lvalue

(i) = 1;
  (i) <- modifiable lvalue (per StoryTeller's answer)
  1 <- rvalue
  ((i) = 1) <- rvalue

Tại sao điều này có ý nghĩa? Hãy xem xét những điều sau đây:

int i = 0, j = 0, k = 0;
i = j = k = 1;
// parsed as `i = (j = (k = 1))`
// the expression `k = 1` has the value `1` and is an rvalue
// the expression `j = (k = 1)` has the value `1` and is an rvalue

(i = 2) = 3;
// is invalid, the expression `i = 2` is an rvalue, but it may not be the lhs of the assignment

Trong trường hợp của tôi, có hai biểu thức gán: (i) = 1itrong ngoặc đơn. Vì vậy, (i)nên là một giá trị.

Không, điều đó không chính xác. (i) = 1là biểu thức gán duy nhất. Có hai biểu thức con (một định danh được ngoặc đơn (i)và một hằng số 1).


0

Câu trả lời này được lấy cảm hứng từ @Eric Postpischil.

sản xuất của a assignment-expressionlà:

<assignment-expression> ::= <conditional-expression>
                          | <unary-expression> <assignment-operator> <assignment-expression>

trong tiêu chuẩn, assignment expressioncụ thể có nghĩa là biểu thức với toán tử gán. Vì thế:

<conditional-expression> is not an assignment expression
<unary-expression> <assignment-operator> <assignment-expression> is an assignment expresssion

vì vậy quy tắc:

Một biểu thức gán có giá trị của toán hạng bên trái sau khi gán, nhưng không phải là một giá trị.

chỉ phù hợp cho sản xuất <unary-expression> <assignment-operator> <assignment-expression>, không cho<conditional-expression>

trong ví dụ (i) =1, ilà một <assignment-expression>nhưng không phải là một assignment expression, <conditional-expression>vì vậy nó là một lvaule vì vậy (i)là một giá trị.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.