Czy wolę stałe niż definiuje?

W C, czy wolę stałe niż definiuje? Czytam ostatnio dużo kodu i wszystkie przykłady mocno wykorzystują definicje.

Author: Thom Wiggers, 2010-02-22

10 answers

Nie, generalnie nie należy używać obiektów kwalifikowanych const w C do tworzenia stałych nazw. Aby utworzyć o nazwie stała W C należy użyć makr (#define) lub enums. W rzeczywistości, język C nie ma stałych, w tym sensie, że wydaje się sugerować. (C różni się znacząco od C++ pod tym względem)

W języku C pojęcia stała i wyrażenie stałe są definiowane zupełnie inaczej niż w C++. W C stała oznacza a literalna wartość , Jak 123. Oto kilka przykładów stałych W C

123
34.58
'x'

Stałe w C mogą być używane do budowania stałych wyrażeń. Jednakże, ponieważ obiekty kwalifikowane przez const dowolnego typu nie są stałymi W C, nie mogą być używane w wyrażeniach stałych, a zatem nie można używać obiektów kwalifikowanych przez const, w których wymagane są wyrażenia stałe.

Na przykład, poniższe nie jest stała

const int C = 123; /* C is not a constant!!! */

A ponieważ powyższa C nie jest stała, nie można jej użyć do zadeklarowania typu tablicy w obszarze pliku

typedef int TArray[C]; /* ERROR: constant expression required */

Nie może być używany jako etykieta przypadku

switch (i) {
  case C: ; /* ERROR: constant expression required */
}

Nie może być używany jako szerokość pola bitowego

struct S {
  int f : C; /* ERROR: constant expression required */
};

Nie może być użyty jako inicjalizator dla obiektu o statycznym czasie przechowywania

static int i = C; /* ERROR: constant expression required */

Nie może być używany jako inicjalizator enum

enum {
  E = C /* ERROR: constant expression required */
};

Tzn. nie może być używany wszędzie tam, gdzie stała jest wymagane.

Może to wydawać się sprzeczne z intuicją, ale tak definiuje się język C.

Dlatego widzisz te liczne #define-s w kodzie, z którym pracujesz. Ponownie, w języku C obiekty const-qualified mają bardzo ograniczone zastosowanie. Są one w zasadzie całkowicie bezużyteczne jako "stałe", dlatego w języku C jesteś zmuszony do używania #define lub enums do deklarowania prawdziwych stałych.

Oczywiście, w sytuacjach, gdy obiekt kwalifikowany const działa dla Ciebie, tj. robi to, co chcesz, jest rzeczywiście lepszy od makr pod wieloma względami, ponieważ jest ograniczony i wpisany. Prawdopodobnie powinieneś preferować takie obiekty w stosownych przypadkach, jednak w ogólnym przypadku będziesz musiał wziąć pod uwagę powyższe ograniczenia.

 97
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-25 05:25:48

Stałe powinny być preferowane przez defineS. istnieje kilka zalet:

  • Bezpieczeństwo Typu . Podczas gdy C jest słabo wpisywanym językiem, użycie define traci całe bezpieczeństwo typu, co pozwoli kompilatorowi wykryć problemy za Ciebie.

  • Łatwość debugowania . Możesz zmienić wartość stałych za pomocą debuggera, podczas gdy defineS są automatycznie zmieniane w kodzie przez pre-procesor na rzeczywistą wartość , oznacza to, że jeśli chcesz zmienić wartość dla celów testowania/debugowania, musisz ponownie skompilować.

 10
Author: LeopardSkinPillBoxHat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-22 01:07:21

Może używałem ich źle, ale przynajmniej w gcc nie można używać stałych w poleceniach case.

const int A=12;
switch (argc) {
    case A:
    break;
}
 7
Author: jbcreix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-22 01:08:16

Chociaż to pytanie jest specyficzne dla C, myślę, że dobrze jest to wiedzieć:

#include<stdio.h>
int main() {
    const int CON = 123;
    int* A = &CON;
    (*A)++;
    printf("%d\n", CON);  // 124 in C
}

Działa w C , ale nie w C++

Jednym z powodów użycia #define jest unikanie takich rzeczy, aby zepsuć kod, szczególnie jest to mieszanka C i C++.

 6
Author: Lazer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-12 16:47:00

Wiele osób tutaj daje Ci porady "C++ style". Niektórzy twierdzą nawet, że argumenty C++ odnoszą się do C. Może to być słuszna Uwaga. (Niezależnie od tego, czy jest to subiektywne, czy nie.) Ludzie, którzy mówią const czasami oznacza coś innego w obu językach są również poprawne.

Ale są to głównie drobne punkty i osobiście uważam, że w rzeczywistości jest stosunkowo niewielka konsekwencja pójścia w obie strony. To kwestia stylu i myślę, że różne grupy ludzi dadzą masz inne odpowiedzi.

Jeśli chodzi o powszechne użycie, historyczne użycie i najczęściej spotykany styl, w C jest o wiele bardziej typowe dla #define. Używanie C++isms w kodzie C może wydawać się dziwne dla pewnego wąskiego segmentu koderów C. (Łącznie ze mną, więc tam leżą moje uprzedzenia.)

Ale jestem zaskoczony, że nikt nie zaproponował rozwiązania pośredniego, które "wydaje się właściwe" w obu językach: jeśli pasuje do grupy stałych całkowitych, użyj enum.

 5
Author: asveikau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-22 02:11:47

Define może być używany do wielu celów (bardzo luźnych) i należy go unikać, jeśli można go zastąpić const, które definiują zmienną i można z nią zrobić dużo więcej.

W przypadkach takich jak poniżej należy użyć define

  • directive switch
  • zastąpienie linii źródłowej
  • makra kodu

Przykładem, w którym musisz użyć define over const jest sytuacja, gdy masz numer wersji powiedzmy 3 i chcesz, aby Wersja 4 zawierała pewne metody, które nie są dostępny w wersji 3

#define VERSION 4
...

#if VERSION==4
   ................
#endif 
 3
Author: Fadrian Sudaman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-22 01:08:51

Defines były częścią języka dłużej niż stałe, więc dużo starszego kodu będzie ich używać, ponieważ definiuje, gdzie jedynym sposobem na wykonanie zadania, gdy kod został napisany. Dla nowszego kodu może to być po prostu kwestia przyzwyczajenia programisty.

Stałe mają zarówno typ, jak i wartość, więc są preferowane, gdy ma to sens, aby Twoja wartość miała typ, ale nie wtedy ,gdy nie jest typowa (lub polimorficzna).

 2
Author: John Knoeller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-22 01:01:12

Jeśli jest to coś, co nie jest określone programowo, używam #define. Na przykład, jeśli chcę, aby wszystkie moje obiekty UI miały taką samą przestrzeń między nimi, mogę użyć #define kGUISpace 20.

 1
Author: David Kanarek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-22 00:59:12

Oprócz doskonałych powodów podanych przez Andreyta za używanie definicji zamiast stałych w kodzie "C" istnieje jeszcze jeden bardziej pragmatyczny powód używania definicji.

DEFINES są łatwe do zdefiniowania i użycia z (.h) pliki nagłówkowe, gdzie każdy doświadczony koder C spodziewałby się znaleźć zdefiniowane stałe. Definiowanie konst w plikach nagłówkowych nie jest takie proste - więcej kodu, aby uniknąć powielania definicji itp.

Również argumenty "typesafe" są dyskusyjne większość kompilatorów odbierze rażące błędy, takie jak assing string to and int, or, "do the right thing" na lekkim niedopasowaniu, takim jak przypisanie liczby całkowitej do float.

 1
Author: James Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-22 03:03:51

Makra (definiuje) mogą być używane przez pre-procesor i podczas kompilacji stałe nie mogą.

Możesz sprawdzić w czasie kompilacji, aby upewnić się, że makro mieści się w prawidłowym zakresie (i #błąd lub # fatal, jeśli nie jest). Możesz użyć wartości domyślnych dla makra, jeśli nie zostało ono jeszcze zdefiniowane. Możesz użyć makra o rozmiarze tablicy.

Kompilator może optymalizować za pomocą makr lepiej niż za pomocą stałych:

const int SIZE_A = 15;
#define SIZE_B 15

for (i = 0; i < SIZE_A + 1; ++i);    // if not optimized may load A and add 1 on each pass
for (i = 0; i < SIZE_B + 1; ++i);    // compiler will replace "SIZE_B + 1" with 16
Większość moich prac jest z wbudowanymi procesorami, które nie mają niesamowite Kompilatory optymalizujące. Może gcc potraktuje SIZE_A jak makro na jakimś poziomie optymalizacji.
 1
Author: tomlogic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-22 06:18:46