c präprozessor

Post Reply
Message
Author
blubb

c präprozessor

#1 Post by blubb »

tag auch,

folgendes problem:
habe eine string_defs.h in der einige deklarationen stehen, jetzt habe ich auch eine main.c (wow ;D) und eine action_funcs.c etc.
in beiden habe ich drinnen stehen:

Code: Select all

#ifndef STRING_DEFS_H
#include "string_defs.h"
#endif
in der string_defs.h steht:

Code: Select all

#ifndef STRING_DEFS_H
#define STRING_DEFS_H
... code ...
#endif
beim compilieren meckert er aber das die strings mehrfach deklariert werden.
weis wer wo das problem liegt? :/

blubb

JochenAlsGast

#2 Post by JochenAlsGast »

Das sieht mir nicht unbedingt falsch aus. Höchsten dass das #ifndef/#endif um das #include herum überfüssig ist. Zum Testen habe ich mal eben was zusammen gepröttelt:

Code: Select all

/* Header */

#ifndef A_H
#define A_H

#define HALLO "Hallo Welt\n"

#endif
Und dazu:

Code: Select all

/* Source */

/* Erstes Mal: Alles definieren */
#include "a.h"
/* Zweites Mal: Ist schon definiert, #ifndef A_H darf nicht mehr greifen */
#include "a.h"

#include <stdio.h>

int main &#40;void&#41; &#123;
        printf &#40;HALLO&#41;;
        exit &#40;0&#41;;
&#125;
Wenn ich die als a.h und a.c abspeichere und mittels "make a" übersetze, erhalte ich keine Fehlermeldungen. Ich würde mal tippen, das der Fehler bei Dir irgendwo anders liegt...?

Jochen

blubb

#3 Post by blubb »

hmm,

ich poste mal die praeprozessor anweisungen von jedem file und den gcc fehler.
string_defs.h:

Code: Select all


#ifndef STRING_DEFS_H
#define STRING_DEFS_H

static struct part_table
&#123;

      char swap&#91;30&#93;;
      char root&#91;30&#93;;
      char fs&#91;15&#93;;
&#125;hdd_info;


char *main_choices&#91;&#93; =
&#123;
   "1&#41; Keymap",
     "2&#41; Swap partition",
...
action_funcs.c

Code: Select all

#include <errno.h>
#include <dirent.h>
#include "string_defs.h"
#include "action_funcs.h"
set_funcs.c:

Code: Select all

#include "string_defs.h"
#include "set_funcs.h"
#include <ncurses.h>
und die letzte; window_funcs.c

Code: Select all

#ifndef WINDOW_FUNCS_H
#define WINDOW_FUNCS_H
#include <stdio.h>
#include <ncurses.h>
#include "string_defs.h"
also ich denk von den header files her sollte alles passen, ich checks auch nich... ich kann auch mal die komplette string_defs.h posten wenn das was bringt...

blubb

User avatar
jochen
prolinux-forum-admin
Posts: 699
Joined: 14. Jan 2000 15:37
Location: Jülich
Contact:

#4 Post by jochen »

Der gcc-Fehler fehlt noch.

Jochen
Die grösste Lüge der EDV? "Mal eben..."

blubb

#5 Post by blubb »

sry, voll verpeilt :D

Code: Select all

main.o&#40;.data+0x0&#41;&#58; multiple definition of `main_choices'
action_funcs.o&#40;.data+0x0&#41;&#58; first defined here
main.o&#40;.data+0x1c&#41;&#58; multiple definition of `keymap_choices'
action_funcs.o&#40;.data+0x1c&#41;&#58; first defined here
main.o&#40;.data+0x2c&#41;&#58; multiple definition of `fs_choices'
action_funcs.o&#40;.data+0x2c&#41;&#58; first defined here
main.o&#40;.data+0x40&#41;&#58; multiple definition of `info_choices'
action_funcs.o&#40;.data+0x40&#41;&#58; first defined here
main.o&#40;.data+0x60&#41;&#58; multiple definition of `welcome_choices'
action_funcs.o&#40;.data+0x60&#41;&#58; first defined here
set_funcs.o&#40;.data+0x0&#41;&#58; multiple definition of `main_choices'
action_funcs.o&#40;.data+0x0&#41;&#58; first defined here
set_funcs.o&#40;.data+0x1c&#41;&#58; multiple definition of `keymap_choices'
action_funcs.o&#40;.data+0x1c&#41;&#58; first defined here
set_funcs.o&#40;.data+0x2c&#41;&#58; multiple definition of `fs_choices'
action_funcs.o&#40;.data+0x2c&#41;&#58; first defined here
set_funcs.o&#40;.data+0x40&#41;&#58; multiple definition of `info_choices'
action_funcs.o&#40;.data+0x40&#41;&#58; first defined here
set_funcs.o&#40;.data+0x60&#41;&#58; multiple definition of `welcome_choices'
action_funcs.o&#40;.data+0x60&#41;&#58; first defined here
window_funcs.o&#40;.data+0x0&#41;&#58; multiple definition of `main_choices'
action_funcs.o&#40;.data+0x0&#41;&#58; first defined here
window_funcs.o&#40;.data+0x1c&#41;&#58; multiple definition of `keymap_choices'
action_funcs.o&#40;.data+0x1c&#41;&#58; first defined here
window_funcs.o&#40;.data+0x2c&#41;&#58; multiple definition of `fs_choices'
action_funcs.o&#40;.data+0x2c&#41;&#58; first defined here
window_funcs.o&#40;.data+0x40&#41;&#58; multiple definition of `info_choices'
action_funcs.o&#40;.data+0x40&#41;&#58; first defined here
window_funcs.o&#40;.data+0x60&#41;&#58; multiple definition of `welcome_choices'
action_funcs.o&#40;.data+0x60&#41;&#58; first defined here
collect2&#58; ld returned 1 exit status

User avatar
jochen
prolinux-forum-admin
Posts: 699
Joined: 14. Jan 2000 15:37
Location: Jülich
Contact:

#6 Post by jochen »

Ah, jetzt wird es klarer.

Der C-Präprozessor hat damit nix zu tun. Die Fehlermeldungen stammen vom Linker, der in unterschiedlichen Object-Files gleichnamige Data-Objekte findet.

Der C-Compiler unterscheidet zwischen der Deklaration und der Definition einer Variablen. "Deklaration" heisst, Du sagst Deinem Compiler, dass es irgendwo eine Variable diesen Namens gibt. Deklarationen kannst Du so viele haben wie Du willst. "Definition"dagegen bedeutet, dass der Compiler für diese Variabe auch tatsächlich Speicherplatz bereitstellen soll.

In Deiner Header-Datei stehen Definitionen, d.h. Du verlangst, dass eine Variable diesen Namens angelegt und Speicherplatz dafür reserviert wird. Jede .c-Datei, die dieses Header-File #includet, bekommt eine ganz eigene Version dieser Variable mit ihrem ganz eigenen Speicherplatz. Da jede .c-Datei eine abgeschlossene Kompilationseinheit ist (d.h. der Compiler weiss nichts von gleichlautenden Variablen in anderen .c-Dateien), geht das solange gut, bis die erzeugten Object-Files gelinkt werden sollen. Dann sieht der Linker eine Variable "main_choices" in action_funcs.o, eine in set_funcs.o usw. Wegen dieses Namenskonfliktes geht das Linken dann in die Hose.

Du musst also im Header-File aus den Definitionen Deklarationen machen: Aus

Code: Select all

static struct part_table
&#123;

      char swap&#91;30&#93;;
      char root&#91;30&#93;;
      char fs&#91;15&#93;;
&#125;hdd_info; 
musst Du ein

Code: Select all

extern struct part_table
&#123;

      char swap&#91;30&#93;;
      char root&#91;30&#93;;
      char fs&#91;15&#93;;
&#125;hdd_info; 
machen. In irgendeiner passenden .c-Datei gehört dann natürlich noch die Definition der Variablen hinein:

Code: Select all

struct part_table hdd_info
Mache diese Variable aber nicht static! Damit würdest Du die Variable privat für die .c-Datei definieren und die anderen Objectfiles bekämen diese nicht zu sehen und könnten dann ihre Verweise auf die Variable beim Linken nicht aufgelöst bekommen.


Jochen
Die grösste Lüge der EDV? "Mal eben..."

blubb

#7 Post by blubb »

super, danke, endlich erscheint mir das alles logischer ;)
werds gleich mal probieren

big thx

blubb

blubb

#8 Post by blubb »

eine frage noch; wie soll ich das dann mit den ganzen strings machen?

zb.:

Code: Select all

char *main_choices&#91;&#93; =
&#123;
   "1&#41; Keymap",
     "2&#41; Swap partition",
     "3&#41; Root partition",
     "4&#41; FS Type",
     "5&#41; Install",
     "6&#41; Config",
     "7&#41; Exit",
&#125;;
soll ich einfach ein extern vor das char schreiben? weil das ist ja eine definition, oder gibts so probs...?

blubb

#9 Post by blubb »

das ist jetzt etwas bloed weil ich die definition in mehreren c files brauche, und somit bin ich wieder beim alten problem... da muesste ich alles neu schreiben...
werd wohl einfach alles in eine datei packen, beim naechsten mal weis ichs...

blubb

_MP_
Posts: 45
Joined: 04. Sep 2004 10:35

#10 Post by _MP_ »

blubb wrote:soll ich einfach ein extern vor das char schreiben
Jepp, genau so. Wobei man globale Variablen aber eigentlich vermeiden sollte. Vielleicht wäre es besser, wenn du dein Programm ein wenig umstrukturierst? Für mich sieht das aus, als ob eine separate drawMenu()-Funktion für dich genau das richtige ist, in der dann dieses Menü aus deinem char-Array gezeichnet/ausgegeben wird.

User avatar
jochen
prolinux-forum-admin
Posts: 699
Joined: 14. Jan 2000 15:37
Location: Jülich
Contact:

#11 Post by jochen »

Hi,

ich war die letzte Zeit etwas netzfern und konnte daher nicht weiter posten. Ich hoffe, es ist noch nicht zu spät?...

Ich habe die Vorgehensweise mal in ein paar Dateien gepackt.

Code: Select all

/* Datei a.h */
#ifndef A_H
#define A_H

struct gruss &#123;
        char *hallo;
        char *welt;
&#125;;

extern struct gruss meingruss;

#endif
Hier ist die Deklaration der Struktur und einer globalen Variablen "meingruss". Da hier noch kein Speicher bereitgestellt wird, kann auch keine Initialisierung erfolgen!

Code: Select all

/* Datei a.c */
#include "a.h"
#include "b.h"

struct gruss  meingruss = &#123; "Hallo", "Welt" &#125;;

int main &#40;void&#41; &#123;
        sei_freundlich&#40;&#41;;
        return 0;
&#125;
Hier ist jetzt die Definition zu finden! Und da hier Speicherplatz bereitgestellt wird, kann auch die Initialisierung erfolgen.

Code: Select all

/* Datei b.h */
#ifndef B_H
#define B_H

void sei_freundlich&#40;void&#41;;

#endif
Damit a.c von der Funktion in b.c erfährt, muss der Prototyp der Funktion bekanntgemacht werden. Das geschieht in der Headerdatei. Jetzt der Source-Code:

Code: Select all

/* Datei b.c */
#include <stdio.h>
#include "a.h"
#include "b.h"

void sei_freundlich&#40;void&#41; &#123;
        printf &#40;"%s %s\n",meingruss.hallo, meingruss.welt&#41;;
&#125;
Hier wird auf die globale Variable meingruss zugefriffen. Aus a.h weiss die Funktion, dass es sie gibt und welchen Typ sie hat. Daher kann der Compiler die Datei übersetzen. Beim Linken wird der Verweis auf die in a.c definierte Variable gesetzt.

So, sind jetzt alle Klarheiten beseitigt? ;-) Allerdings möchte ich mich _MP_ anschliessen: Dieser Aufbau ist nicht gerade elegant. Das Handeln eines Menus sollte sich sehr schön kapseln lassen, so dass Du nach Aufruf einer menu-Funktion nur definierte Rückgabewerte (in der .h-Datei als #defines gesetzte int-Konstanten) zu verarbeiten brauchst...

Jochen
Die grösste Lüge der EDV? "Mal eben..."

Post Reply