Pergunta

Eu preciso declarar uma matriz de ponteiros para funções como assim:

extern void function1(void);
extern void function2(void);
...

void (*MESSAGE_HANDLERS[])(void) = {
   function1,
   function2,
   ...
};

No entanto, eu quero a matriz para ser declarado como constante - tanto os dados na matriz e o ponteiro para os dados. Infelizmente, não me lembro onde colocar a palavra-chave (s) const.

Estou assumindo o ponteiro real, MESSAGE_HANDLERS neste caso, já é constante porque ele é declarado como uma matriz. Por outro lado, não podia os ponteiros de função dentro da matriz ser alterado em tempo de execução se for declarada como mostrado?

Foi útil?

Solução

Há uma técnica para lembrar como construir tal tipo. Primeiro tente ler ponteiros a partir de seu nome e lido da direita para a esquerda.

Como declarar essas coisas sem ajuda?

Arrays

T t[5];

é um array de 5 T . Para fazer T um tipo de função, você escreve o tipo de retorno à esquerda, e os parâmetros para a direita:

void t[5](void);

seria ser um array de 5 funções retornar void e tomando nenhum parâmetro . Mas a própria funções não podem ser recheadas em matrizes! Eles não são objetos. Somente ponteiros para eles pode.

E

void * t[5](void);

Isso ainda é errado, pois seria apenas mudar o tipo de retorno para ser um ponteiro para void. Você tem que parênteses uso:

void (*t[5])(void);

e isso vai realmente funcionar. t é um array de 5 ponteiros para funções retornar void e tomando nenhum parâmetro .

Great! E sobre uma matriz de ponteiros para arras? Isso é muito semelhante. O tipo de elemento aparece à esquerda, ea dimensão à direita. Mais uma vez, os parênteses são necessários porque caso contrário a matriz se tornaria uma matriz multidimensional de ponteiros inteiros:

int (*t[5])[3];

É isso aí! Um array de 5 ponteiros para matrizes de 3 int .

E sobre funções?

O que acabamos de aprender é verdade sobre funções também. Vamos declarar uma função de tomar um int que retorna um ponteiro para outra função tomando nenhum parâmetro e retornar void:

void (*f(int))(void);

precisamos parênteses novamente por ele mesmo motivo acima. Poderíamos agora chamá-lo, e chamar a função retornou apontado novamente.

f(10)();

Retornando um ponteiro para função retornando outro ponteiro para a função

O que sobre isso?

f(10)(true)(3.4);

? Em outras palavras, como é que um função de tomar int retornando um ponteiro para uma função de tomada bool retornando um ponteiro para uma função de tomar casal e retornar void se pareceria? A resposta é que você só ninho eles:

void (*(*f(int))(bool))(double);

Você poderia fazer vezes de modo infinitas. Na verdade, você também pode retornar um ponteiro para uma matriz assim como você pode um ponteiro para uma função:

int (*(*f(int))(bool))[3];

Esta é uma função de tomada int retornando um ponteiro para um bool função de tomada retornando um ponteiro para uma matriz de 3 int

O que isso tem a ver com const?

Agora que o acima explicado como construir tipos complexante de tipos fundamentais, você pode colocar const em lugares onde você já sabe onde eles pertencem. Basta considerar:

T c * c * c ... * c name;

O T é o tipo básico que acabam apontando para no final. O c significa qualquer const ou não const. Por exemplo

int const * const * name;

declarará nome para ter o tipo ponteiro para um ponteiro constante para uma constante int . Você pode alterar name, mas você não pode mudar *name, o que seria do tipo

int const * const

e nem **name, o que seria do tipo

int const

Vamos aplicar isto a um ponteiro de função do acima:

void (* const t[5])(void);

Este seria realmente declarar a matriz para conter ponteiros constantes. Assim, depois de criar (e inicializar) a matriz, o ponteiros são const, porque o const apareceu depois de a estrela. Note-se que não podemos colocar um const antes da estrela, neste caso, uma vez que não há ponteiros para funções constantes . Funções simplesmente não pode ser const como isso não faria sentido. Assim, o seguinte não é válido:

void (const * t[5])(void);

Conclusão

O C ++ e C forma de declarar funções e matrizes, na verdade, é na verdade um pouco confusa. Você tem que obter a sua cabeça em torno dela em primeiro lugar, mas se você entender isso, você pode escrever declarações de função muito compactas usá-lo.

Outras dicas

cdecl diz:

cdecl> explain void (* const foo[])(void)
declare foo as array of const pointer to function (void) returning void

É o que você precisa?

Em situações como esta, fazer uma typedef para nomear sua assinatura função, que o torna muito mais simples:

typedef void MESSAGE_HANDLER(void);

com isso no lugar, ele deve ser apenas:

MESSAGE_HANDLER * const handlers[] = { function1, function2 };

Para obter o conteúdo real da constante de matriz.

Editar :. Removeram parte ponteiro do typedef, isso realmente é melhor (ao vivo e aprender)

Com o Visual Studio 2008, eu recebo:

void (* const MESSAGE_HANDLERS[])(void) = {
   NULL,
   NULL
};

int main ()
{
    /* Gives error 
        '=' : left operand must be l-value
    */
    MESSAGE_HANDLERS = NULL;

    /* Gives error 
        l-value specifies const object
    */
    MESSAGE_HANDLERS[0] = NULL;
}

Eu não tenho certeza se isso vai funcionar em 'C'. ela não funciona em 'C ++':

  • Primeiro defina MESSAGE_HANDLERS como um tipo:

    typedef void (*MESSAGE_HANDLER)();

  • Em seguida, use a definição do tipo de declarar sua matriz uma constante:

    MESSAGE_HANDLER const handlers[] = {function1, function2};

O truque está na typedef, se você pode fazer o mesmo semanticamente em 'C', ele deve funcionar também.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top