Я создал следующие макросы для блокировки мьютекса и возврата (из функции, в которой вызывается этот макрос) в случае, если попытка блокировки не удалась. В настоящее время я ограничил круг макросов двумя - один для возврата из функций, которые возвращают значение, независимо от типа, и другой для возврата из функций, которые ничего не возвращают (т.е. void).

Код за пределами макросов (ниже) предназначен только для иллюстрации и имеет очень мало общего с реальным производственным кодом, в котором будут использоваться макросы.

.
#define MUTEX_LOCK()\
    {\
        if (pthread_mutex_lock(&mutex) != 0)\
        {\
            printf("Failed to lock mutex.\n");\
            return;\
        }\
    }
#define MUTEX_LOCK_RVAL(err_val)\
    {\
        if (pthread_mutex_lock(&mutex) != 0)\
        {\
            printf("Failed to lock mutex.\n");\
            return err_val;\
        }\
    }

void vfunc()
{
    printf("\nIn vfunc()\n");
    MUTEX_LOCK();
    printf("\nOut of vfunc()\n");
}

UINT16 uint16func()
{
    printf("\nIn uint16func()\n");
    MUTEX_LOCK_RVAL(0);
    printf("\nOut of uint16func()\n");

    return 9;
}

CHAR* errstr = "Hoo boy!";
CHAR* strfunc()
{
    printf("\nIn strfunc()\n");
    MUTEX_LOCK_RVAL(errstr);
    printf("\nOut of strfunc()\n");

    return NULL;
}

Есть ли способ свести их к одному макросу, который можно использовать в функциях, возвращающих значение, а также void.

work.bin

Ответов: 3

Ответы (3)

Чтобы сделать его совместимым с ANSI, я определяю макрос с помощью return и другого простого символа, который оценивается в null и явно показывает, что это null. То есть:

#define VOID_RET    //This nulls the return value
#define MUTEX_LOCK(err_val)\
    {\
        if (pthread_mutex_lock(&mutex) != 0)\
        {\
            printf("Failed to lock mutex.\n");\
            return err_val;\
        }\
    }
void *mutex = NULL;
void vfunc(void)
{
    printf("\nIn vfunc()\n");
    MUTEX_LOCK(VOID_RET);
    printf("\nOut of vfunc()\n");
}
UINT16 uint16func(void)
{
    printf("\nIn uint16func()\n");
    MUTEX_LOCK(0);
    printf("\nOut of uint16func()\n");

    return 9;
}
CHAR* errstr = "Hoo boy!";
CHAR* strfunc(void)
{
    printf("\nIn strfunc()\n");
    MUTEX_LOCK(errstr);
    printf("\nOut of strfunc()\n");

    return NULL;
}

Я протестировал этот код под C11 и C99.

Единственное решение, которое я могу себе представить, следующее:

#define MUTEX_LOCK( err_val )\
{\
  {\
      if (pthread_mutex_lock(&mutex) != 0)\
      {\
          printf("Failed to lock mutex.\n");\
          return err_val;\
      }\
   }\
}

int test_int()
{
    MUTEX_LOCK( 1 );

    return 0;
}

void test_void()
{
    MUTEX_LOCK( ; );

    return;
}

Насколько я могу судить по документации, вы можете удалить макрофункцию, не принимающую аргументов, потому что вы не обязаны передавать аргумент макрофункции, ожидающей аргументов.
Из документации GNU GCC:

.

Вы можете оставлять аргументы макроса пустыми; это не является ошибкой для препроцессора [...]


По многим аргументам это интересно:

Вы не можете опускать аргументы полностью; если макрос принимает два аргументов, то на верхнем уровне его списка аргументов должна быть ровно одна запятая. списке аргументов.

С учетом приведенных примеров:

min(, b)        ==> ((   ) < (b) ? (   ) : (b))
min(a, )        ==> ((a  ) < ( ) ? (a  ) : ( ))
min(,)          ==> ((   ) < ( ) ? (   ) : ( ))
min((,),)       ==> (((,)) < ( ) ? ((,)) : ( ))

2022 WebDevInsider