Как я могу добавить статическое утверждение, чтобы проверить, является ли переменная статической? - PullRequest
3 голосов
/ 13 апреля 2011

У меня есть макрос, который хорошо работает только со статическими локальными переменными (так как он использует встроенную запись ассемблера для извлечения данных о переменной).Мне нужен способ обеспечить, чтобы входные данные для макроса действительно были статической локальной переменной:

правильно:

func f()
{
    static int x;
    my_macro(x);
}

не правильно:

func f()
{
    int x;
    my_macro(x);
}

Я работаюс GCC для C (без C ++).

Ответы [ 4 ]

4 голосов
/ 15 апреля 2011

Вы можете использовать следующий прием:

#define ASSERT_LOCAL_STATIC(v) static void *p_ ## v = &v

void fn()
{
    int nonstatic_var = 0;
    static int static_var = 0;

    ASSERT_LOCAL_STATIC(static_var);
    ASSERT_LOCAL_STATIC(nonstatic_var);
}

GCC выдает ошибку «элемент инициализатора не является константой» для нестатических переменных.

3 голосов
/ 13 апреля 2011

Вы можете отличить статические и локальные переменные, используя их адреса:

  • Статические переменные хранятся в секциях .BSS или .DATA

  • Локальные переменные хранятся в стеке

Например, вывод следующей программы в моей системе

#include <stdio.h>

void f0() {
    int x = 0;
    printf("%p\n", &x);
}

void f1() {
    static int x = 0;
    printf("%p\n", &x);
}

int main() {
        f0();
        f1();

        return 0;
}

это:

0x7fff1dc718dc
0x600900

Где размещается каждый раздел и стек, зависит от ABI вашей платформы, но вы можете использовать адрес локальной блочной переменной для формирования условия:

#include <stdio.h>

#define check(var) { \
        int ___ = 0; \
        printf("%s (%p): %s\n", #var, &var, (&var > &___)?"local":"static"); \
}

void f0() {
    int x = 0;
    check(x);
}

void f1() {
    static int y = 0;
    check(y);
}

int main() {
        f0();
        f1();

        return 0;
}

Это выводит:

x (0x7fff4b965afc): local
y (0x600978): static

Предупреждение: я бы не советовал использовать этот «трюк». Вот и все: хитрость, которая сломается в самых неудачных обстоятельствах. Просто документируйте свой макрос правильно и позвольте людям, которые его используют, справиться с последствиями его неправильного использования.

2 голосов
/ 13 апреля 2011

Просто сделайте это так, как использует большинство библиотек C: Скажите пользователям, что ваш макрос работает для статических переменных, а поведение для всего остального может быть неопределенным / неожиданным.

Точно так же, как вы можете также передавать NULL-указатели на strdup() и т. Д., Что приведет только к segfault, нет большой проблемы с неисполнением содержимого.

0 голосов
/ 13 апреля 2011

Я думаю, что вы не можете различить эти случаи в ISO C. Но так как вы уже упоминали, что используете GCC, могут быть некоторые полезные встроенные псевдо-функции.Все их имена начинаются с __builtin_, поэтому вы должны прочитать этот список в документации GCC.

http://www.google.com/search?q=gcc+builtin

Ну, я просто прочитал весь встроенный раздел иЯ ничего не нашел.Поэтому я думаю, что это на самом деле невозможно.

Что вы пытаетесь сделать с макросом, просто из любопытства?

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