"Const estático" vs "#define" vs "enum"

585

Qual é o melhor para usar entre as instruções abaixo em C?

static const int var = 5;

ou

#define var 5

ou

enum { var = 5 };
Vijay
fonte
35
Curiosamente, essa é quase exatamente a mesma pergunta que stackoverflow.com/questions/1637332/static-const-vs-define . A única diferença é que essa pergunta é sobre C ++, e esta é sobre C. Como minha resposta foi específica em C ++, digo que as torna não idênticas, mas outras podem discordar.
TED
53
Não é idêntico, definitivamente. Há muitas áreas em que o C ++ permite a sintaxe C por motivos de compatibilidade. Nesses casos, perguntas como "qual é a melhor maneira de fazer o X" terão respostas diferentes em C ++. Por exemplo, inicialização de objeto.
MSalters 4/11/2009
Como isso não é baseado em opiniões? Cada um deles tem uma finalidade diferente
Sam Hammamy
1
@RobertSsupportsMonicaCellio, Sim. Obrigado pela intimação
Vijay

Respostas:

690

Depende do valor que você precisa. Você (e todo mundo até agora) omitiu a terceira alternativa:

  1. static const int var = 5;
  2. #define var 5
  3. enum { var = 5 };

Ignorando problemas sobre a escolha do nome, então:

  • Se você precisar passar um ponteiro, use (1).
  • Como (2) é aparentemente uma opção, você não precisa passar indicadores.
  • Ambos (1) e (3) têm um símbolo na tabela de símbolos do depurador - que facilita a depuração. É mais provável que (2) não tenha um símbolo, deixando você se perguntando o que é.
  • (1) não pode ser usado como uma dimensão para matrizes no escopo global; ambos (2) e (3) podem.
  • (1) não pode ser usado como uma dimensão para matrizes estáticas no escopo da função; ambos (2) e (3) podem.
  • Em C99, tudo isso pode ser usado para matrizes locais. Tecnicamente, o uso de (1) implicaria o uso de um VLA (array de comprimento variável), embora a dimensão referenciada por 'var' seja, obviamente, fixada no tamanho 5.
  • (1) não pode ser usado em lugares como instruções de chave; ambos (2) e (3) podem.
  • (1) não pode ser usado para inicializar variáveis ​​estáticas; ambos (2) e (3) podem.
  • (2) pode alterar o código que você não deseja alterar porque é usado pelo pré-processador; ambos (1) e (3) não terão efeitos colaterais inesperados como esse.
  • Você pode detectar se (2) foi definido no pré-processador; nem (1) nem (3) permitem isso.

Portanto, na maioria dos contextos, prefira o 'enum' sobre as alternativas. Caso contrário, o primeiro e o último marcador provavelmente serão os fatores de controle - e você precisará pensar mais se precisar satisfazer os dois ao mesmo tempo.

Se você estivesse perguntando sobre C ++, usaria a opção (1) - a const estática - sempre.

Jonathan Leffler
fonte
111
lista fantástica! Uma desvantagem enumé que eles são implementados como int([C99] 6.7.2.2/3). A #definepermite que você especifique sem assinatura e com Ue com Lsufixos, além de especificar constum tipo. enumpode causar problemas nas conversões de tipo comuns.
Gauthier
37
(2) as pessoas SEMPRE reclamam da segurança do tipo. Eu nunca entendo porque não basta usar "#define var ((int) 5)" e, viva, você obteve segurança de tipo com um define.
Ingo Blackman
6
@ RedX: você teria que estar em um ambiente muito peculiar para ter espaço para uma preocupação. Dito isto, enumnem #defineusa espaço extra, por si só. O valor aparecerá no código do objeto como parte das instruções, em vez de ser alocado para armazenamento no segmento de dados, no heap ou na pilha. Você terá algum espaço alocado para o static const intarquivo, mas o compilador poderá otimizá-lo se você não usar um endereço.
Jonathan Leffler
15
Outro 'voto' para enums (e static const): eles não podem ser alterados. a definepode ser #undefineonde d enume static constsão fixados no valor fornecido.
Daan Timmer
15
@ QED: Não, obrigado. Uma constante simples é segura fora dos parênteses. Ou, mostre-me como um programa que poderia legitimamente ser compilado seria alterado por não ter os 5 entre parênteses. Se fosse o argumento para uma macro no estilo de função ou se houvesse algum operador na expressão, você estaria correto em me culpar se eu não tivesse incluído os parênteses. Mas esse não é o caso aqui.
Jonathan Leffler
282

