22

Trong another answer nó được tuyên bố rằng trước khi C++ 11, nơi i là một int, sau đó sử dụng các biểu thức:Không * & + + tôi gây ra hành vi không xác định trong C++ 03?

*&++i 

gây ra hành vi không xác định. Điều này có đúng không?

Câu trả lời khác có một chút thảo luận trong nhận xét nhưng có vẻ không thuyết phục.

+1

Trong câu trả lời đó, các ý kiến ​​rất hiểu biết "Johannes Schaub - litb" mà ông cho rằng đó là một tuyên bố không đúng sự thật. Và không có phản ứng. –

+2

@DrewDormann James Kanze cũng rất am hiểu –

+2

'* & i' sẽ hoàn toàn hợp lệ và' + + i' trả về tham chiếu đến 'i' vì vậy tôi không thấy vấn đề ... –

Trả lời

0

Tôi nghĩ câu hỏi chỉ có ý nghĩa nếu chúng ta đối phó với các biểu hiện:

i = *&++i; 

Các trích dẫn có liên quan trong tiêu chuẩn C++ 03 sẽ là [expr]/4:

Trừ trong đó lưu ý, thứ tự đánh giá các toán hạng của các toán tử riêng lẻ và các biểu thức con của các biểu thức riêng lẻ và thứ tự mà các tác dụng phụ xảy ra, không được chỉ định. Giữa và điểm chuỗi tiếp theo đối tượng vô hướng phải có giá trị được lưu trữ được sửa đổi nhiều nhất một lần bằng cách đánh giá của biểu thức. Hơn nữa, giá trị trước chỉ được truy cập để xác định giá trị được lưu trữ. Các yêu cầu của đoạn này phải được đáp ứng cho mỗi thứ tự cho phép của các biểu thức con của biểu thức đầy đủ ; nếu không hành vi là không xác định.

i = ++i + 1; // the behavior is unspecified 

Chúng tôi chỉ có thể so sánh trình tự của i = *&++i vs i = ++i + 1 để xác định rằng các quy tắc tương tự gây nên cả hai được xác định. Họ là cả hai câu lệnh có dạng:

i = f(++i); 

Đối với bất kỳ chức năng f, cách đọc của i ở phía bên trái và tác dụng phụ của ++i ở phía bên tay phải không được lập trình tự tương đối với nhau khác. Do đó, hành vi không xác định.

7

Không có ý nghĩa gì khi tự hỏi liệu có *&++i có UB không. Hội nghị không nhất thiết truy cập vào giá trị được lưu trữ (trước hoặc mới) của i, như bạn có thể thấy bằng cách sử dụng biểu thức khởi tạo này để tham chiếu. Chỉ khi một chuyển đổi rvalue là có liên quan (sử dụng trong bối cảnh đó) là có bất kỳ câu hỏi để thảo luận ở tất cả. Và sau đó, vì chúng tôi có thể sử dụng giá trị của ++i, chúng tôi có thể sử dụng giá trị *&++i với chính xác các lời nhắc tương tự như đối với ++i.

Câu hỏi ban đầu có liên quan về cơ bản là i = ++i, tương tự như i = *&++i. Đó là hành vi không xác định trong C++ 03, do i được sửa đổi hai lần giữa các điểm chuỗi và được xác định rõ trong C++ 11, do các tác dụng phụ của toán tử gán được sắp xếp sau khi tính toán giá trị của bên trái và bên tay phải. Có lẽ có liên quan cần lưu ý rằng các tiêu chuẩn phi quy định ví dụ trong tiêu chuẩn C++ 98 và C++ 03, không chính xác, mô tả một số trường hợp Hành vi không xác định chính thức chỉ là hành vi không xác định. Vì vậy, ý định không hoàn toàn rõ ràng, tất cả các con đường trở lại.Một nguyên tắc nhỏ là chỉ đơn giản là không dựa vào các trường hợp góc tối nghĩa của ngôn ngữ đó, để tránh chúng: người ta không cần phải là luật sư ngôn ngữ để hiểu mã & hellip;

+0

AFAICS 'i = ++ i' được xác định rõ trong C++ 03, như được hiển thị chính xác bởi câu trả lời được chấp nhận trong Q/A được liên kết. – Columbo

+1

@Columbo: Nếu bạn rất tử tế để tóm tắt hoặc báo giá, tôi sẽ cố gắng bác bỏ khiếu nại bạn đã thấy. Tôi không thể tìm thấy nó, xin lỗi. Tuy nhiên, vì điều này rất đơn giản trong C++ 03, tuyệt đối không bao giờ sửa đổi hai lần hoặc nhiều hơn giữa các điểm chuỗi, có thể bạn không cần nhiều hơn thế? C++ 03 §5/4 trong [expr]: “Giữa và điểm chuỗi tiếp theo đối tượng vô hướng sẽ có giá trị được lưu trữ của nó được sửa đổi nhiều nhất một lần bằng cách đánh giá biểu thức.” –

+0

Dường như tôi hiểu sai khái niệm về chuỗi điểm hoàn toàn. Tôi nghĩ rằng các đoạn văn được trích dẫn bởi [câu trả lời] này (http://stackoverflow.com/a/17403467/3647361) sẽ đủ để chứng minh sự xác định rõ ràng của biểu thức đó. Nhưng không nơi nào có thể nói về các điểm chuỗi ở đó (tôi nghĩ rằng sự tồn tại của chúng là * ngụ ý *, nhưng điều đó có vẻ sai lầm trong nhận thức). Trong thực tế, có vẻ như khi chúng xuất hiện rất hiếm khi chúng xác định được rất nhiều mã khái niệm tốt để gọi UB. May mắn thay đã được sửa trong C++ 11. – Columbo

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