Рассмотрим библиотеку, в которой у вас есть код. Например, допустим некоторые манипуляции с точками X и Y.
И затем вы создаете свою библиотеку, где вы не хотите разрешать пользователям доступ к вашей переменной struct, поэтому я использую этот подход до сих пор, и он работает нормально, без каких-либо действий undefined:
lib.h:
#ifndef __LIB_H
#define __LIB_H
#ifdef __LIB_INTERNAL
//Structure for single point
typedef struct {
int x, y;
} Point;
//Casted pointer
#define _P(in) ((Point *)(in))
#endif
//Define pointer for public use as void pointer
typedef void* Point_p;
//Create point
Point_p createPoint(int x, int y);
#endif
lib.c:
//Define LIB_INTERNAL to allow visible access
#define __LIB_INTERNAL
#include "lib.h"
#include "stdlib.h"
Point_p createPoint(int x, int y) {
Point_p p = malloc(sizeof(Point));
_P(p)->x = x; //_P is visible in this function
_P(p)->y = y;
return p;
}
main.c:
#include "lib.h"
int main() {
Point_p p = createPoint(1, 2); //OK
Point *ptr = createPoint(1, 2); //Error as Point is not visible public
p->x = 4; //Error as Point_p is void *
}
Таким образом, я уверен, что у пользователя нет прямого доступа к переменной Point, и он вынужден использовать функции для выполнения операций в этой точке.
Теперь я думаю о другом подходе. Но сначала sizeof(void *)
и sizeof(Point *)
всегда одно и то же, поэтому я хотел бы использовать этот подход, показывая Point_p
до lib.c
как typedef Point* Point_p
и ко всем другим файлам, которые не являются частью библиотеки как typedef void* Point_p
.
lib.h
#ifndef __LIB_H
#define __LIB_H
#ifdef __LIB_INTERNAL
//Structure for single point
typedef struct {
int x, y;
} Point;
//Define pointer for private use as Point pointer
typedef Point* Point_p;
#else
//Define pointer for public use as void pointer
typedef void* Point_p;
#endif
//Create point
Point_p createPoint(int x, int y);
#endif
lib.c:
//Define LIB_INTERNAL to allow visible access
#define __LIB_INTERNAL
#include "lib.h"
#include "stdlib.h"
Point_p createPoint(int x, int y) {
Point_p p = malloc(sizeof(Point));
p->x = x; //_P is not needed because Point_p is visible as Point *
p->y = y;
return p;
}
main.c: то же, что и предыдущий
Вопрос
Это поведение undefined? Поскольку во втором подходе lib.c
видит Point_p
как Point *
, но main.c
все еще видит его как void *
, и поэтому lib.c
имеет доступ к элементам напрямую без каста до и main.c
не имеет его ни может забрасываться, потому что структура Point
скрыта.