De um modo geral:

static const

Porque respeita o escopo e é seguro para o tipo.

A única ressalva que pude ver: se você deseja que a variável seja possivelmente definida na linha de comando. Ainda existe uma alternativa:

#ifdef VAR // Very bad name, not long enough, too general, etc..
  static int const var = VAR;
#else
  static int const var = 5; // default value
#endif

Sempre que possível, em vez de macros / elipses, use uma alternativa segura para o tipo.

Se você realmente precisa usar uma macro (por exemplo, deseja __FILE__ou __LINE__), é melhor nomear sua macro com muito cuidado: em sua convenção de nomenclatura Boost recomenda todas as letras maiúsculas, começando pelo nome do projeto (aqui BOOST_ ), ao ler a biblioteca, você notará que isso é (geralmente) seguido pelo nome da área específica (biblioteca) e, em seguida, com um nome significativo.

Geralmente faz para nomes longos :)

Matthieu M.
fonte
2
Concordo - também com #define, há um risco geral de codificar desconfigurado, pois o pré-processador não está ciente da sintaxe.
NeilDurant 4/11/2009
10
É melhor usar #if do que #ifdef, mas caso contrário, eu concordo. +1.
Tim Post
58
Este é o evangelismo C ++ padrão. A resposta abaixo é MUITO mais clara ao explicar o que as opções realmente são e significam. Em particular: eu apenas tive um problema com "const estática". Alguém o usou para definir cerca de 2000 "constantes" em um arquivo de cabeçalho. Em seguida, esse arquivo de cabeçalho foi incluído em cerca de 100 arquivos ".c" e ".cpp". => 8 MB para "consts". Ótimo. Sim, eu sei que você pode usar um vinculador para remover consts não referenciados, mas isso ainda deixa você quais os "consts" referenciados. Ficar sem espaço O que há de errado com esta resposta.
Ingo Blackman
2
@IngoBlackman: Com um bom compilador, apenas aqueles staticcujo endereço é usado devem permanecer; e se o endereço for escolhido, não seria possível usar um #defineou enum(sem endereço) ... então, eu realmente não consigo ver qual alternativa poderia ter sido usada. Se você pode acabar com a "avaliação do tempo de compilação", pode estar procurando extern const.
Matthieu M.
15
@ Tim Post: #ifpode ser preferível ao longo #ifdefde bandeiras booleanas, mas, neste caso, seria impossível para definir varcomo 0a partir da linha de comando. Portanto, neste caso, #ifdeffaz mais sentido, desde que 0seja um valor legal para var.
Maarten
108

Em C, especificamente? Em C, a resposta correta é: use #define(ou, se apropriado enum)

Embora seja benéfico ter as propriedades de escopo e digitação de um constobjeto, na realidade os constobjetos em C (em oposição ao C ++) não são constantes verdadeiras e, portanto, geralmente são inúteis na maioria dos casos práticos.

Portanto, em C, a escolha deve ser determinada pela forma como você planeja usar sua constante. Por exemplo, você não pode usar um const intobjeto como um caserótulo (enquanto uma macro funcionará). Você não pode usar umconst int objeto como uma largura de campo de bits (enquanto uma macro funcionará). No C89 / 90, você não pode usar um constobjeto para especificar um tamanho de matriz (enquanto uma macro funcionará). Mesmo em C99, você não pode usar um constobjeto para especificar um tamanho de matriz quando precisar de um VLA não matriz que .

Se isso é importante para você, ele determinará sua escolha. Na maioria das vezes, você não terá escolha a não ser usar #defineem C. E não se esqueça de outra alternativa, que produz constantes verdadeiras em C - enum.

No C ++, os constobjetos são constantes verdadeiras; portanto, no C ++, é quase sempre melhor preferir a constvariante ( staticembora não seja necessário explicitar o C ++).

Formiga
fonte
6
"você não pode usar um objeto const int como um rótulo de caso (enquanto uma macro funcionará)" ---> Em relação a essa instrução, testei uma variável const int em C no caso de opção que está funcionando ...
john
8
@ john: Bem, você precisa fornecer o código que você testou e nomear o compilador específico. O uso de const intobjetos em rótulos de maiúsculas e minúsculas é ilegal em todas as versões da linguagem C. (Obviamente, o seu compilador é livre para suportá-lo como uma extensão de linguagem semelhante ao C ++ não padrão.) #
1068
11
"... e, portanto, geralmente são inúteis na maioria dos casos práticos ." Discordo. Eles são perfeitamente úteis desde que você não precise usar o nome como uma expressão constante. A palavra "constante" em C significa algo que pode ser avaliado em tempo de compilação; constsignifica somente leitura. const int r = rand();é perfeitamente legal.
26414 Keith Thompson
Em c ++, é melhor usar constexprem comparação com constespecialmente com os stlcontêineres como arrayou bitset.
Mayukh Sarkar
1
@ john você deve ter testado na switch()declaração, não em caseuma. Eu também fui pego nessa também ☺
Hi-Angel
32

