2012-03-17 14 views
14

Mã này có vi phạm nghiêm ngặt răng cưa không?Việc truy cập trường đầu tiên của cấu trúc thông qua diễn viên C có vi phạm nghiêm ngặt răng cưa không?

struct {int x;} a; 
*(int*)&a = 3 

Tóm lại, có hợp pháp khi bỏ qua các loại khác nhau miễn là hoạt động đọc/ghi nguyên thủy có đúng không?

+2

Bảng V có khả năng xuất hiện đầu tiên, vì vậy đây là lãnh thổ UB. – ildjarn

+1

@ildjarn, vtables không tồn tại trong C – bdonlan

+4

@bdonlan: Thẻ này cũng được gắn thẻ 'C++'. ; -] – ildjarn

Trả lời

24

Đầu tiên, nó là hợp pháp để cast trong C. §6.7.2.1/13:

Trong vòng một đối tượng cấu trúc, các thành viên phi bit trường và các đơn vị trong mà cắn-lĩnh vực cư trú có địa chỉ tăng theo thứ tự trong số mà chúng được khai báo. Một con trỏ đến một đối tượng cấu trúc, phù hợp được chuyển đổi, trỏ tới thành viên ban đầu của nó (hoặc nếu thành viên đó là một trường bit , sau đó đến đơn vị mà nó cư trú) và ngược lại. Có thể có phần đệm chưa đặt tên trong một đối tượng kết cấu, nhưng không phải ở số bắt đầu.

Nguyên tắc răng cưa đọc như sau (§6.5/7):

Một đối tượng có trách nhiệm đã được lưu trữ giá trị của nó chỉ được truy cập bởi một biểu thức vế trái có một trong các loại sau đây:

  • loại tương thích với loại đối tượng hiệu quả,
  • phiên bản đủ điều kiện của loại tương thích với loại đối tượng hiệu quả,
  • một loại đó là ký kết hoặc kiểu unsigned tương ứng với loại hiệu quả của đối tượng ,
  • một loại đó là ký kết hoặc kiểu unsigned tương ứng với một phiên bản đủ của loại hiệu quả của đối tượng,
  • loại tổng hợp hoặc liên kết bao gồm một trong các loại được nêu trên trong số các thành viên (bao gồm, đệ quy, thành viên của tổ hợp phụ hoặc công đoàn) hoặc
  • một loại ký tự.

Ở đây bạn sẽ được truy cập nó thông qua con trỏ của một "kiểu tương thích với các loại hiệu quả của đối tượng" và "một loại tổng hợp hoặc công đoàn trong đó bao gồm một trong các loại nói trên giữa các thành viên của nó", vì vậy không vấn đề với răng cưa hoặc. Vì vậy, trong C, nó thực sự là hoàn toàn hợp pháp để truy cập vào thành viên đầu tiên của một cấu trúc bằng cách đúc con trỏ tới cấu trúc theo kiểu của thành viên được đề cập.

Trong C++, tuy nhiên, bạn thường sẽ tìm thấy vtables và những thứ khác khi bắt đầu đối tượng C++. Tuy nhiên, trong trường hợp cụ thể của bạn, cấu trúc của bạn là bố trí chuẩn, và do đó điều này được cho phép rõ ràng (§9.2/20 trong n3290, nhờ Luc Danton! - C++ 03 dường như có quy tắc tương tự, được thể hiện bằng các đối tượng POD) .

+0

C++ chắc chắn sẽ không giấy trên sự hiện diện của một vtable, nhưng tôi chỉ áp dụng điều này trong trường hợp không có sự kỳ quặc như vậy. –

+0

@Geoffrey: "* trường hợp không có sự kỳ quặc như vậy *". Aka loại có thể sao chép một cách đáng kể? Aka một cái gì đó bạn nên đã đề cập trong câu hỏi của bạn? – ildjarn

+1

Vâng, câu hỏi đề cập rằng cấu trúc có một trường int duy nhất, trong số những thứ khác ngụ ý không có vtable. Tiêu đề đã khá dài dòng. –

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