Prototypen anlegen mit struct

OP #2872408
Lesenswert?

Hi ich will von dieser Funktionen (s.unten) einen Prototypen anlegen.
So habe ich es versucht und es kommt ein Fehler:

In file included from relais.c:20:
relais.h:83: warning: 'struct Relais' declared inside parameter list
relais.h:83: warning: its scope is only this definition or declaration, 
which is probably not what you want
relais.c:104: error: conflicting types for 'RelaisSchalten'
relais.h:83: error: previous declaration of 'RelaisSchalten' was here

In der h.
1
uint16_t RelaisSchalten( struct Relais* theRelais);

Funktion sieht so aus:
1
uint16_t RelaisSchalten( struct Relais* theRelais)  
2
{
3

4
  AusgangSetBit( theRelais->bitToSet );
5
  AusgangUnsetBit( theRelais->bitToClear ); 
6
  AusgangOut();
7

8
  theRelais->setCycles++;
9

10
 
11
  if (theRelais->setCycles >= 200)
12
    {
13
    AusgangUnsetBit( theRelais->bitToSet ); 
14
    AusgangUnsetBit( theRelais->bitToClear ); 
15
    AusgangOut();
16

17
    theRelais->setCycles = 0;
18
    return true;
19
    }  
20

21
  return false;
22
}


Was mache ich falsch?
OP #2872419
Lesenswert?

Hi Mario,

das habe ich ja gemacht...Dann kommt dieser Fehler:


Linking: Hexfiles/MEGA1284_P.elf
avr-gcc -mmcu=atmega1284p -I. -Os -funsigned-char -funsigned-bitfields 
-fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o 
-fno-inline-small-functions -fno-split-wide-types 
-fno-move-loop-invariants -mcall-prologues -ffunction-sections 
-fdata-sections -Wl,--gc-sections -Wl,--relax -std=gnu99 main.o usart.o 
stack.o timer.o cmd.o base64.o networkcard/enc28j60.o httpd.o telnetd.o 
ntp.o wol.o http_get.o sendmail.o dnsc.o dhcpc.o infrared/rc5.o 
1-wire/crc8.o 1-wire/ds18x20.o 1-wire/messung.o 1-wire/onewire.o 
udp_send/udp_send.o com74hc595.o R_TRIG.o relais.o email.o jalousie.o 
--output Hexfiles/MEGA1284_P.elf -Wl,-Map=Hexfiles/MEGA1284_P.map,--cref 
-lm
httpd.o:(.data.K1_Ein+0x0): multiple definition of `K1_Ein'
main.o:(.data.K1_Ein+0x0): first defined here
c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/bin/ld.exe: 
Disabling relaxation: it will not work with multiple definitions
httpd.o:(.data.K1_Aus+0x0): multiple definition of `K1_Aus'
main.o:(.data.K1_Aus+0x0): first defined here
httpd.o:(.data.K2_Ein+0x0): multiple definition of `K2_Ein'
main.o:(.data.K2_Ein+0x0): first defined here
httpd.o:(.data.K2_Aus+0x0): multiple definition of `K2_Aus'
main.o:(.data.K2_Aus+0x0): first defined here
httpd.o:(.data.K3_Ein+0x0): multiple definition of `K3_Ein'
main.o:(.data.K3_Ein+0x0): first defined here
httpd.o:(.data.K3_Aus+0x0): multiple definition of `K3_Aus'
main.o:(.data.K3_Aus+0x0): first defined here
httpd.o:(.data.K4_Ein+0x0): multiple definition of `K4_Ein'
main.o:(.data.K4_Ein+0x0): first defined here
httpd.o:(.data.K4_Aus+0x0): multiple definition of `K4_Aus'
main.o:(.data.K4_Aus+0x0): first defined here
httpd.o:(.data.K5_Ein+0x0): multiple definition of `K5_Ein'
main.o:(.data.K5_Ein+0x0): first defined here


usw...................


So sieht das dann aus in der .h
1
struct Relais {
2
   uint16_t   bitToSet; 
3
   uint16_t   bitToClear;
4
   uint16_t   setCycles;     // Zaehlt die 0-Durchgänge bis zum Abschalten
5
};
6

7

8
struct Relais   K1_Ein   = { 1, 0, 0 };
9
struct Relais   K1_Aus   = { 0, 1, 1 };
10

11
struct Relais   K2_Ein   = { 3, 2, 2 };
12
struct Relais   K2_Aus   = { 2, 3, 3 };
13

14
struct Relais   K3_Ein   = { 5, 4, 4 };
15
struct Relais   K3_Aus   = { 4, 5, 5 };
16

17
struct Relais   K4_Ein   = { 7, 6, 6 };
18
struct Relais   K4_Aus   = { 6, 7, 7 };
19

20
struct Relais   K5_Ein   = { 9, 8, 8 };
21
struct Relais   K5_Aus   = { 8, 9, 9 };
22

23
struct Relais   K6_Ein   = { 11, 10, 10 };
24
struct Relais   K6_Aus   = { 10, 11, 11 };
25

26
struct Relais   K7_Ein   = { 13, 12, 12 };  
27
struct Relais   K7_Aus   = { 12, 13, 13 };
28

29
struct Relais   K8_Ein   = { 15, 14, 14 };
30
struct Relais   K8_Aus   = { 14, 15, 15 };
31

32
//Prototyp
33

34
uint16_t RelaisSchalten( struct Relais* theRelais)  ;
Gast #2872427
Lesenswert?

Man macht in einer H-Datei keine Variablendeklarationen.
Oder allenfalls (da gibt es aber Meinungsverschiedenheiten) mittels 
einem Conditional define für "extern".

Da Du die H-Datei in main.c und httpd.c einfügst werden die Variablen 
natürlich doppelt deklariert.
Ändere das und alles wird gut.
Gast #2872428
Lesenswert?

Also das ist im relais.c - file:
1
uint16_t RelaisSchalten( struct Relais* theRelais)  
2
{
3

4
  AusgangSetBit( theRelais->bitToSet );
5
  AusgangUnsetBit( theRelais->bitToClear ); 
6
  AusgangOut();
7

8
  theRelais->setCycles++;
9

10
 
11
  if (theRelais->setCycles >= 200)
12
    {
13
    AusgangUnsetBit( theRelais->bitToSet ); 
14
    AusgangUnsetBit( theRelais->bitToClear ); 
15
    AusgangOut();
16

17
    theRelais->setCycles = 0;
18
    return true;
19
    }  
20

21
  return false;
22
}

Und das im relais.h file :

struct Relais {
   uint16_t   bitToSet;
   uint16_t   bitToClear;
   uint16_t   setCycles;     // Zaehlt die 0-Durchgänge bis zum 
Abschalten
};


struct Relais   K1_Ein   = { 1, 0, 0 };
struct Relais   K1_Aus   = { 0, 1, 1 };

struct Relais   K2_Ein   = { 3, 2, 2 };
struct Relais   K2_Aus   = { 2, 3, 3 };

struct Relais   K3_Ein   = { 5, 4, 4 };
struct Relais   K3_Aus   = { 4, 5, 5 };

struct Relais   K4_Ein   = { 7, 6, 6 };
struct Relais   K4_Aus   = { 6, 7, 7 };

struct Relais   K5_Ein   = { 9, 8, 8 };
struct Relais   K5_Aus   = { 8, 9, 9 };

struct Relais   K6_Ein   = { 11, 10, 10 };
struct Relais   K6_Aus   = { 10, 11, 11 };

struct Relais   K7_Ein   = { 13, 12, 12 };
struct Relais   K7_Aus   = { 12, 13, 13 };

struct Relais   K8_Ein   = { 15, 14, 14 };
struct Relais   K8_Aus   = { 14, 15, 15 };

//Prototyp

uint16_t RelaisSchalten( struct Relais* theRelais)  ;
[/c]
Gast #2872445
Lesenswert?

Stefan Ernst schrieb:
> Hmm schrieb:
>> Man macht in einer H-Datei keine Variablendeklarationen.
>
> Doch, genau da gehören sie hin. Aber eben keine Definitionen, wie die
> oben.

Definition heisst:
Dem Compiler sagen, dass er dieses etwas anlegen soll. So stehts im 
Buch. Das dient dann doch als "Prototyp". Ich bin zu blöd dafür, btte 
klär mich noch nen bischen mehr auf...
Gast #2872453
Lesenswert?

>Definition heisst:
>Dem Compiler sagen, dass er dieses etwas anlegen soll. So stehts im
Buch.
Ja. Richtig. In Bezug auf Variablen und Funktionen.

>Das dient dann doch als "Prototyp".

Definitionen "können" Deklarationen sozusagen "ersetzen", wenn sie vor 
der ersten Verwendung stehen.

Aber unter einem "Prototyp" versteht man eine Deklaration. Insofern ist 
ein Prototyp, also eine Deklaration nicht identisch mit einer 
Definition.
Gast #2872464
Lesenswert?

Puhh...ich kriege es nicht hin.

Ich habe z.B. eine einfache Funktion im .c file:
1
//Min Max begrenzen
2
uint16_t MinMax (uint16_t Input, uint16_t Min , uint16_t Max)
3
{
4
            if (Input <= Min)
5
                Input = Min;  
6

7
            if (Input >= Max)
8
                Input = Max;
9
            
10
      return Input;
11

12
}

In der .h
[c
uint16_t MinMax (uint16_t Input, uint16_t Min , uint16_t Max);
[/c]

und alles läuft. Warum nicht das mit der Struktur als Übergabewert?

Wie muss ich's denn machen?
Gast #2872474
Lesenswert?

Das ist doch genau das, was die Fehlermeldungen sagen:

httpd.o:(.data.K1_Aus+0x0): multiple definition of `K1_Aus'
main.o:(.data.K1_Aus+0x0): first defined here


"multiple definition" heisst: "mehrfache Definition".
#2872477
Lesenswert?

<8 schrieb:
> Definition heisst:
> Dem Compiler sagen, dass er dieses etwas anlegen soll. So stehts im
> Buch. Das dient dann doch als "Prototyp". Ich bin zu blöd dafür, btte
> klär mich noch nen bischen mehr auf...

Deklaration bedeutet:
Es gibt da irgendwo etwas, was nach außen so aussieht.

Definition bedeutet:
Lege etwas an.

Deklaration (Variable und Funktion):
1
extern int var;
2

3
void func (void);

Definition (Variable und Funktion):
1
int var;
2

3
void func (void) {
4
}
Gast #2872479
Lesenswert?

Hmm schrieb:
> Das ist doch genau das, was die Fehlermeldungen sagen:
>
> httpd.o:(.data.K1_Aus+0x0): multiple definition of `K1_Aus'
> main.o:(.data.K1_Aus+0x0): first defined here
>
>
> "multiple definition" heisst: "mehrfache Definition".

Wo soll ich dann das hin packen?
1
struct Relais {
2
   uint16_t   bitToSet; 
3
   uint16_t   bitToClear;
4
   uint16_t   setCycles;     // Zaehlt die 0-Durchgänge bis zum Abschalten
5
};
6

7
struct Relais   K1_Ein   = { 1, 0, 0 };
8
struct Relais   K1_Aus   = { 0, 1, 1 };
9

10
struct Relais   K2_Ein   = { 3, 2, 2 };
11
struct Relais   K2_Aus   = { 2, 3, 3 };
12

13
....
Gast #2872492
Lesenswert?

>> "multiple definition" heisst: "mehrfache Definition".
>
> Wo soll ich dann das hin packen?
>


Das musst doch in die H-Datei. Ok, dadurch dsas die H datei woanders 
auch noch eingebunden war gab es multiple definitions. Aber wie muss ich 
es denn machen?
Gast #2872493
Lesenswert?

Die einfachste Anfängermöglichkeit ist folgende:

1. Du kopierst die Variablendefinitionen aus der H-Datei in main.c Damit 
werden eben dort die Definitionen gemacht.

2. Du setzt das Wort "extern" vor die Variablendefinitionen in der 
h-Datei. Damit werden das Deklarationen. Sie werden also beim include in 
main.c und httpd.c nicht mehr doppelt definiert.
#2872511
Lesenswert?

Das folgende Beispiel compiliert ohne Fehler. Du darfst selbst suchen, 
was du falsch gemacht hast (einfach nur jeden Leerraum, jedes Zeichen 
ansehen)

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>

struct Relais {
   uint16_t   bitToSet;
   uint16_t   bitToClear;
   uint16_t   setCycles;     // Zaehlt die 0-Durchgänge bis zum 
Abschalten
};

struct Relais   K1_Ein   = { 1, 0, 0 };
struct Relais   K1_Aus   = { 0, 1, 1 };

struct Relais   K2_Ein   = { 3, 2, 2 };
struct Relais   K2_Aus   = { 2, 3, 3 };

uint16_t RelaisSchalten( struct Relais *theRelais)
{

//  AusgangSetBit( theRelais->bitToSet );
//  AusgangUnsetBit( theRelais->bitToClear );
//  AusgangOut();

  theRelais->setCycles++;


  if (theRelais->setCycles >= 200)
    {
//    AusgangUnsetBit( theRelais->bitToSet );
//    AusgangUnsetBit( theRelais->bitToClear );
//    AusgangOut();

    theRelais->setCycles = 0;
    return true;
    }

  return false;
}int main(void) {

  uint16_t temp;

  temp = RelaisSchalten(&K1_Ein);

  return(0);
  }
Gast #2872513
Lesenswert?

In main.c siehts so aus:
1
extern struct Relais   K1_Ein   = { 1, 0, 0 };
2
extern struct Relais   K1_Aus   = { 0, 1, 1 };
3

4
extern struct Relais   K2_Ein   = { 3, 2, 2 };
5
extern struct Relais   K2_Aus   = { 2, 3, 3 };
6

7
.....

in der anderen .h steht das noch:
1
struct Relais {
2
   uint16_t   bitToSet; 
3
   uint16_t   bitToClear;
4
   uint16_t   setCycles;     // Zaehlt die 0-Durchgänge bis zum Abschalten
5
};

in dem anderen .c file steht das:
1
uint16_t RelaisSchalten( struct Relais* theRelais)  
2
{
3

4
  AusgangSetBit( theRelais->bitToSet );
5
  AusgangUnsetBit( theRelais->bitToClear ); 
6
  AusgangOut();
7

8
  theRelais->setCycles++;
9

10
 
11
  if (theRelais->setCycles >= 200)
12
    {
13
    AusgangUnsetBit( theRelais->bitToSet ); 
14
    AusgangUnsetBit( theRelais->bitToClear ); 
15
    AusgangOut();
16

17
    theRelais->setCycles = 0;
18
    return true;
19
    }  
20

21
  return false;
22
}

dan kommt diese Meldung:
Compiling: main.c
avr-gcc -c -mmcu=atmega1284p -I. -Os -funsigned-char 
-funsigned-bitfields -fpack-struct -fshort-enums -Wall 
-Wstrict-prototypes -Wa,-adhlns=main.lst  -fno-inline-small-functions 
-fno-split-wide-types -fno-move-loop-invariants -mcall-prologues 
-ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax 
-std=gnu99 main.c -o main.o
main.c:89: warning: 'K1_Ein' initialized and declared 'extern'
main.c:90: warning: 'K1_Aus' initialized and declared 'extern'
main.c:92: warning: 'K2_Ein' initialized and declared 'extern'
main.c:93: warning: 'K2_Aus' initialized and declared 'extern'
Gast #2872549
Lesenswert?

>>Hmm schrieb:
>> Man macht in einer H-Datei keine Variablendeklarationen.
>Dafür sind Header doch da?
>Du meinst Variablendefinitonen?

@ Johann L.
Ich würde sogar sagen es handelt sich um Variablendefinitionen. Dieser 
Hmm ist ein absoluter Idiot.
#2872565
Lesenswert?

Hmm schrieb:
> Der macht hier nur den Troll. Einfach ignorieren.
> Da fehlen keine Leerzeichen.

Du weißt schon, wie Pointer definiert werden?

uint16_t RelaisSchalten( struct Relais* theRelais);
-> der Name der Struktur ist Relais*, definiert wurde aber eine Struktur 
namens Relais.

uint16_t RelaisSchalten( struct Relais * theRelais);
Die Funktion hat als Argument einen Pointer auf die Struktur.

Lies mal wieder etwas, Grundlagen in C sind hilfreich.
#2872582
Lesenswert?

Georg G. schrieb:
> Du weißt schon, wie Pointer definiert werden?
>
> uint16_t RelaisSchalten( struct Relais* theRelais);
> -> der Name der Struktur ist Relais*, definiert wurde aber eine Struktur
> namens Relais.

Sorry, aber das ist kompletter Unsinn.
Alle folgenden Varianten sind in ihrer Bedeutung absolut identisch:
1
struct Relais * theRelais;
2
struct Relais* theRelais;
3
struct Relais *theRelais;
4
struct Relais*theRelais;
5
struct
6
Relais
7
*
8
theRelais
9
;
Gast #2872611
Lesenswert?

Klaus Wachtler schrieb:

>nicht ganz - nur die erste geht durch den Compiler, der Rest nicht, weil
>mehrfach definiert

Ach Mensch! Das sagst Du jetzt? Was mache ich jetzt mit der Tüte 
Leerzeichen?
Au fein, ich weiss. Zusammen mit Zucker und Himbeeren in den Quark 
rühren.

<8 ??? Wie stehts denn bei Dir. Schon was geändert? Oder beim 
Abendessen?
Persönliche Seite #2872638
Lesenswert?

<8 schrieb:
> In main.c siehts so aus:
1
 
2
extern struct Relais   K1_Ein   = { 1, 0, 0 };
3
extern struct Relais   K1_Aus   = { 0, 1, 1 };
4

5
extern struct Relais   K2_Ein   = { 3, 2, 2 };
6
extern struct Relais   K2_Aus   = { 2, 3, 3 };

Das ist Unsinn.
Lass das extern weg.

Und binde davor die Headerdatei ein, in der die Struktur deklariert 
wird.

> in der anderen .h steht das noch:
1
struct Relais {
2
   uint16_t   bitToSet; 
3
   uint16_t   bitToClear;
4
   uint16_t   setCycles;     // Zaehlt die 0-Durchgänge bis zum Abschalten
5
};

Da fehlt noch was:
1
extern struct Relais   K1_Ein;
2
extern struct Relais   K1_Aus;
3

4
extern struct Relais   K2_Ein;
5
extern struct Relais   K2_Aus;

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren