Question

Quand on initialise un tableau comme celui-ci int a[5] = {0}, le compilateur fait tous les 5 éléments 0. C'est vraiment bon, l'initialisation-compact et fonctionnalité utile.

Mais je me demande pourquoi le compilateur ne initialize int a[5]={1} De même? Pourquoi il ne fait pas les 5 éléments 1? Pourquoi la norme ne prescrit pas? Ne serait-il pas été une caractéristique impressionnante? Est-il pas manque?

En outre, si le nombre d'éléments dans l'initialiseur est inférieure à la taille du tableau, la compilation peut initialiser les éléments restants avec le dernier élément de l'initialiseur. Les moyens, int a[5]={1,2,3} équivaut à int a[5]={1,2,3,3,3}. Et de même, int a[10]={1,2,3,0} équivaut à int a[10]={1,2,3,0,0,0,0,0,0,0};.

Ne serait-il tout ne pas être une caractéristique impressionnante si les mandats standard il? Ou est-il des bonnes raisons pour cette fonctionnalité manquante?


Et il y a quelque chose appelé désigné initialiseur dans C99, qui est utilisé comme:

initialiseurs désignés peut être combiné avec initializers réguliers, dans l'exemple suivant:

int a[10] = {2, 4, [8]=9, 10}

Dans ce exemple, un [0] est initialisé à 2, a 1 est initialisé à 4, a [2] a [7] sont initialisés à 0, et [9] est initialisé à 10.

Tout à fait intéressant. Mais même cette fonction est en C ++.

Était-ce utile?

La solution

Je trouve personnellement plus « logique » (à savoir simple,) ayant une position par défaut au lieu initialiseur d'une autre règle de répéter dernier seulement pour les tableaux. Cela peut paraître « pratique » (à savoir utile), mais il est plus logique de l'OMI complexe.

Cela dit mais je pense que vous faites un grand erreur en essayant d'appliquer une logique à un langage comme C ++.

C ++ est un langage complexe dont les règles sont le résultat d'une longue histoire de l'évolution, et sa forme actuelle est le résultat du travail de nombreuses personnes et même des comités officiels (la dernière partie seule pourrait expliquer quoi que ce soit ).

Une langue comme C ++ ne peut pas être déduit par la logique, il doit être étudié comme l'histoire. Sauf si vous êtes Hari Seldon il n'y a vraiment aucun moyen que vous pouvez déduire l'histoire en utilisant le raisonnement logique.

Il y a des endroits de C ++ où vous allez souffrir beaucoup si vous essayez d'utiliser la logique au lieu d'étudier. Juste pour en nommer que quelques-uns ...

  • Pourquoi est statique d'expédition par défaut (par exemple mauvais )?
  • Pourquoi il n'y a aucun mot-clé pour le pointeur NULL?
  • Pourquoi la différence de deux non signé est non signé?
  • Pourquoi une somme entre un signé et un non signé est non signé?
  • Si "élément de Z_ {2 ^ n} " signifie non signés alors pourquoi tailles ne sont pas signés ?
  • Pourquoi std::string s; s=3.141592654; est parfaitement valide C ++?
  • Pourquoi en C ++ 0X i = i++ + 1; est un comportement non défini et i = ++i + 1; est valide?
  • Pourquoi double x=3.14; int y(int(x)); ne y moyenne sera de 3?

Autres conseils

Pourquoi il ne fait pas les 5 éléments 1?

Parce que tu es malentendu ce que signifie {}. (En fait, en C ++ la meilleure façon de le faire est {} plutôt que {0}). La {0} de syntaxe ne signifie pas que vous voulez tous les éléments du jeu global à zéro. Au contraire, il est dit que vous voulez un agrégat avec le premier élément zéro affecté à la variable indiquée (qui peut être un tableau ou un type de classe en C ++). Parce que l'agrégat a généralement plus de champs que qu'une valeur zéro, les autres éléments de l'ensemble sont default construit . La valeur par défaut d'un ou de type POD builtin est de mettre tous les champs à zéro, de sorte que vous avez effectivement définir l'agrégat entier à zéro.

Quant à savoir pourquoi précisément, considérez ce qui suit. Selon la norme actuelle, aucune des affirmations ci-dessous échouera:

struct abc
{
    char field1;
    int field2;
    char field3;
};

int main()
{
    abc example = {'a', static_cast<int>('b')};
    //All three asserts pass
    assert(example.field1 == 'a');
    assert(example.field2 == static_cast<int>('b'));
    assert(example.field3 == '\0');

    int example2[3] = {static_cast<int>('a'), 42};
    assert(example2[0] == static_cast<int>('a'));
    assert(example2[1] == 42);
    assert(example2[2] == 0);
}

Qu'est-ce que vous vous attendez à la valeur de field3 être dans votre changement norme proposée? Même si vous définissez comme le dernier élément du initialiseur global que vous avez montré ci-dessus, qui va briser la compatibilité avec le code existant qui suppose le reste des éléments sont construits par défaut.


EDIT:. Juste rendu compte que votre question est posée en termes de tableaux - mais la réponse est la même chose avec soit des structures ou des tableaux, donc il n'a pas d'importance

EDIT2:. Pour le rendre plus conforme à la norme, les références à la classe / structure ont été remplacés par « global » ci-dessous, qui couvre les cas de structures et tableaux

Oui, ils pourrait ont fait, mais ils ne l'ont pas, et il est beaucoup trop tard pour changer ce comportement. Les décisions derrière C et C ++ ont été faites avec la pensée donnée à la performance et le minimalisme à presque toutes les étapes, donc je suppose que, si rien d'autre, entre en jeu ici.

Une telle caractéristique ne me frappe pas comme tout ce qui impressionnant. Il est un morceau très simple de sucre syntaxique, et je trouve rarement la nécessité d'initialiser un tableau comme ça pour autre chose que 0 de toute façon.

bibliothèques d'exécution typiques offrent une caractéristique qui le rend facile à initialiser des données à 0. En termes généraux, cela est stocké dans un section dans le fichier exécutable, organisé par le compilateur et éditeur de liens. Au démarrage du programme, le démarrage du code d'exécution utilise quelque chose comme memset() pour effacer toutes les données initialisées à 0. Cela signifie que le zéro octets ne doivent pas être stockés à l'intérieur de l'exécutable lui-même.

L'inverse est que si vous initialisez données à quelque chose autre que zéro, les octets pour que les données doivent être stockées dans le fichier exécutable lui-même, puisque le Initialiser automatique seulement initialise à zéro.

Par conséquent, si vous deviez déclarer un grand tableau de char (disons un méga-octet?) Et initialisez avec, disons, {0}, alors il n'y aurait pas d'octets stockés dans le fichier exécutable pour ce tableau. D'autre part, si vous étiez à elle avec {1} sous initialiser votre système, un méga-octet d'octets de 1 devrait être stocké dans l'exécutable lui-même. En changeant un seul caractère dans la liste d'initialiser, la taille de l'exécutable augmente d'un méga-octet.

Je crois qu'un tel système serait contraire à la principe de moindre surprise .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top