A diferença entre static conste #defineé que o primeiro usa a memória e o posterior não usa a memória para armazenamento. Em segundo lugar, você não pode passar o endereço de um#define enquanto você pode passar o endereço de umstatic const . Na verdade, depende de em que circunstâncias estamos, precisamos selecionar um entre esses dois. Ambos estão no seu melhor em diferentes circunstâncias. Por favor, não assuma que um é melhor que o outro ... :-)

Se esse fosse o caso, Dennis Ritchie teria mantido o melhor sozinho ... hahaha ... :-)

envoltório
fonte
6
+1 por mencionar memória, alguns sistemas incorporados ainda não têm muito, embora eu provavelmente comece usando consts estáticos e mude para #defines, se necessário.
Fluffyben 7/03/12
3
Eu apenas testei. De fato, const int usa memória adicional em comparação com #define ou enum. Como programamos sistemas embarcados, não podemos permitir o uso adicional de memória. Então, voltaremos a usar #define ou enum.
Davide Andrea
2
Na prática, não é mais verdade (a) que a constuse memória. O GCC (testado com 4.5.3 e algumas versões mais recentes) otimiza facilmente o const intliteral direto em seu código ao usar -O3. Portanto, se você desenvolver um desenvolvimento incorporado com pouca RAM (por exemplo, AVR), poderá usar com segurança consts C se usar o GCC ou outro compilador compatível. Eu não testei, mas espero que o Clang faça a mesma coisa.
Raphael
19

Em C #defineé muito mais popular. Você pode usar esses valores para declarar tamanhos de matriz, por exemplo:

#define MAXLEN 5

void foo(void) {
   int bar[MAXLEN];
}

O ANSI C não permite que você use static consts neste contexto, tanto quanto eu sei. Em C ++, você deve evitar macros nesses casos. Você pode escrever

const int maxlen = 5;

void foo() {
   int bar[maxlen];
}

e até deixar de fora staticporque a ligação interna constjá está implícita [somente em C ++].

sellibitze
fonte
1
O que você quer dizer com "ligação interna"? Eu posso ter const int MY_CONSTANT = 5;em um arquivo e acessá-lo extern const int MY_CONSTANT;em outro. Não pude encontrar nenhuma informação no padrão (C99 pelo menos) sobre a constalteração do comportamento padrão "6.2.2: 5 Se a declaração de um identificador para um objeto tiver escopo de arquivo e nenhum especificador de classe de armazenamento, seu vínculo é externo".
Gauthier 19/01
@ Gauthier: Desculpe, por isso. Eu deveria ter dito "já está implícito por const na linguagem C ++". Isso é específico para C ++.
usar o seguinte comando
@sellibitze, é bom ver alguns argumentos ao longo do caminho, em vez de toneladas de OPINIÃO Se houvesse bônus para argumentos verdadeiros, você conseguiu!
Paul Paulo
1
A partir de C99, seu segundo trecho é legal. baré um VLA (array de comprimento variável); é provável que o compilador gere código como se seu comprimento fosse constante.
26414 Keith Thompson
14

Outra desvantagem de constC é que você não pode usar o valor na inicialização de outro const.

static int const NUMBER_OF_FINGERS_PER_HAND = 5;
static int const NUMBER_OF_HANDS = 2;

// initializer element is not constant, this does not work.
static int const NUMBER_OF_FINGERS = NUMBER_OF_FINGERS_PER_HAND 
                                     * NUMBER_OF_HANDS;

Mesmo isso não funciona com uma const, pois o compilador não a vê como uma constante:

