cuốn sách gpt4 ai đã làm

Quy tắc bí danh đã ký/không dấu có hoạt động như mong đợi không?

In lại Tác giả: Taklimakan Thời gian cập nhật: 2023-11-03 00:46:29 25 4
mua khóa gpt4 Nike

Đây là dạng C++17 của quy tắc ([basic.lval]/8), nhưng nó trông tương tự trong các tiêu chuẩn khác ("lvalue" thay vì "glvalue" trong C++98):

8 Nếu một chương trình cố gắng truy cập giá trị được lưu trữ của một đối tượng thông qua một giá trị không phải là một trong các loại sau thì hành vi đó không được xác định:

(8.4) - một loại là loại có dấu hoặc không dấu tương ứng với loại động của đối tượng

Quy tắc này nghe có vẻ giống như "trừ khi bạn làm X, bạn sẽ nhận được UB", nhưng điều đó không có nghĩa là nếu bạn làm là UB có điều kiện hoặc vô điều kiện, tùy thuộc vào phiên bản của tiêu chuẩn.

Chúng ta hãy xem đoạn mã sau:

int tôi = -1;
chưa ký j = reinterpret_cast(i);

Hành vi của mã này là gì?

C++98 và C++11

[expr.reinterpret.cast]/10 (/11 trong C++11) (nhấn mạnh của tôi):

Một biểu thức giá trị của loại T1 có thể được chuyển thành loại “tham chiếu đến T2” nếu một biểu thức thuộc loại “con trỏ tới T1” có thể được chuyển đổi rõ ràng thành loại “con trỏ tới T2” bằng cách sử dụng reinterpret_cast. (x) có tác dụng tương tự như chuyển đổi *reinterpret_cast(&x) với các toán tử & và * tích hợp. Kết quả là một giá trị tham chiếu đến cùng một đối tượng với giá trị nguồn, nhưng với một loại khác.

所以 reinterpret_cast(i)giá trị đề cập đến int对象 Tôi , nhưng với được sử dụngkiểu. Việc khởi tạo yêu cầu khởi tạo giá trị của một biểu thức, có nghĩa chính thức là áp dụng chuyển đổi lvalue-to-rvalue cho lvalue.

[conv.lval]/1:

Một giá trị của không có chức năng, không có mảng loại T có thể được chuyển đổi thành giá trịNếu T là loại không đầy đủ thì chương trình yêu cầu chuyển đổi này sẽ không được định dạng đúng. Nếu đối tượng mà lvalue đề cập đến không phải là đối tượng thuộc loại T và không phải là đối tượng thuộc loại bắt nguồn từ T hoặc nếu đối tượng chưa được khởi tạo, một chương trình yêu cầu chuyển đổi này có hành vi không xác định.

giá trị của chúng tôi không dấuloại không được tham chiếu không dấu Loại đối tượng có nghĩa là hành vi không được xác định.

C++14 và C++17

Trong các tiêu chuẩn này, mọi thứ phức tạp hơn một chút nhưng các quy tắc lại được nới lỏng một chút. [expr.reinterpret.cast]/11 cũng nói như vậy:

Kết quả đề cập đến cùng một đối tượng với giá trị nguồn, nhưng với loại được chỉ định.

Ngôn ngữ xúc phạm liên quan đến UB đã bị xóa khỏi [conv.lval]/1:

Một giá trị của không có chức năng, không có mảng loại T có thể được chuyển đổi thành một giá trịNếu T là loại không đầy đủ thì chương trình yêu cầu chuyển đổi này sẽ không được định dạng đúng. Nếu T là loại không phải loại, thì loại giá trị là phiên bản cv không đủ tiêu chuẩn của T. Ngược lại, loại giá trị là T.

Nhưng chuyển đổi L-to-R đọc được giá trị nào? [conv.lval]/(2.6) (/(3.4) trong C++17) trả lời câu hỏi này:

… giá trị chứa trong đối tượng được biểu thị bằng glvalue là kết quả của giá trị

không dấugiá trị reinterpret_cast(i)thể hiện Tôi intGiá trị là -1 Các giá trị được tạo ra bởi việc chuyển đổi L-to-R của các đối tượng là không dấukiểu. [expr]/4 đã nói:

Nếu trong quá trình đánh giá một biểu thức, kết quả không được xác định về mặt toán học hoặc không nằm trong phạm vi giá trị biểu thị cho loại của nó thì hành vi đó không được xác định.

