2017-09-05 27 views
20

Tôi có một cấu trúc quy định tại .hLàm cách nào để làm cho gcc cảnh báo cấu trúc không xác định?

struct buf_stats { 
    // *** 
}; 

sau đó trong file .c

struct buf_stats *bs = malloc(sizeof(struct buf_states*)) ; 

nơi buf_states là một lỗi đánh máy.

nhưng gcc không cảnh báo tôi, mặc dù tôi đã sử dụng -Wall

và lỗi này/typo chi phí cho tôi 3 giờ để tìm hiểu.

Làm cách nào để làm cho gcc cảnh báo cấu trúc không xác định như thế này?

+0

Heh? Thông báo lỗi bạn nhận được là gì? –

+0

@SouravGhosh Tôi nghĩ rằng KHÔNG có thông báo lỗi và đó là những gì OP đang hỏi về. – Yunnosch

+17

Dou muốn malloc đủ không gian cho một con trỏ? Trình biên dịch không thực sự cần kích thước của những gì nó trỏ đến cho điều đó. Hoặc bạn có muốn malloc cho một cấu trúc? Trong trường hợp đó, có một lỗi đánh máy khác, thứ hai '*'. – Yunnosch

Trả lời

36

Trong mã của bạn

struct buf_stats *bs = malloc(sizeof(struct buf_states*)) ; 

là sai vì nhiều lý do, như

  • Bạn đang sử dụng một loại không xác định (như bạn nói)
  • Bạn đang phân bổ cách ít bộ nhớ (phân bổ cho a pointer-to-type thay vì loại)

Nhưng bạn biên dịch không thể giúp gì nhiều trong _this_case cho loại đặc biệt này của lỗi, như

  • một con trỏ đến (bất kỳ) gõ vào một nền tảng có kích thước xác định, cho rằng cấu trúc (I E loại biến mà nó trỏ đến) không cần phải hoàn thành (được xác định). Đây là lý do chúng ta có thể có cấu trúc tự tham khảo, đúng không?

  • malloc() không có ý tưởng về loại biến mục tiêu. Nó chỉ đọc đối số cho kích thước cần thiết, trả về một con trỏ (có kiểu là void *) tới bộ nhớ được phân bổ và khi gán, được thay đổi thành kiểu đích. Không thể tính số không khớp ở kích thước mục tiêu (loại) với kích thước bộ nhớ được phân bổ.

cách thuận tiện nhất và đơn giản nhất để tránh những loại sai lầm là, không sử dụng các loại mã hóa cứng trực tiếp như các toán hạng của sizeof, đúng hơn, sử dụng tài liệu tham khảo khác nhau.

Something như

struct buf_stats *bs = malloc(sizeof *bs) ; // you can write that as (sizeof (*bs)) also 
              // sizeof *bs === sizeof (struct buf_stats) 

tương đương với

struct buf_stats *bs = malloc(sizeof(struct buf_stats)) ; 

nhưng là mạnh mẽ hơn và ít dễ bị lỗi.

Ghi chú:

  1. Bạn không cần ngoặc nếu toán hạng không phải là một tên loại.
  2. Tuyên bố này không cần bất kỳ sửa đổi nào khi thay đổi loại biến mục tiêu bs.
+2

Có lẽ đáng nói đến là '*' trong 'sizeof * bs' không * không * biểu thị một con trỏ, nhưng là một tham số. 'bs' là một con trỏ, vì vậy' * bs' là giá trị struct, mà sizeof được gọi ở đây. – tomsmeding

+0

Ngoài ra, chú thích 1 là tốt vì nó thực sự sẽ tạo ra một lỗi tương tự như những gì @Sato đang yêu cầu, trong trường hợp 'struct but_stats' chưa hoàn thành, hoặc' bs' là tên kiểu thay vì tên biến . – Leushenko

+1

Tôi đã nhìn thấy nền tảng mà con trỏ đến những thứ có kích thước khác nhau có kích thước khác nhau. (void * là con trỏ lớn nhất cho bất kỳ kiểu dữ liệu nào để thực hiện công việc này.) – Joshua

17

Bạn không thể. Sử dụng biểu thức như struct foo * (con trỏ đến một số loại cấu trúc) tuyên bố cấu trúc đó là loại không đầy đủ. Kích thước không được biết, nhưng không cần thiết cho kích thước của con trỏ .

Điều đó nói rằng, các mã trông sai, như bạn cần kích thước của struct (không kích thước của con trỏ), vì vậy với đoạn mã sau:

struct buf_stats *bs = malloc(sizeof(struct buf_states)); 

bạn sẽ nhận được một lỗi.

Có một cách tốt hơn để viết mã như:

struct buf_stats *bs = malloc(sizeof *bs); 

Khái niệm *bs có đúng loại cho sizeof, ngay cả khi sau này bạn thay đổi kiểu.

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