1

Возможно ли инициализировать статический массив с тройным оператором в инициализаторе? Например:Можно ли инициализировать статический массив, используя тернарный оператор в инициализаторе?

// Array of functions 
static const Callback_t CallbackArray[] = 
{ 
    GenConfig, 
    GenInfo, 
    /* here is the ternary operator to chose a callback */ 
    Test() ? Config : NULLConfig, 
}; 

где Test() является функцией, которая возвращает 0 или 1

// somewhere else in the code 
int gVar = 0; 

int TEST(void) 
{ 
    return gVar; 
} 
+2

Да. Это совершенно верно. До тех пор, пока 'Test()' s макрос – George

+1

Вы * пробовали * его? Это сработало? Если нет, то какие ошибки вы получили? –

+0

Я думаю, что единственной проблемой здесь является 'Test()', поскольку функции не являются постоянными выражениями. Если не для этого, код должен быть в порядке. – Lundin

ответ

2

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

Здесь условный оператор ?: не дает постоянного выражения (поскольку он содержит вызов функции), поэтому код является недопустимым.

+0

Я не верю, что это правильно. Я ничего не могу найти в 6.5.15, поддерживая ваше заявление. Источник? Также 'static const int foo = 1? 1: 0; 'компилируется просто отлично с помощью' gcc -std = c11 -pedantic-errors'. – Lundin

+0

@ Lundin: Я считаю, что это C11 6.7.9/4 'Все выражения в инициализаторе для объекта, который имеет статическую или длительность хранения потоков, должны быть постоянными выражениями или строковыми литералами. –

+0

Да, но это не доказывает, что все операнды и результат условного оператора не могут быть постоянными выражениями. – Lundin

0

Вы не можете инициализировать содержимое массива static на основе функции.

Но сделать еще одну функцию, чтобы выбрать ...

typedef returntype (*fxtype)(parmtypes); 

fxtype choose(void) { 
    return Test() ? Config : NULLConfig; 
} 

static const Callback_t CallbackArray[] = 
{ 
    GenConfig, 
    GenInfo, 
    choose, 
}; 
+1

Интересная идея, но для правильной замены не 'select()' должна вызывать правильную функцию? То есть, предполагаемый код будет использовать '(* CallbackArray [2])()' и ожидать, что функция будет вызвана, поэтому ваш заместитель должен быть больше похож на 'return Test()? Config(): NULLConfig(); '? –

3

Если массив не имеет длительность статического хранения, то оператор может быть использован в качестве выражения инициализатора.

От C Стандартных (6.7.9 Инициализации)

4 Всех выражения в инициализаторе для объекта, который имеет статический или хранения нити длительности должна быть постоянная выражением или строкой литералов.

Примите во внимание, что вы не можете объявлять массив функций, но вы можете объявить массив указателей на функции.

Вот демонстративной программа

#include <stdio.h> 

void f(void) { puts("f"); } 
void g(void) { puts("g"); } 

int main(void) 
{ 
    int x = 1, y = 2; 

    void (*fp[])(void) = { x < y ? f : g }; 

    fp[0](); 

    return 0; 
} 

Выход программы

f 

Если тип функции слишком сложный, вы можете ввести ЬурейиЙ для него. Например,

#include <stdio.h> 

void f(void) { puts("f"); } 
void g(void) { puts("g"); } 

int main(void) 
{ 
    int x = 1, y = 2; 

    typedef void F(void); 

    F * fp[] = { x < y ? f : g }; 

    fp[0](); 

    return 0; 
} 

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

#include <stdio.h> 

void f(void) { puts("f"); } 
void g(void) { puts("g"); } 

typedef void F(void); 

F * fp[] = { 1 ? &f : &g }; 

int main(void) 
{ 
    fp[0](); 

    return 0; 
} 

Из стандарта C (6.6 Постоянные выражения)

9 адрес константы пустого указатель, указатель на именующий , обозначающей объект статической продолжительности хранения, или указатель на функции Обозначения; его должно быть создано с использованием оператора унарного & или целочисленного значения константы, присвоенного типу указателя, или неявно с использованием выражения типа массива или функции. массив-индекс [] и член-доступ. и ->, & и косвенные * унарные операторы и указатели-указатели могут использоваться в создании константы адреса, но значение объекта должно быть не доступно при использовании этих операторов.

+0

Ничто в ваших примерах не имеет статической продолжительности хранения? Разве вы не хотели объявить массив указателей функций в области файлов? – Lundin

+0

@ Lundin Я обновил свой пост. :) –

+0

Хорошо, что имеет больше смысла, поскольку OP, похоже, также имеет массив указателей на функции со статической продолжительностью хранения. Это показывает, что условный оператор не является проблемой. – Lundin

Смежные вопросы