Hãy xem xét các chương trình ví dụ sau:Chuyển đổi một con trỏ đến một cấu trúc thành viên đầu tiên của mình
#include <stdio.h>
struct base {
int a, b;
};
struct embedded {
struct base base;
int c, d;
};
struct pointed {
struct base* base;
int c, d;
};
static void base_print(struct base* x) {
printf("a: %d, b: %d\n", x->a, x->b);
}
static void tobase_embedded(void* object) {
base_print(object); // no cast needed, suitably converted into first member.
}
static void tobase_pointed(void* object) {
struct base* x = *(struct base**) object; // need this cast?
base_print(x);
}
int main(void) {
struct embedded em = {{4, 2}};
struct pointed pt = {&em.base};
tobase_embedded(&em);
tobase_pointed(&pt);
return 0;
}
Biên soạn với:
$ gcc -std=c99 -O2 -Wall -Werror -pedantic -o main main.c
Sản lượng dự kiến là:
$ ./main
a: 4, b: 2
a: 4, b: 2
Các C99 tiêu chuẩn nói về thành viên đầu tiên của cấu trúc:
C99 6.7.2.1 (13): Một con trỏ tới đối tượng cấu trúc, được chuyển đổi phù hợp, trỏ đến thành viên ban đầu của nó ... và ngược lại. Có thể có đệm không tên trong phạm vi đối tượng cấu trúc, nhưng không phải lúc bắt đầu.
Trong chương trình ví dụ như một con trỏ đến struct embedded
được chuyển thành một con trỏ đến struct base
(thông qua void*
) mà không cần chuyển kiểu tường minh.
Điều gì sẽ xảy ra nếu thay vào đó thành viên đầu tiên là con trỏ đến cơ sở như trong struct pointed
? Tôi không chắc về dàn diễn viên trong phạm vi tobase_pointed
. Nếu không có thùng rác được in, nhưng không có cảnh báo/lỗi biên dịch. Với việc đúc các giá trị chính xác cho base.a
và base.b
được in, nhưng điều đó không thực sự có ý nghĩa nhiều nếu có hành vi không xác định.
Dàn diễn viên có chuyển đổi struct pointed
thành thành viên đầu tiên struct base*
chính xác không?
Thành viên đầu tiên của 'struct pointed' là một con trỏ tới' struct base'. Điều này sẽ yêu cầu dereferencing 'void * object'. Nhưng bạn không thể dereference 'void *' mà không nói trình biên dịch làm thế nào để dereference con trỏ, do đó cần phải cast. – alvits