Làm thế nào chính xác? Toán tử làm việc trong C?


10

Tôi có một câu hỏi, làm thế nào trình biên dịch hoạt động trên đoạn mã sau:

#include<stdio.h>

int main(void)
{
  int b=12, c=11;
  int d = (b == c++) ? (c+1) : (c-1);
  printf("d = %i\n", d);
}

Tôi không chắc chắn lý do tại sao kết quả là d = 11.


1
Tại sao bạn không chắc chắn? Bạn còn mong đợi gì nữa và tại sao?
Gerhardh

2
Tôi không nhớ các ngữ nghĩa chính xác liên quan, nhưng bạn có thể đang quan sát hành vi không xác định.
chepner

3
Không, @chepner, có một điểm trình tự sau khi đánh giá tình trạng của một con chim nhạn, trước khi đánh giá lựa chọn thay thế. Điều đó tránh được vectơ UB tôi cho rằng bạn đang nghĩ đến.
John Bollinger

Vâng, tôi không chắc chắn nơi tôi nghĩ trình biên dịch sẽ có một sự lựa chọn.
chepner

Câu trả lời:


6

Trong int d = (b == c++) ? (c+1) : (c-1);:

  • Giá trị của c++là giá trị hiện tại của c, 11. Một cách riêng biệt, cđược tăng lên 12.
  • b == 11là sai, vì blà 12.
  • (b == c++)là sai, (c-1)được sử dụng. Ngoài ra, sự gia tăng củac lên 12 phải được hoàn thành trước thời điểm này.
  • Kể từ c12c-1 là 11.
  • d được khởi tạo cho giá trị đó, 11.

5

Theo tiêu chuẩn C (6.5.15 Toán tử có điều kiện)

4 Toán hạng đầu tiên được ước tính; có một điểm thứ tự giữa đánh giá của nó và đánh giá toán hạng thứ hai hoặc thứ ba (tùy theo đánh giá nào). Toán hạng thứ hai chỉ được ước tính nếu giá trị thứ nhất so sánh bằng 0; toán hạng thứ ba chỉ được ước tính nếu giá trị thứ nhất bằng 0; kết quả là giá trị của toán hạng thứ hai hoặc thứ ba (bất kỳ giá trị nào được ước tính), được chuyển đổi thành loại được mô tả dưới đây.110)

Vì vậy, trong biểu thức khởi tạo của tuyên bố này

int d = (b == c++) ? (c+1) : (c-1);

biến bđược so sánh với giá trị của biến cvì toán tử tăng sau trả về giá trị của toán hạng trước khi tăng nó.

Vì các giá trị không bằng nhau ( bđược đặt thành 12 trong khi cđược đặt thành 11), nên biểu thức con (c-1)được ước tính.

Theo báo giá có một điểm thứ tự sau khi đánh giá tình trạng của người vận hành. Nó có nghĩa là sau khi đánh giá điều kiện ccó giá trị 12sau khi áp dụng toán tử tăng sau cho biến c. Kết quả là biến d được khởi tạo bởi giá trị 1( 12 - 1).


2
Câu trả lời đúng duy nhất - trường hợp cụ thể này phải được trả lời bằng cách đề cập đến điểm thứ tự trong ?:. Bởi vì thông thường trong C, kết hợp ++với các hoạt động khác trên cùng một toán hạng là hành vi không xác định. Và mã này chỉ hoạt động có thể dự đoán được vì ?:có nhiều quy tắc bông tuyết đặc biệt khác nhau.
Lundin

4

Beacuse điều kiện là sai, do đó falsetrường hợp sẽ xảy ra: c-1nhưng vì bạn đã tăng ctrong điều kiện bởi c++vì vậy cbây giờ là 12. Kết quả như vậy 12 - 1 là 11.

EDIT: Điều OP hiểu lầm là sự gia tăng bài đăng.

Vì vậy, những gì thực sự xảy ra là như thế này:

#include<stdio.h>
int main(void)
{
  int b=12, c=11;
  int d;

  if (b == c) { // 12 == 11 ? -> false
    c = c + 1;
    d = c + 1;
  } else { // this executes since condition is false
    c = c + 1; // post increment -> c++ -> c = 12 now
    d = c - 1; // 12 - 1 = 11 -> d = 11
  }
  printf("d = %i\n", d);
}

1
Tôi nghĩ rằng OP đang đề cập đến thứ tự các hoạt động, được đưa ra c++trong điều kiện. Điều kiện là sai, nhưng sau đó giá trị ban đầuc được sử dụng để tính toán c - 1, không phải là phiên bản tăng dần.
chepner

1
Tôi nghĩ rằng chân thành 12 == 11 + 1 đó là sự thật ...
J0S

Nhưng điều đó không đúng vì giá trị c mới được sử dụng hoặc tôi thiếu điểm của bạn?
Eraklon

Tôi nghĩ rằng có thể có một sự hiểu lầm giữa c++++c
ChatterOne

@ N00b c++bài toán -increment. Giá trị c++là 11, với tác dụng phụ của việc chế tạo c == 12. ++csẽ có giá trị là 12.
chepner

4

Được dịch sang câu lệnh if thông thường, mã của bạn sẽ trông như thế này:

int b=12, c=11;
int d;

if (b == c++)
   d = c+1;
else
   d = c-1;

Manh mối ở đây là c được tăng lên sau khi điều kiện được kiểm tra. Vì vậy, bạn nhập elsetrạng thái nhưng c đã có giá trị 12 đó.


1

Tham khảo Toán tử Ternary.

Cú pháp

tình trạng ? value_if_true: value_if_false

Vì vậy, bạn đã viết

int d = (b == c++) ? (c+1) : (c-1);

Trong tình huống này, kết quả sẽ là 11 bởi vì, sau khi kiểm tra, giá trị 'c' được tăng (c + 1 = 12) và chỉ sau đó nó đặt giá trị 'd' là c (12) -1 là 11.

Nếu bạn đã sử dụng, ví dụ:

int d = (b == ++c) ? (c+1) : (c-1);

Giá trị "c" sẽ được tăng lên trước khi kiểm tra câu lệnh, vì vậy nó sẽ đúng và giá trị "d" sẽ là c (12) +1 là 13.

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.