Verständnis von C-Namespaces

Lesezeit: 3 Minuten

Benutzer-Avatar
Laser

Zitat von hier,

In C gibt es zwei verschiedene Namespaces von Typen: einen Namespace von struct/union/enum-Tag-Namen und einen Namespace von typedef-Namen.

name.c

$ cat name.c
#include<stdio.h>

typedef long long long2;

int long2 () {
    return 4;
}

int main() {

    printf("hello, world!");
    return 0;
}
$ gcc name.c -o name
name.c:4: error: 'long2' redeclared as different kind of symbol
name.c:3: error: previous declaration of 'long2' was here
$

name2.c

$ cat name2.c
#include<stdio.h>

int four() {
    return 4;
}

struct dummy {
    int member;
};

int main() {

    struct dummy four;
}

$ gcc name2.c -o name2
$ 

Ich versuche, C-Namespace-Konflikte zu verstehen.

  • Warum gibt es im ersten Fall einen Konflikt? Gehören auch Funktionen zum Typedef-Namensraum?

  • Warum gibt es im zweiten Fall überhaupt keinen Konflikt? Die Funktion und die Variable heißen beide vier. Warum lässt der Compiler das zu? Wie ist &four soll gelöst werden?

Benutzer-Avatar
schott

C hat vier verschiedene Namensräume für Bezeichner:

  • Markennamen (die goto Typ).
  • Tags (Namen von Strukturen, Vereinigungen und Aufzählungen).
  • Mitglieder von Strukturen und Unions (diese haben einen eigenen Namensraum pro Struktur/Union).
  • Alle anderen Bezeichner (Funktionsnamen, Objektnamen, Typ(def)-Namen, Aufzählungskonstanten usw.).

Siehe auch C99 6.2.3.

Ihre beiden Fragen können also wie folgt beantwortet werden:

  1. Ja, Funktionsnamen und Typedef-Namen teilen sich denselben Namensraum.
  2. Kein Konflikt, da der Compiler Bereichsregeln (für Funktions- oder Objektnamen) verwendet. Der Bezeichner in der Hauptsache wird gesagt Schatten den globalen Funktionsnamen, wovor Ihr Compiler Sie warnen wird, wenn Sie die Warnstufen hoch genug setzen.

  • Teilen sich Structs/Unions/Enums einen Namensraum? dh kann struct T und union T passen gut zusammen?

    – iBug

    17. November 2017 um 10:00 Uhr

  • iBug, nein, das können sie nicht, da struct, unions und enumerations den gleichen Namensraum (Tags-Namensraum) teilen.

    – dandev486

    18. August um 11:39 Uhr

Benutzer-Avatar
kennytm

Aber der entscheidende Punkt in Ihren Beispielen ist nicht der Namensraum, sondern der Umfang der Namen.

Im name.cbeide long2 sind “normale Bezeichner” (haben denselben Namensraum), und beide sind im selben Bereich definiert, sodass ein Konflikt besteht. (C99 §6.7/3)

Wenn name2.cdie lokale Variable four ist in einem Bereich, der tiefer ist als die Funktion fouralso die Variable verbirgt sich die Funktion four (C99 §6.2.1/4).

Benutzer-Avatar
pmg

Ihr 2. Beispiel zeigt nicht “kein Konflikt”. Es gibt einen Konflikt! Versuche dies:

#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
    struct dummy four;
    four.member = four();
}

Und jetzt das

#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
    int (*fx)(void) = four; /* "save" function */
    struct dummy four;     /* hide it         */
    four.member = fx();    /* use "hidden" fx */
}

In Ihrem 2. Beispiel die Variable four verbirgt sich die Funktion four().

Um deine zwei Fragen schnell zu beantworten.

Q1. Warum gibt es im ersten Fall einen Konflikt? Gehören auch Funktionen zum Typedef-Namensraum?

A1. Ja, Kennungen für Funktionen und typdefinierte Typen denselben Namensraum teilen. Es gibt also einen Konflikt.

Q2. Warum gibt es im zweiten Fall überhaupt keinen Konflikt? Die Funktion und die Variable heißen beide vier. Warum lässt der Compiler das zu? Wie soll &four aufgelöst werden?

A2. In Ihrem zweiten Beispiel gibt es keinen Konflikt, obwohl die beiden genannten Bezeichner vier gehören zum selben Bezeichner-Namespace, der ist Ordinary namespace. Denn der Variablenbezeichner vier in der Hauptsache ist in a Funktionsumfangwährend die Funktionskennung vier in einem Dateibereich. Letzteres wird also von ersterem als grundlegende Geltungsbereichsregel verdeckt. Wenn Sie die Variable verschieben vier zum Dateibereich (global) wie unten, sehen Sie einen Fehler.

...

struct dummy four; // Error! there's a previous definition
                   // in this file scope(global).

int main() {
    // struct dummy four; // Commented out.
}

Tatsächlich gibt es vier verschiedene Namensräume für Bezeichner: Etikett, Schild, Mitgliedund Ordinär. Details dazu finden Sie unter https://en.cppreference.com/w/c/language/name_space

1371720cookie-checkVerständnis von C-Namespaces

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy