Mục đích của [1] này ở cuối khai báo struct là gì?


96

Tôi đã dò tìm các tệp tiêu đề của bộ vi điều khiển MSP430 của mình và tôi gặp phải vấn đề này trong <setjmp.h>:

/* r3 does not have to be saved */
typedef struct
{
    uint32_t __j_pc; /* return address */
    uint32_t __j_sp; /* r1 stack pointer */
    uint32_t __j_sr; /* r2 status register */
    uint32_t __j_r4;
    uint32_t __j_r5;
    uint32_t __j_r6;
    uint32_t __j_r7;
    uint32_t __j_r8;
    uint32_t __j_r9;
    uint32_t __j_r10;
    uint32_t __j_r11;
} jmp_buf[1]; /* size = 20 bytes */

Tôi hiểu rằng nó khai báo một cấu trúc ẩn danh và typedef là nó jmp_buf, nhưng tôi không thể tìm ra nó để làm gì [1]. Tôi biết nó tuyên bố jmp_buflà một mảng có một thành viên (của cấu trúc ẩn danh này), nhưng tôi không thể tưởng tượng nó được sử dụng để làm gì. Có ý kiến ​​gì không?


5
Có thể làm gì đó với việc phân rã thành con trỏ?
Elazar

3
Các bình luận cuối cùng dường như hoàn toàn sai ...
R .. GitHub DỪNG GIÚP ICE

Câu trả lời:


115

Đây là một thủ thuật phổ biến để tạo một "kiểu tham chiếu" trong C, trong đó việc sử dụng nó làm đối số hàm khiến mảng phần tử đơn lẻ bị suy giảm thành một con trỏ tới phần tử đầu tiên của nó mà người lập trình không cần phải sử dụng &toán tử một cách rõ ràng để lấy địa chỉ của nó. Khi được khai báo, đó là kiểu ngăn xếp thực (không cần cấp phát động), nhưng khi được truyền dưới dạng đối số, hàm được gọi sẽ nhận một con trỏ tới nó, không phải bản sao, vì vậy nó được truyền với giá rẻ (và có thể bị thay đổi bởi hàm được gọi nếu không const).

GMP sử dụng thủ thuật tương tự với mpz_tkiểu của nó , và nó rất quan trọng ở đó, bởi vì cấu trúc quản lý một con trỏ tới bộ nhớ được cấp phát động; các mpz_initchức năng dựa vào nhận được một con trỏ đến cấu trúc, không phải là một bản sao của nó, hoặc nó không thể khởi tạo nó ở tất cả. Tương tự, nhiều hoạt động có thể thay đổi kích thước bộ nhớ được cấp phát động và điều đó sẽ không hoạt động nếu chúng không thể thay đổi cấu trúc của người gọi.


12
Nó cũng ngăn chặn việc sao chép qua =.
melpomene

11
Kinh quá. Tôi sẽ chấp nhận câu trả lời này khi thời gian tối thiểu trôi qua. Cảm ơn bạn đã giúp đỡ!
Alexander - Phục hồi Monica

3
@Alexander: Nó không quá thô thiển khi được gói gọn qua một cái typedefnhư thế này. Vâng, thực hiện điều này đặc biệt sẽ hơi khủng khiếp, nhưng nếu bạn có loại không rõ ràng, nơi người dùng API không bao giờ cần phải suy nghĩ về ngữ nghĩa tham chiếu so với không tham chiếu (nó luôn phải chuyển qua tham chiếu), đó là một cách hợp lý bổ sung ngữ nghĩa tham chiếu tự động cho một ngôn ngữ thiếu nó. Nó thậm chí còn hoạt động nếu người dùng viết các API của riêng họ nhận kiểu, bởi vì trong C, việc khai báo bạn chấp nhận một mảng làm đối số thực sự có nghĩa là bạn chấp nhận một con trỏ; mọi thứ "chỉ hoạt động".
ShadowRanger

4
@ShadowRanger Đó là một thủ thuật thông minh, nhưng ... otherwise lacks itđiều đó thật khó hiểu. Những hạn chế của C, không phải là bản thân workaround
Alexander - Khôi phục Monica

34
IMO nó thật kinh khủng. Lần đầu tiên làm việc với GMP, tôi không thể hiểu nó hoạt động như thế nào vì các con số dường như được chuyển theo giá trị. Tôi đã phải tìm hiểu các tiêu đề GMP để giải đáp nó. Nó chỉ bay vào mặt những người thực sự biết C rồi. Sau đó, bạn phải theo dõi tinh thần xem các tham số nào được truyền theo giá trị và tham chiếu nào thay vì chỉ tìm kiếm *trong mã.
MM
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.