2016-01-19 19 views
6

Hãy xem xét đoạn mã sau:Pointer arithmetics trên các loại phi mảng

struct Blob { 
    double x, y, z; 
} blob; 

char* s = reinterpret_cast<char*>(&blob); 
s[2] = 'A'; 

Giả sử rằng sizeof (double) là 8, thì hành vi undefined mã này kích hoạt?

+4

Điều này thậm chí sẽ không biên dịch mà không có dàn diễn viên. – dgross

+0

Đây có phải là C? Trong C++, điều này sẽ không biên dịch. – Bathsheba

+1

Đây không phải là hợp pháp C hoặc C++, bạn cần một diễn viên. Một khi bạn có một diễn viên, điều này là hợp pháp và được xác định rõ. Tất nhiên bất cứ điều gì có thể xảy ra nếu bạn cố gắng truy cập blob.x sau đó. –

Trả lời

5

Trích dẫn từ N4140 (khoảng C++ 14):

3,9 loại [basic.types]

2 Đối với bất kỳ đối tượng (trừ một subobject cơ sở-class) của trivially copyable loại T, cho dù đối tượng có chứa giá trị hợp lệ của loại T, các byte cơ bản (1.7) tạo thành đối tượng có thể được sao chép vào mảng char hoặc unsigned char. Nếu nội dung của mảng char hoặc unsigned char được sao chép trở lại vào đối tượng, đối tượng sau đó sẽ giữ giá trị ban đầu của nó.

42) Bằng cách sử dụng, ví dụ: chức năng thư viện (17.6.1.2) std::memcpy hoặc std::memmove.

3 Đối với bất kỳ loại trivially copyable T, nếu hai con trỏ đến T điểm đến khác biệt T đối tượng obj1obj2, là nơi chẳng obj1 cũng không obj2 là một subobject cơ sở hạng nhất, nếu các byte cơ bản (1.7) chiếm obj1 được sao chép vào obj2, obj2 sau đó sẽ giữ nguyên giá trị như obj1. [Ví dụ: ...]

43) Bằng cách sử dụng, ví dụ: chức năng thư viện (17.6.1.2) std::memcpy hoặc std::memmove.

này, về nguyên tắc, cho phép chuyển nhượng trực tiếp đến s[2] nếu bạn dành vị trí đó gán để s[2] được gián tiếp yêu cầu phải tương đương với sao chép tất cả các số khác Blob vào một mảng mà chỉ xảy ra được bytewise giống hệt nhau ngoại trừ đối với byte thứ ba và sao chép nó vào Blob: bạn không chỉ định cho s[0], s[1], v.v ... Đối với các loại có thể sao chép một cách trivially bao gồm char, tương đương với đặt chúng thành giá trị chính xác mà chúng đã có. hiệu ứng.

Tuy nhiên, nếu cách duy nhất để có được s[2] == 'A' là do thao tác bộ nhớ, sau đó một đối số hợp lệ cũng có thể được thực hiện rằng những gì bạn đang sao chép lại vào Blob bạn không các byte tiềm ẩn mà tạo thành bất kỳ trước Blob . Trong trường hợp đó, về mặt kỹ thuật, hành vi sẽ không được xác định bởi thiếu sót.

Tôi thực sự nghi ngờ, đặc biệt là khi "đối tượng có giữ giá trị hợp lệ của loại T" nhận xét hay không, ý định đó được cho phép.

+0

Nhận xét không dành cho thảo luận mở rộng; cuộc hội thoại này đã được [chuyển sang trò chuyện] (http://chat.stackoverflow.com/rooms/101136/discussion-on-answer-by-hvd-pointer-arithmetics-on-non-array-types). –

0

Chương 3.10 của tiêu chuẩn dường như cho phép trường hợp cụ thể đó, giả định rằng "truy cập giá trị được lưu trữ" có nghĩa là "đọc hoặc ghi", điều không rõ ràng.

3.10-10

Nếu một chương trình cố gắng truy cập các giá trị được lưu trữ của một đối tượng thông qua một glvalue của khác hơn là một trong các loại sau đây hành vi này là unde fi định nghĩa:

- (10.1) loại động của đối tượng,

- (10.2) phiên bản cv-quali của loại động của đối tượng,

- (10.3) một loại tương tự (như de fi định nghĩa trong 4.4) với các loại động của đối tượng ,

- (10.4) một loại đó là ký kết hoặc kiểu unsigned tương ứng với loại năng động của đối tượng,

- (10.5) một kiểu đó là ký kết hoặc kiểu unsigned tương ứng với một phiên bản fi ed cv-quali của các loại động của đối tượng,

- (10.6) một tổng hợp hoặc công đoàn kiểu đó bao gồm một trong các loại nói trên trong số các thành phần hoặc thành phần dữ liệu phi tuyến tính (bao gồm, đệ quy, một yếu tố hoặc thành viên dữ liệu không tĩnh của một subaggregate hoặc công đoàn chứa),

- (10.7) một loại đó là một (có thể cv-quali fi ed) kiểu lớp cơ sở của loại động của đối tượng,

- (10.8) một loại char hoặc unsigned char.

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