static uint8_t const ARRAY_SIZE = 16;
static int8_t const lookup_table[ARRAY_SIZE] = {
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; // ARRAY_SIZE not a constant!

Eu ficaria feliz em usar digitado const nesses casos, caso contrário ...

Gauthier
fonte
5
Um pouco tarde para o jogo, mas essa pergunta surgiu em outra pergunta. Perseguir por que seu static uint8_t const ARRAY_SIZE = 16;repentino não compila mais pode ser um pouco desafiador, principalmente quando ele #define ARRAY_SIZE 256está enterrado a dez camadas de profundidade em uma teia emaranhada de cabeçalhos. Que o nome todo em maiúsculas ARRAY_SIZEestá causando problemas. Reserve ALL_CAPS para macros e nunca defina uma macro que não esteja no formato ALL_CAPS.
David Hammen
@ David: bons conselhos, que vou seguir.
Gauthier
1
4 anos depois, você me poupou muito tempo imaginando por que eu não podia "aninhar" const. Isso poderia ser mais votado!
Plouff
11

Se você pode se safar, static const tem muitas vantagens. Obedeça aos princípios normais do escopo, é visível em um depurador e geralmente obedece às regras que as variáveis ​​obedecem.

No entanto, pelo menos no padrão C original, na verdade não é uma constante. Se você usar #define var 5, poderá escrever int foo[var];como uma declaração, mas não poderá fazê-lo (exceto como uma extensão do compilador " static const int var = 5;. Com este não é o caso em C ++, onde a static constversão pode ser usada em qualquer lugar do#define versão puder, e acredito que isso também é o caso do C99.

No entanto, nunca nomeie uma #defineconstante com um nome em minúsculas. Ele substituirá qualquer uso possível desse nome até o final da unidade de tradução. As constantes de macro devem estar no que é efetivamente seu próprio espaço para nome, que é tradicionalmente todas as letras maiúsculas, talvez com um prefixo.

David Thornley
fonte
6
Infelizmente, esse não é o caso do C99. constem C99 ainda não é uma constante real. Você pode declarar o tamanho da matriz com a constem C99, mas apenas porque C99 suporta matrizes de comprimento variável. Por esse motivo, ele funcionará apenas onde os VLAs são permitidos. Por exemplo, mesmo em C99, você ainda não pode usar a constpara declarar o tamanho de uma matriz de membros em a struct.
AnT
Embora seja correto que o C99 não permita isso, o GCC (testado com 4.5.3) permitirá perfeitamente inicializar matrizes com um const inttamanho como se fosse uma const C ++ ou uma macro. Se você deseja depender desse desvio do GCC do padrão, é certamente sua escolha, eu pessoalmente o escolheria, a menos que você possa realmente usar outro compilador que não o GCC ou o Clang, este último tem o mesmo recurso aqui (testado com o Clang 3.7)
Raphael
7

É SEMPRE preferível usar const, em vez de #define. Isso porque const é tratado pelo compilador e #define pelo pré-processador. É como se o #define em si não faça parte do código (grosso modo).

Exemplo:

#define PI 3.1416

O nome simbólico PI nunca pode ser visto pelos compiladores; pode ser removido pelo pré-processador antes que o código-fonte chegue ao compilador. Como resultado, o nome PI pode não ser inserido na tabela de símbolos. Isso pode ser confuso se você receber um erro durante a compilação envolvendo o uso da constante, porque a mensagem de erro pode se referir a 3.1416, não ao PI. Se o PI fosse definido em um arquivo de cabeçalho que você não escreveu, você não teria ideia de onde veio esse 3.1416.

Esse problema também pode surgir em um depurador simbólico, porque, novamente, o nome com o qual você está programando pode não estar na tabela de símbolos.

Solução:

const double PI = 3.1416; //or static const...
suren
fonte
6

#define var 5causará problemas se você tiver coisas assim mystruct.var.

Por exemplo,

struct mystruct {
    int var;
};

#define var 5

int main() {
    struct mystruct foo;
    foo.var = 1;
    return 0;
}

O pré-processador irá substituí-lo e o código não será compilado. Por esse motivo, o estilo tradicional de codificação sugere que todas as constantes #defines usam letras maiúsculas para evitar conflitos.

Interrupção não mascarável
fonte
6

Eu escrevi um programa de teste rápido para demonstrar uma diferença:

#include <stdio.h>

enum {ENUM_DEFINED=16};
enum {ENUM_DEFINED=32};

#define DEFINED_DEFINED 16
#define DEFINED_DEFINED 32

int main(int argc, char *argv[]) {

   printf("%d, %d\n", DEFINED_DEFINED, ENUM_DEFINED);

   return(0);
}

Isso compila com estes erros e avisos:

main.c:6:7: error: redefinition of enumerator 'ENUM_DEFINED'
enum {ENUM_DEFINED=32};
      ^
main.c:5:7: note: previous definition is here
enum {ENUM_DEFINED=16};
      ^
main.c:9:9: warning: 'DEFINED_DEFINED' macro redefined [-Wmacro-redefined]
#define DEFINED_DEFINED 32
        ^
main.c:8:9: note: previous definition is here
#define DEFINED_DEFINED 16
        ^

Observe que o enum dá um erro quando define dá um aviso.

Michael Potter
fonte
4

A definição

const int const_value = 5;

nem sempre define um valor constante. Alguns compiladores (por exemplo, tcc 0.9.26 ) apenas alocam a memória identificada com o nome "const_value". Usando o identificador "const_value", você não pode modificar esta memória. Mas você ainda pode modificar a memória usando outro identificador:

const int const_value = 5;
int *mutable_value = (int*) &const_value;
*mutable_value = 3;
printf("%i", const_value); // The output may be 5 or 3, depending on the compiler.

Isso significa a definição

#define CONST_VALUE 5

é a única maneira de definir um valor constante que não pode ser modificado por nenhum meio.

user2229691
fonte
8
Modificar um valor constante usando um ponteiro é um comportamento indefinido. Se você deseja ir para lá, #definetambém pode ser modificado editando o código da máquina.
ugoren
Você está parcialmente certo. Testei o código com o Visual Studio 2012 e ele é impresso 5. Mas não se pode modificar #defineporque é uma macro de pré-processador. Não existe no programa binário. Se alguém quisesse modificar todos os locais onde CONST_VALUEera usado, era necessário fazê-lo um por um.
user2229691
3
@ugoren: Suponha que você escrever #define CONST 5, então if (CONST == 5) { do_this(); } else { do_that(); }, eo compilador elimina o elseramo. Como você propõe editar o código da máquina para mudar CONSTpara 6?
26414 Keith Thompson
@KeithThompson, eu nunca disse que isso pode ser feito com facilidade e confiabilidade. Só isso #definenão é à prova de balas.
26414 ugoren
3
@ugoren: Meu argumento é que "editar o código da máquina" não é uma maneira sensata de duplicar o efeito de alterar o valor de a #define. A única maneira real de fazer isso é editar o código fonte e recompilar.
26414 Keith Thompson
4

Embora a pergunta fosse sobre números inteiros, vale a pena notar que #define e enums são inúteis se você precisar de uma estrutura ou string constante. Ambos são geralmente passados ​​para funções como ponteiros. (Com strings é necessário; com estruturas é muito mais eficiente.)

Quanto aos números inteiros, se você estiver em um ambiente incorporado com memória muito limitada, talvez seja necessário se preocupar com o local onde a constante é armazenada e como os acessos a ela são compilados. O compilador pode adicionar duas consts em tempo de execução, mas adicionar dois # define em tempo de compilação. Uma constante #define pode ser convertida em uma ou mais instruções MOV [imediatas], o que significa que a constante é efetivamente armazenada na memória do programa. Uma constante const será armazenada na seção .const na memória de dados. Em sistemas com arquitetura de Harvard, pode haver diferenças no desempenho e no uso da memória, embora provavelmente sejam pequenos. Eles podem ser importantes para a otimização rígida dos loops internos.

Adam Haun
fonte
3

Não pense que há uma resposta para "o que é sempre melhor", mas, como Matthieu disse

static const

é do tipo seguro. Minha maior preocupação com o animal de estimação #defineé que, ao depurar no Visual Studio, você não pode assistir à variável. Dá um erro que o símbolo não pode ser encontrado.

Afcrowe
fonte
1
"você não pode assistir a variável" Certo, não é uma variável. Não muda, por que você precisa assistir? Você pode encontrar todos os lugares em que é usado simplesmente pesquisando o rótulo. Por que você precisaria (ou até desejaria) assistir a um #define?
Marshall Eubanks
3

Aliás, uma alternativa para #define, que fornece escopo adequado, mas se comporta como uma constante "real", é "enum". Por exemplo:

enum {number_ten = 10;}

Em muitos casos, é útil definir tipos enumerados e criar variáveis ​​desses tipos; se isso for feito, os depuradores poderão exibir variáveis ​​de acordo com o nome da enumeração.

Uma ressalva importante ao fazer isso, no entanto: no C ++, os tipos enumerados têm compatibilidade limitada com números inteiros. Por exemplo, por padrão, não se pode executar aritmética sobre eles. Acho que esse é um comportamento padrão curioso para enumerações; embora fosse bom ter um tipo de "enum estrito", dado o desejo de ter C ++ geralmente compatível com C, eu pensaria que o comportamento padrão de um tipo de "enum" deveria ser intercambiável com números inteiros.

supercat
fonte
1
Em C, constantes de enumeração são sempre do tipo int, portanto, o "enum hack" não pode ser usado com outros tipos inteiros. (A enumeração tipo é compatível com algum tipo inteiro definido pela implementação, não necessariamente int, mas, neste caso, o tipo é tão anônimo que não importa.)
Keith Thompson
@KeithThompson: Desde que escrevi o texto acima, eu li que o MISRA-C gritará se um compilador atribuir um tipo diferente de intuma variável do tipo enumeração (que os compiladores podem fazer) e se tentar atribuir a essa variável um membro de sua própria enumeração. Eu gostaria que os comitês de padrões adicionassem maneiras portáteis de declarar tipos inteiros com semântica especificada. QUALQUER plataforma, independentemente do chartamanho, deve poder, por exemplo, declarar um tipo que envolverá o mod 65536, mesmo que o compilador precise adicionar muitas AND R0,#0xFFFFinstruções ou instruções equivalentes.
Supercat 26/02
Você pode usar uint16_t, embora é claro que não seja um tipo de enumeração. Seria bom permitir ao usuário especificar o tipo inteiro usado para representar um determinado tipo de enumeração, mas você pode obter o mesmo efeito com a typedefpara uint16_te uma série de #defines para valores individuais.
26514 Keith Thompson
1
@KeithThompson: Eu entendo que, por razões históricas, estamos presos ao fato de que algumas plataformas serão avaliadas 2U < -1Lcomo verdadeiras e outras como falsas, e agora estamos presos ao fato de que algumas plataformas implementarão uma comparação entre uint32_te int32_tcomo assinado e alguns como não assinados, mas isso não significa que o Comitê não possa definir um sucessor compatível com C que inclua tipos cuja semântica seria consistente em todos os compiladores.
Supercat
1

Uma diferença simples:

No tempo de pré-processamento, a constante é substituída por seu valor. Portanto, você não pode aplicar o operador de desreferência a uma definição, mas pode aplicar o operador de desreferência a uma variável.

Como você supõe, define é mais rápido que a const estática.

Por exemplo, tendo:

#define mymax 100

você não pode fazer printf("address of constant is %p",&mymax);.

Mas ter

const int mymax_var=100

você pode fazer printf("address of constant is %p",&mymax_var);.

Para ser mais claro, a definição é substituída por seu valor no estágio de pré-processamento, portanto, não temos nenhuma variável armazenada no programa. Temos apenas o código do segmento de texto do programa em que a definição foi usada.

No entanto, para const estático, temos uma variável que está alocada em algum lugar. Para o gcc, a const estática é alocada no segmento de texto do programa.

Acima, eu queria falar sobre o operador de referência, para substituir a desreferência por referência.

mihaitzateo
fonte
1
Sua resposta está muito errada. É sobre C, sua resposta está relacionada ao C ++, que possui semânticas muito diferentes para o constqualificador. C não possui constantes simbólicas que não sejam constantes enum . A const inté uma variável. Você também confunde linguagem e implementações específicas. Não há exigência de onde colocar o objeto. E isso nem é verdade para o gcc: normalmente ele coloca constvariáveis ​​qualificadas na .rodataseção. Mas isso depende da plataforma de destino. E você quer dizer o endereço do operador &.
muito honesto para este site
0

Examinamos o código assembler produzido no MBF16X ... Ambas as variantes resultam no mesmo código para operações aritméticas (ADD Imediato, por exemplo).

Portanto, const inté preferível para a verificação de tipo enquanto #defineestiver no estilo antigo. Talvez seja específico do compilador. Portanto, verifique o código do assembler produzido.

hóspede
fonte
-1

Não tenho certeza se estou certo, mas na minha opinião chamando #define valor d é muito mais rápido do que chamar qualquer outra variável normalmente declarada (ou valor const). É porque quando o programa está sendo executado e ele precisa usar alguma variável declarada normalmente, ele precisa pular para o local exato na memória para obter essa variável.

Ao contrário, quando usa o #definevalor d, o programa não precisa pular para nenhuma memória alocada, apenas aceita o valor. Se #define myValue 7e a chamada do programa myValue, ele se comporta exatamente da mesma maneira que quando apenas chama 7.

pajczur
fonte