-1Tuyệt đối không có ở đây không dấu Loại biểu thức giá trị nằm trong phạm vi giá trị có thể biểu thị, do đó hành vi không được xác định.

nếu như Tôi Đối tượng hành vi sẽ được xác định để chứa các giá trị trong phạm vi [0, INT_MAX].

Lý do tương tự áp dụng cho không dấu tình huống. vượt qua int Các đối tượng truy cập thêm giá trị. Đây là UB trong C++98 và C++11 và UB trong C++14 và C++17, trừ khi giá trị của đối tượng nằm trong phạm vi [0, INT_MAX].

Vì vậy, trái với niềm tin phổ biến, quy tắc bí danh này cho phép các đối tượng được diễn giải lại dưới dạng chứa các giá trị của các loại có dấu/không dấu tương ứng, nó không cho phép điều này. Các đối tượng thuộc loại có dấu và không dấu có cùng cách biểu diễn cho các giá trị trong phạm vi [0, INT_MAX] ("Phạm vi giá trị không âm của loại số nguyên có dấu là phạm vi con của loại số nguyên không dấu tương ứng, biểu thị rằng cùng một giá trị ở hai loại là giống nhau", [basic.fundamental]/3 trong C++17). Thật khó để gọi quyền truy cập này là "diễn giải lại", chứ chưa nói đến việc đây là UB vô điều kiện trước C++ 14.

Vậy mục đích của quy tắc ([basic.lval]/(8.4)) là gì?

câu trả lời hay nhất

Đây là báo cáo lỗi 2214 Chủ đề nó nói:

Phần: 6.9.1 [basic.fundamental] Trạng thái: C++17 Người gửi: Richard Smith Ngày: 15-12-2015

[Được thông qua tại cuộc họp tháng 2/tháng 3 năm 2017.]

Theo 6.9.1 [basic.fundamental] đoạn 3,

Phạm vi các giá trị không âm của loại số nguyên có dấu là một phạm vi con của loại số nguyên không dấu tương ứng và cách biểu diễn giá trị của từng loại có dấu/không dấu tương ứng sẽ giống nhau. (Đây là cách diễn đạt trong phiên bản C++11 và C++14, mặc dù số đoạn văn có thể khác nhau -- nm)

Phương pháp viết tương ứng cho C11 là,

Phạm vi các giá trị không âm của loại số nguyên có dấu là một phạm vi con của loại số nguyên không dấu tương ứng và cách biểu diễn cùng một giá trị trong mỗi loại là như nhau.

Từ ngữ C được cho là rõ ràng hơn, nhưng nó làm mất đi hàm ý của từ ngữ C++ rằng bit dấu của loại có dấu là một phần của biểu diễn giá trị của loại không dấu tương ứng.

Nghị quyết đề xuất (tháng 1 năm 2017):

Thay đổi đoạn 3 của 6.9.1 [basic.fundamental] như sau:

...Các kiểu số nguyên không dấu tiêu chuẩn và mở rộng được gọi chung là các kiểu số nguyên không dấu. Phạm vi giá trị không âm của kiểu số nguyên có dấu là một tập con của kiểu số nguyên không dấu tương ứng. sự biểu diễn của cùng một giá trị ở mỗi loại trong hai loại là như nhauvà biểu diễn giá trị của từng loại có dấu/không dấu tương ứng sẽ giống nhau. Các loại số nguyên có dấu tiêu chuẩn...

Vì vậy, đó rõ ràng là ý định từ lâu. C++17 vừa sửa từ ngữ.

Các tiêu chuẩn C và C++ không bao giờ nhằm mục đích cho phép các giá trị âm được diễn giải lại dưới dạng không dấu hoặc ngược lại. Có một số cách biểu diễn số nguyên có dấu trong tự nhiên (ví dụ: phần bù một, phần bù hai, dấu và độ lớn) và tiêu chuẩn không bắt buộc bất kỳ cách biểu diễn nào trong số đó, vì vậy nó không thể chỉ ra tác động của việc diễn giải lại như vậy. họCó thểĐịnh nghĩa này được thực hiện, nhưng với khả năng biểu diễn bẫy, điều này không mang lại lợi ích thực sự. "Thực hiện những hậu quả hoặc cạm bẫy đã xác định" cũng tốt như "không xác định".

Giới thiệu về c++ - Quy tắc bí danh đã ký/không dấu có hoạt động như mong đợi không? , chúng tôi đã tìm thấy một câu hỏi tương tự trên Stack Overflow: https://stackoverflow.com/questions/54085710/

25 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress