Forum: Mikrocontroller und Digitale Elektronik problem mit include


von Rolf R. (ultra-low)


Lesenswert?

hallo

ich binde die datei test.c mit #include "test.c" ein. nun wenn ich in 
dieser datei irgendein c code schreibe ausser #define dann gibt der 
compiler fehler aus.
ein beispiel:
    uint8_t var_1;

../test.c:1: error: expected '=', ',', ';', 'asm' or '__attribute__' 
before 'var_1'


ich vermute dass bei compiler zusätzlich was eingestellt werden muss 
dass die include datei "ganz normal" eingegunden wird.

meine prog. umgebung: xp, avrstudio 4.16, winavr 20081205

gruss

von Draco (Gast)


Lesenswert?

Weil der Compiler uint8_t nicht als Datentyp kennt, denkt er Du möchtest 
einen Wert zuweisen. Vermutlich hast Du einfach das #include <..> für 
das .h-File vergessen, in dem der Typ uint8_t definiert ist.

Du solltest übrigens keine *.c Files per Include einbinden. Include ist 
für *.h Files. Wenn Du mehrere *.c Files brauchst, dann kannst Du die 
einzeln kompilieren und dann beim Linken alle *.o Files angeben oder Du 
gibst dem Compiler gleich eine Liste der *.c Files die er zu einem 
Executable machen soll. Schau Dir einfach mal ein x-beliebiges Makefile 
an, da kann man sehen wie das gemacht wird.

von Martin (Gast)


Lesenswert?

Du kannst nur Header dateien includen. Die C-Datei musst du zum Projekt 
hinzufügen.

von Rolf R. (ultra-low)


Angehängte Dateien:

Lesenswert?

habs in projekt eingebunden. aber die fehlermeldung kommt immer noch...

ps:die betreffende datei heisst "global_var_def.c"

von P. S. (Gast)


Lesenswert?

Man kann mit #include alles includen. Egal ob .h, .c, .txt, .schnitzel 
oder sonstwas. Der Praeprozessor fuegt den Teil einfach ein, basta - nur 
syntaktisch korrekt muss das Resultat sein.

Um Rolfs Problem zu loesen, muesste er schon ein wenig mehr zeigen. 
Mindestens das File das den include macht und das komplette test.c.

von Rolf R. (ultra-low)


Angehängte Dateien:

Lesenswert?

Man kann mit #include alles includen. Egal ob .h, .c, .txt, .schnitzel
oder sonstwas. Der Praeprozessor fuegt den Teil einfach ein, basta - nur
syntaktisch korrekt muss das Resultat sein.

@ Peter Stegemann

das habe ich auch gemeint. mehr möchte ich auch nicht. in meiner 
referenz steht auch "Der Präprozessor entfernt die #include-Zeile und 
ersetzt sie durch den gesamten Quelltext der Include-Datei. Die 
Quelltextdatei selbst wird nicht physisch verändert, der Compiler erhält 
jedoch den modifizierten Text zur Übersetzung. "

dem scheint es aber nicht so zu sein...

hier ist gleich makefile

######################################################################## 
#######
# Makefile for the project projekt_1
######################################################################## 
#######

## General Flags
PROJECT = projekt_1
MCU = atmega644p
TARGET = projekt_1.elf
CC = avr-gcc

## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)

## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
CFLAGS += -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d

## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2

## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS +=  -SRC=$(TARGET).c-globals.c  -Wl,-Map=projekt_1.map


## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature

HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings


## Objects that must be built in order to link
OBJECTS = projekt_1.o globals.o

## Objects explicitly added by the user
LINKONLYOBJECTS =

## Build
all: $(TARGET) projekt_1.hex projekt_1.eep projekt_1.lss size

## Compile
projekt_1.o: ../projekt_1.c
  $(CC) $(INCLUDES) $(CFLAGS) -c  $<

globals.o: ../globals.c
  $(CC) $(INCLUDES) $(CFLAGS) -c  $<

##Link
$(TARGET): $(OBJECTS)
   $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o 
$(TARGET)

%.hex: $(TARGET)
  avr-objcopy -O ihex $(HEX_FLASH_FLAGS)  $< $@

%.eep: $(TARGET)
  -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0

%.lss: $(TARGET)
  avr-objdump -h -S $< > $@

size: ${TARGET}
  @echo
  @avr-size -C --mcu=${MCU} ${TARGET}

## Clean target
.PHONY: clean
clean:
  -rm -rf $(OBJECTS) projekt_1.elf dep/* projekt_1.hex projekt_1.eep 
projekt_1.lss projekt_1.map


## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)

von Johannes M. (johnny-m)


Lesenswert?

Um es mal zu präzisieren:
Die übliche Vorgehensweise, um syntaktische Probleme zu vermeiden, ist 
das erstellen einer Headerdatei (*.h) zu jeder .c-Datei, in der sich 
ausschließlich Deklarationen (jedoch keine Definitionen ) aller 
Objekte befinden, die in der dazugehörigen .c-Datei definiert sind und 
die für andere Module (andere .c-Dateien) sichtbar sein sollen. Und nur 
die .h-Dateien werden dann mit #include eingebunden.

Außer Variablen-/Funktionsdeklarationen können in Headerdateien auch 
Typdfinitionen (typedef) und Präprozessormakros stehen. Das war es dann 
aber auch schon fast...

Normalerweise bindet man Quelldateien tatsächlich nicht mit #include 
ein. Klar, man kann alles einbinden, aber nur in wenigen Fällen macht 
das Sinn.

von Johannes M. (johnny-m)


Lesenswert?

Sag mal, geht's noch? Du sollst den Quellcode posten und nicht 
irgendwelche unsinnigen Screenshots! Das Dateiformat für C-Code heißt 
nicht .jpg, sondern .c!

von ... .. (docean) Benutzerseite


Lesenswert?

stell die linker Optionen wieder zurück, das macht avrstudio schon von 
alleine

siehe unten die Ausgabe des Compilers...

Er versucht die globals.c zum compiliern, was natürlich fehlschlägt...

Jede .c braucht alle includes die sie selber brauch.

Such mal nach globlane Variablen hier im Forum, da wird dir geholfen...

von P. S. (Gast)


Lesenswert?

Rolf Riller wrote:

> @ Peter Stegemann

> dem scheint es aber nicht so zu sein...

Doch doch, dein projekt_1.c uebersetzt auch einwandfrei. Nur hast du 
globals.c nochmal separat im Projekt - und das File alleine kann der 
Compiler so nicht uebersetzen. Und selbst wenn er koennte, du haettest 
den Inhalt dann doppelt, was beim Linken wieder krachen duerfte, weil du 
so doppelte Symbole bekommst. Ach das liesse sich loesen, fuehrt aber 
hier wohl zu weit...

Man kann zwar mit #include machen was man moechte, wenn man aber nicht 
genau weiss, was man tut, haelt man sich besser an die von Johannes 
beschriebenen Konventionen ;-)

Ich denke was du willst ist ein globals.c, das selbstaendig uebersetzt 
(also alle noetigen includes machen!) und ein globals.h, dass die 
Variablen extern deklariert und von den anderen Dateien eingebunden 
wird. Wie ....... schon schrieb, muss das mehrfach hier im Forum 
beschrieben sein.

von Rolf R. (ultra-low)


Lesenswert?

gut. danke. habe jetzt in globals.c "#include <avr/io.h> " eingefügt und 
beim compilieren ergeben sich jetzt keine fehler.

von Karl H. (kbuchegg)


Lesenswert?

Und nein, das hat nichts mit Compiler oder Linker-Einstellungen zu tun.

Mein Tip ist übrigens, dass dir ein

#include <inttypes.h>

an irgendeiner Stelle fehlt.

von Rolf R. (ultra-low)


Lesenswert?

also ich kriegs nicht auf die reihe.

kann mir jemand ein tutoriallink geben wo erklärt wird wie man diese 
problematik bewerkstelligt:

--- hauptfile.c -----
int main()
  {
    var_1 = 1;
    var_2 = 1;
    func_1();
    func_2();
  }

--- module_1.c ------
int var_1;
void func_1()
  {
    var_2 = 1;
    func_2();
  }

--- module_2.c -------
int var_2;
void func_2()
  {
    var_1 = 1;
    func_1();
  }

was ich möchte ist dass man "kreuz und querz" aufrufe tätigen kann, wie 
man das von php oder vb.net kennt. dort includet man das nötige modul 
mit seinen funktionen und variablen und gut ist es. meine hausaufgaben 
habe ich schon gemacht nämlich sämtliche foren durchsucht usw. da wird 
zwar viel geredet aber nichts konkretes.

danke im voraus

von Karl H. (kbuchegg)


Lesenswert?


von P. S. (Gast)


Lesenswert?

Du solltest dir ein C-Buch zulegen. Das sind absolute Grundlagen, kaum 
einer hier wird Lust haben, einen C-Kurs abzuhalten.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Einfach:

--- hauptfile.c -----
#include "module_1.h"
#include "module_2.h"

int main()
  {
    var_1 = 1;
    var_2 = 1;
    func_1();
    func_2();
  }

--- module_1.c ------
#include "module_2.h"

int var_1;
void func_1()
  {
    var_2 = 1;
    func_2();
  }

--- module_2.c -------
#include "module_1.h"

int var_2;
void func_2()
  {
    var_1 = 1;
    func_1();
  }

--- module_1.h ------
extern int var_1;
void func_1();

--- module_2.h -------
extern int var_2;
void func_2();

von Marco G. (stan)


Lesenswert?


von Karl H. (kbuchegg)


Lesenswert?

zunächst mal überlegst du dir, welche Informationen für module_1.c bzw. 
module_2.c 'nach aussen' sichtbar sein sollen.

Für module_1.c sind das
  * Es gibt eine Variable var_1
  * Es gibt eine Funktion func_1

Für module_2.c sind das
  * Es gibt eine Variable var_2
  * Es gibt eine Funktion func_2

Dann legst du dir für jedes der beiden *.c Files ein entsprechendes 
Header File an. Sinnvollerweise nennt man das Header File gleich wie das 
zugehörige *.c File, nur kriegt es die Endung *.h

In diese Header Files kommen die Deklarationen für alle Dinge, die vom 
*.c File exportiert werden, also von aussen sichtbar sein sollen

In deinem Beispiel sind das

--- module_1.h ------
1
extern int var_1;
2
3
void func_1();

und

--- module_2.h -------
1
extern int var_2;
2
void func_2();

Wie werden sie jetzt verwendet?
Ganz einfach.
Jedes *.c, dass eine Funktionalität aus einem anderen *.c benutzen will, 
includiert das entsprechende Header File. Sinnvollerweise wird das 
definierende C-File auch sein eigenes Header File includieren. Damit 
ermöglicht man dem Compiler eine gewisse Prüfung, ob beides auch 
zusammenstimmt und wenn man eigene Datentypen definiert (Strukture, 
Unions) führt sowieso an diesem Include kein Weg vorbei

Konkret:

--- hauptfile.c -----
1
#include "module_1.h"    // stellt var_1  und func_1  bereit
2
#include "module_2.h"    // stellt var_2  und func_2  bereit
3
4
int main()
5
{
6
  var_1 = 1;
7
  var_2 = 1;
8
  func_1();
9
  func_2();
10
}

--- module_1.c ------
1
#include "module_1.h"
2
3
int var_1;
4
void func_1()
5
{
6
  var_2 = 1;
7
  func_2();
8
}

--- module_2.c -------
1
#include "module_2.h"
2
#include "module_1.h"   // weil ja var_1 und func_1 benutzt werden sollen
3
4
int var_2;
5
void func_2()
6
{
7
  var_1 = 1;
8
  func_1();
9
}

von Rolf R. (ultra-low)


Lesenswert?

super. danke. besser hätte man das nicht erklären können.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Das funktioniert so nicht:

-- module_1.c ------
1
#include "module_1.h"
2
3
int var_1;
4
void func_1()
5
{
6
  var_2 = 1;
7
  func_2();
8
}

Hier wird auf Dinge zugegriffen, die im Modul2 definiert sind. Also muss 
auch --wie ich es weiter oben schon gezeigt habe-- auch module_2.h 
eingebunden werden.

Pedanterie:
s/dass/das/

von Rolf R. (ultra-low)


Lesenswert?

habe schon getestet. alles bestens.

von Karl H. (kbuchegg)


Lesenswert?

Rufus t. Firefly wrote:
> Das funktioniert so nicht:
> Hier wird auf Dinge zugegriffen, die im Modul2 definiert sind.

Oops. Hab ich übersehen.
Danke für den Fix.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.