Если у вас нет типа передаваемой структуры (как подсказывает ваша пустота *), вы обречены. Это всего лишь куча памяти с начальным адресом.
То, что вы можете сделать, это иметь несколько функций, таких как предложенные вами поля update_fields, и каким-то образом вызывать нужную функцию в зависимости от типа структуры (, что легко и может быть совершенно скрыто в макрос, чтобы избежать синтаксического шума).
При этом вы получите код, указанный ниже:
#include <stdio.h>
#include <string.h>
typedef struct {
char street[10];
char city[10];
char lat[10];
char lon[10];
} ADDR_A;
typedef struct {
char street[10];
char city[10];
char zip[10];
char country[10];
} ADDR_B;
#define UPDATEFIELDS(type, value) updateFields_##type(value)
static void updateFields_ADDR_A(ADDR_A *myStruct ) {
strcpy(myStruct->street, "abc" );
strcpy(myStruct->city, "def" );
}
static void updateFields_ADDR_B(ADDR_B *myStruct ) {
strcpy(myStruct->street, "abc" );
strcpy(myStruct->city, "def" );
}
int main(){
ADDR_A a;
ADDR_B b;
updateFields_ADDR_A(&a);
updateFields_ADDR_B(&b);
UPDATEFIELDS(ADDR_A, &a);
printf("%s\n", a.city);
printf("%s\n", b.city);
}
Обратите внимание, что вы, очевидно, не должны писать реальный код изменения поля в функциях updateFields_XXX, а просто использовать этот код в качестве оболочки для получения правильного смещения для внутренних полей.
Если вы также хотите иметь локальный код, вы можете снова использовать макрос,
#define COMMONBODY strcpy(myStruct->street, "abc" );\
strcpy(myStruct->city, "def" );
static void updateFields_ADDR_A(ADDR_A *myStruct ) {
COMMON_BODY
}
static void updateFields_ADDR_B(ADDR_B *myStruct ) {
COMMON_BODY
}
или даже поместить общий код в отдельный файл и включить его два раза (довольно необычный, но рабочий файл)
static void updateFields_ADDR_A(ADDR_A *myStruct ) {
#include "commonbody.c"
}
static void updateFields_ADDR_B(ADDR_B *myStruct ) {
#include "commonbody.c"
}
Также почти возможно (но не так долго, как я знаю) сделать это, используя оператор typeof , за исключением части искажения имени.
Если ваша структура имеет другой размер, мы могли бы даже использовать только одну функцию updateFields (с void *), которая принимает размер структуры в качестве второго параметра и использует ее для автоматического приведения к нужному типу. Это довольно грязно, но возможно [пожалуйста, прокомментируйте, если кто-то хочет увидеть это решение разработанным].
Вы также можете использовать союз. Общие поля будут доступны любому члену объединения, если есть общий префикс (но я понимаю, что это не так). Вы должны понимать, что определение такого объединения ничего не меняет в существующей структуре данных. Это в основном определяет тип ADDR_A или ADDR_B, на который можно ссылаться с помощью указателя.
typedef union {
ADDR_A a;
ADDR_B b;
} ADDR_A_or_B;
Если есть общий префикс, вы можете установить эти переменные, используя любое поле доступа:
static void updateFields(ADDR_A_or_B *myStruct ) {
strcpy( myStruct->a.street, someStreeValueFromSomewhereElse);
strcpy( myStruct->a.city, someCityValueFromSomewhereElse);
}
Вам просто нужно разыграть при вызове:
ADDR_A a;
updateFields((ADDR_A_or_B *)&a);
ADDR_B b;
updateFields((ADDR_A_or_B *)&b);