С трюком макрос, чтобы скрыть назначение? - PullRequest
0 голосов
/ 16 мая 2018

У меня есть проект с несколькими файлами: source1.c source2.c source1.h source2.h.Теперь source1.c объявляет некоторые переменные, а source1.h выводит их (с условным макросом сборки).Затем source2.c будет использовать переменные extern путем присвоения им значения.

Проблема заключается в том, что source1.h имеет что-то вроде следующего:

#ifdef CUST1
extern type var_name;
#else
// Need to extern something or use a clever macro here but i dont like these below
//#define var_name int x (requires top of scope block usage)
//#define var_name // (doesnt compile)
//#define var_name -1 (simply doesnt compile)
//#define var_name 1= (This seems like it would reduce to unused 1==1; but doesnt work)
#endif

Моя сборка работает для CUST1, но она не будет работать для CUST2, потому что var_name никогда не объявляется / выходит из области действия, когда на него ссылаются в source2.c.

Я не хочу использовать var_name для CUST2, и это недоступный код в source2.c.Вот мой вопрос, как я могу использовать макрос для #define var_name, чтобы назначение "уходило" или ничего не делало?

Я мог бы "#define var_name int x".Это поместит int x в стек в функциях source2.c и присвоит значения в source2.c, но если на него когда-либо будут ссылаться где-либо, кроме вершины блока области, мой старый (C89?) Компилятор выдаст ошибку.

Например, если source2.c когда-либо имел следующее, он не смог бы скомпилировать:

unsigned short local_var = 0;
local_var = 1; //or someother value
var_name = local_var * 2;

Я мог бы обернуть логику в source2.c теми же макросами #ifdef CUST1, но это не тактоже хорошо.

Если бы var_name сравнивалось только с ним, это было бы не так уж плохо, потому что я мог бы просто использовать #define var_name -1 или что-то, что не сработало бы, все сравнивает / переключает.Проблемы -1 = temp_var;не компилируется, потому что -1 не может быть lvalue.

Аналогично, я не могу "#define var_name //", потому что комментарии удаляются до замены маркера в соответствии с этим: Можете ли вы # определить комментарий вC?

Есть ли хитрый макрос-трюк, который скрывает / удаляет это назначение, который не помещает local_var в стек?Я чувствую, что есть что-то возможное с троичной, но я не могу думать об этом.

РЕДАКТИРОВАТЬ минимальный пример кода:

source1.c

int var_name = 0;

source1.h

#ifdef CUST1
extern int var_name;
#else
// clever macro
#endif

source2.c

#include "source1.h"
int main(){
  var_name = 1;
  return 0;
}

Ответы [ 3 ]

0 голосов
/ 16 мая 2018
extern int varname;

#define varname __attribute__((unused)) int varname

int square(int num) {
    varname = 1;
    return num * num;
}

Будет работать на любом уровне оптимизации, кроме -O0

https://godbolt.org/g/phssNn

0 голосов
/ 16 мая 2018

Если код доступа к var_name в source2.c недоступен, когда CUST1 не определено (как вы, кажется, говорите), тогда вы можете определить его следующим образом:

#include <stdlib.h>

#define var_name (*(abort(), (type *)0))

Это будет синтаксически работать как lvalue (или rvalue) правильного типа, но прервет программу, если она действительно когда-либо будет выполнена.

0 голосов
/ 16 мая 2018

Нет прямого способа скрыть назначение, как вы предлагаете, но есть несколько альтернатив:

  1. Вы можете использовать другой макрос:

    #ifdef CUST1
    extern type var_name;
    /* Do the real assignment */
    #define SET_VAR_TO(val) do{ var_name = (val); } while(0)
    #else
    /* Just evaluate for the side-effects */
    #define SET_VAR_TO(val) do { val; } while(0)
    #endif
    

    А затем внутри source2.c замените все присвоения var_name на SET_VAR_TO(value), например:

    int foo(void) {
        /* Replace
        var_name = bar();
        * With: */
        SET_VAR_TO(bar());
    }
    
  2. Вы можете проверить, определено ли CUST1 также в source2.c:

    /* in source2.c */
    int foo(void) {
    #ifdef CUST1
    var_name = bar();
    #endif
    }
    

    В этом случае вы можете даже обернуть присвоение реальной функции, определенной только в исходном файле:

    /* in source2.c */
    int set_var_to(type value) {
    #ifdef CUST1
    var_name = value;
    #endif
    }
    
    int foo(void) {
        /* Replace
        var_name = bar();
        * With: */
        set_var_to(bar());
    }
    

Поскольку вы предпочитаете не дублировать код, заключая каждое назначение в #ifdef CUST1 ... #endif, вы можете использовать функцию или макрос. Помните, что опция # 1 также предоставляет макрос SET_VAR_TO любому файлу, который #include s source1.h, а не только source2.c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...