MicrosoctCprog
MicrosoctCprog

Reputation: 490

Check is member in struct with C

I want to access to member in struct but check if this member exist

#include <stdio.h>

int main()
{
    struct MyStruct { int a;};
    struct MyStruct temp ;
    temp.a=3;

    return 0;
}

Is there a way to check if member a is in struct m and if not access to b with #ifdef ? something like #ifdef MyStruct.a temp.a=3; #else temp.b=3; #endif

Upvotes: 4

Views: 1177

Answers (1)

KamilCuk
KamilCuk

Reputation: 140960

It's not possible to do in C.

The usual way if you really want to detect a member of a struct, is to first compile a sample program that uses the struct, see if the compilation succeeds and depending on the result define or not a preprocessor macro to the compiler used to compile the rest of the project. Various build systems were created to ease up such tasks. A short example with cmake may look like the following:

cat >mystruct.h <<EOF
struct MyStruct { 
    int a; // a? maybe not? no one knows.
};
EOF

cat >CMakeLists.txt <<EOF
cmake_minimum_required(VERSION 3.11)
project(test_include C)
# will try to compile a testing file
try_compile(mystruct_has_a "${CMAKE_BINARY_DIR}/temp" ${CMAKE_SOURCE_DIR}/test_mystruct_has_a.c)
add_executable(main main.c)
if(mystruct_has_a)
    target_compile_definitions(main PUBLIC MYSTRUCT_HAS_A)
endif()
EOF

cat >test_mystruct_has_a.c <<EOF
#include "mystruct.h"
int main() {
    struct MyStruct temp;
    temp.a = 3; // test - can we compile this?
}
EOF

cat >main.c <<EOF
#include <stdio.h>
#include "mystruct.h"
int main() {
    struct MyStruct temp ;
#if MYSTRUCT_HAS_A
    // it's ok to use `temp.a` here.
    temp.a = 3;
    printf("%d\n", temp.a);
#endif
}
EOF

Which can be compiled with from the command line:

cmake -S. -B_build && cmake --build _build --verbose

cmake will try to compile file test_mystruct_has_a.c. If the compilation is successful, then the macro MYSTRUCT_HAS_A will be added as a macro to compiler arguments. If not, the macro will not be added. Then main.c will compile with that macro or without depending on the previous result. Such a way is typically used in many, many various projects mostly to provide portability by detecting operating system specific stuff, from top of my head for example members of sigaction, siginfo_t or sched_param.

Upvotes: 4

Related Questions