Forum: PC-Programmierung C: const array in header, warum wird linker probleme machen?


von dotm (Gast)


Lesenswert?

Hallo!

Das ist ein wahrscheinlich einfaches Thema aber das ganze ist so 
unübersichtlich dass ich dennoch nachfragen muss.
Der Ursprung meines Problemes ist der, dass ich meinen 
Mikrocontrollercode auf ein eventuelles Pinswapping vorbereiten wollte.
In den Beispielen von STM wird das eigentlich ganz elegant erledigt. 
Aufgrunddessen hab ich jetzt beispielsweise sowas konstruiert:

config.h wäre dann die datei wo ich meine pins und ports eintrage:
1
#define DIGITAL_OUTn    7
2
3
typedef enum
4
{
5
EN_FILTER = 0,
6
EN_MODEM = 1,
7
EN_SENSOR = 2,
8
} DIGITAL_OUT_TypeDef;
9
10
#define EN_FILTER_PIN          GPIO_Pin_1
11
#define EN_FILTER_GPIO_PORT    GPIOA
12
#define EN_FILTER_GPIO_CLK     RCC_AHBPeriph_GPIOA
13
#define EN_FILTER_GPIO_SPEED   GPIO_Speed_2MHz
14
15
#define EN_MODEM_PIN           GPIO_Pin_9
16
#define EN_MODEM_GPIO_PORT     GPIOB
17
#define EN_MODEM_GPIO_CLK      RCC_AHBPeriph_GPIOB
18
#define EN_MODEM_GPIO_SPEED    GPIO_Speed_2MHz
19
 
20
#define EN_SENSOR_PIN          GPIO_Pin_8
21
#define EN_SENSOR_GPIO_PORT    GPIOB
22
#define EN_SENSOR_GPIO_CLK     RCC_AHBPeriph_GPIOB
23
#define EN_SENSOR_GPIO_SPEED   GPIO_Speed_2MHz

config.c beinhaltet jetzt noch das:
1
#include "config.h"
2
3
const uint16_t DIGITAL_OUT_PIN[DIGITAL_OUTn] =
4
  {
5
EN_FILTER_PIN, EN_MODEM_PIN, EN_SENSOR_PIN
6
  };
7
8
GPIO_TypeDef* DIGITAL_OUT_PORT[DIGITAL_OUTn] =
9
  {
10
EN_FILTER_GPIO_PORT, EN_MODEM_GPIO_PORT, EN_SENSOR_GPIO_PORT
11
  };
12
13
const uint32_t DIGITAL_OUT_CLK[DIGITAL_OUTn] =
14
  {
15
EN_FILTER_GPIO_CLK, EN_MODEM_GPIO_CLK, EN_SENSOR_GPIO_CLK, 
16
  };
17
18
const uint8_t DIGITAL_OUT_SPEED[DIGITAL_OUTn] =
19
  {
20
EN_FILTER_GPIO_SPEED, EN_MODEM_GPIO_SPEED, EN_SENSOR_GPIO_SPEED,
21
  };

jetzt kann ich innert config.c noch solche schönen funktionen schreiben:
1
void DigitalOutInit(DIGITAL_OUT_TypeDef DIGITAL_OUT)
2
  {
3
  GPIO_InitTypeDef GPIO_InitStructure;
4
5
  /* Enable the GPIO Clock */
6
  RCC_AHBPeriphClockCmd(DIGITAL_OUT_CLK[DIGITAL_OUT], ENABLE);
7
8
  /* Configure the GPIO pin */
9
  GPIO_InitStructure.GPIO_Pin = DIGITAL_OUT_PIN[DIGITAL_OUT];
10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
11
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
12
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
13
  GPIO_InitStructure.GPIO_Speed = DIGITAL_OUT_SPEED[DIGITAL_OUT];
14
  GPIO_Init(DIGITAL_OUT_PORT[DIGITAL_OUT], &GPIO_InitStructure);
15
  }

Aufgerufen wird das also dann mit:
1
DigitalOutInit(EN_FILTER);

so weit so wunderbar.
Jetzt dachte ich mir wär doch schön wenn ich in einem anderm Modul zb 
GPIO.c auch noch solche Funktionen verwenden könnte
1
// folgende Zeile geht noch:
2
void SetPin(DIGITAL_OUT_TypeDef DIGITAL_OUT)
3
{
4
// folgende Zeile geht nicht, wenn ich nur #include "config.h" mache,
5
// weil die const arrays aus config.c unbekannt sind.
6
GPIO_SetBits(DIGITAL_OUT_PORT[DIGITAL_OUT],DIGITAL_OUT_PIN[DIGITAL_OUT]);
7
}

mein erster Gedanke war also den Inhalt von config.c einfach in config.h 
reinzumachen weil ich sowieso so ein Konstrukt habe:
1
#ifndef INIT_CONFIG_H_
2
#define INIT_CONFIG_H_
3
4
// hier der headercode
5
6
#endif

offensichtlich nicht, weil laut folgendem Beitrag:
Beitrag "Re: const array in header auslagern"
der Linker sich dennoch beschweren wird.

das muss also z.B. via
1
extern uint16_t DIGITAL_OUT_PIN;
in der config.h gelöst werden. (ja? nein?)

Kann mir jemand erklären wieso der linker trotz #ifndef muckt?
Gibt es eine Möglichkeit dass ich das nur mit einer headerfile machen 
kann?
Ich würde mir echt gerne die config.c (und auch das notwendige 
mitverlinken) und die doppelschreiberei ersparen...

von Verne (Gast)


Lesenswert?

Hier sind zwei Irrtümer maßgebend.
1. Der Linker "muckt" nicht, sondern reagiert sinnvoll auf dass, was Du 
in C geschrieben hast.
2. Der Linker hat mit #ifdef uws. nichts zu tun. Das ist Sache des 
Präprozessors.

Das #ifndef verhindert/befördert ja nur ob das config.h included wird 
oder nicht. Der Hauptzweck dieses Konstrukts, ist es zu verhindern, das 
include files mehrfach included werden.
Mit der Deklaration/Definition Deiner Variablen aber hat das nichts zu 
tun. Da musst Du in der Tat eine Methode finden, wie Du zwischen

extern uint16_t DIGITAL_OUT_PIN;

und

const uint16_t DIGITAL_OUT_PIN[...

auswählst.

Das ist garnicht so schwer und benutzt im Grunde den selben Gedankengang 
wie das obige #ifdef. Überleg mal selbst.

von dotm (Gast)


Lesenswert?

also, was ist eigentlich das Problem wenn ich das Array direkt in die 
headerfile schreibe.
Der Compiler wird die header einmal aufrufen und danach ist das Array 
global (oder eben nicht?) deklariert.
Ich denke was du mir sagen willst ist, dass das Array dann NUR für die 
aufrufende Funktion deklariert ist.. (?)
Könnte das eine Lösung sein?
config.h enthält also auch:
1
#ifndef INIT_CONFIG_H_
2
const uint16_t DIGITAL_OUT_PIN[DIGITAL_OUTn] =
3
  {
4
EN_FILTER_PIN, EN_MODEM_PIN, EN_SENSOR_PIN
5
  };
6
#endif
7
8
#ifdef INIT_CONFIG_H_
9
extern uint16_t DIGITAL_OUT_PIN;
10
#endif

Das würde heissen dass das Array zwar im ersten Durchlauf global 
deklariert wird aber immer noch mit jedem weiteren Modul (.c Datei) 
durch extern verbunden werden muss.

Das ist mir ein bisschen unklar. Wenn meine main.h die datei config.h 
inkludiert, dann müsste doch das array global ohne weiteres "extern" zur 
Verfügung stehen?
Wenn ich ein einzelnes Modul (z.B. GPIO.c) kompiliere dann ist 
INIT_CONFIG_H_ ja noch nicht definiert und das Modul sollte doch ohne 
Probleme kompilierbar sein.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Verne schrieb:
> 1. Der Linker "muckt" nicht, sondern reagiert sinnvoll auf dass, was Du
> in C geschrieben hast.

So kann man das natürlich auch "interpretieren".

Das Problem, das hier auftritt, ist, daß für jede Objektdatei, die mit 
eingebundener Headerdatei erzeugt wird, jeweils eine Kopie des 
const-Array angelegt wird. Wenn diese nicht als statisch definiert 
sind, d.h. nur innerhalb der Objektdatei sichbar, dann beschwert sich 
der Linker --zu Recht-- über mehrfach definierte Symbole.

Der gcc-Linker bietet die Möglichkeit, diese Definitionen zu überlagern 
und zu einem zusammenzufassen (so daß die Warnung nicht mehr auftritt), 
aber das kann auch Probleme erzeugen, wenn nämlich die Symbole 
eigentlich unterschiedlich sein sollten. Dann verdeckt diese Möglichkeit 
den Fehler, den man dann recht aufwendig suchen muss.

Daher sollte --meiner Ansicht nach-- auf diese Möglichkeit verzichtet 
werden, zumal das eine gcc-Spezialität ist, und andere C-Compiler bzw. 
deren Linker sowas nicht unterstützen.



In Headerdateien gehören nur Deklarationen, also Erklärungen, daß es 
irgendwo ein Objekt mit diesen und jenen Eigenschaften gibt, aber 
nicht die Definition des Objektes, die festlegt, daß es hier dieses 
Objekt gibt.
1
const uint16_t DIGITAL_OUT_PIN[DIGITAL_OUTn] =
2
  {
3
EN_FILTER_PIN, EN_MODEM_PIN, EN_SENSOR_PIN
4
  };

Das ist eine Definition.

Die korrespondierende Deklaration sieht so aus:
1
extern const uint16_t DIGITAL_OUT_PIN[DIGITAL_OUTn];


"Include-Guards", also das Verpacken in #ifdef & Co. helfen nur, wenn 
sie so genutzt werden, daß nur für eine C-Datei die Definition 
vorhanden ist.

Dann aber kann man es auch richtig machen und Definition und Deklaration 
trennen.


Nochwas: Variablennamen, wie Dein DIGITAL_OUT_PIN, gehören nicht in 
Großbuchstaben geschrieben. Das ist Macros, also mit #define definierten 
Dingen vorbehalten - und je nach Philosophie des Entwicklers einzelnen 
enum-Werten sowie typedefs.

----

Anmerkung:

In einem durch einen langen Arbeitstag vielleicht begründbaren Anfall 
geistiger Umnachtung habe ich, als ich das gestern schrieb, recht 
konsequent Definition und Deklaration durcheinandergebracht.
Das habe ich jetzt korrigiert -- mit Dank an den aufmerksamen Leser 
Stefan Ernst.

: Bearbeitet durch User
von Stefan E. (sternst)


Lesenswert?

Rufus Τ. Firefly schrieb:
> In Headerdateien gehören nur Definitionen, also Erklärungen, daß es
> irgendwo ein Objekt mit diesen und jenen Eigenschaften gibt, aber
> nicht die Deklaration des Objektes, die festlegt, daß es hier dieses
> Objekt gibt.

Bedeutung von "Definition" und "Deklaration" ist genau anders herum.

von Stefan E. (sternst)


Lesenswert?

@ dotm:

Ein #define wirkt sich nicht Modul übergreifend aus. Zweck der 
Include-Guards ist ausschließlich, das mögliche mehrfache Einbinden 
eines Headers in ein und das selbe Modul zu unterbinden.

von dotm (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> In Headerdateien gehören nur Definitionen, also Erklärungen, daß es
> irgendwo ein Objekt mit diesen und jenen Eigenschaften gibt, aber
> nicht die Deklaration des Objektes, die festlegt, daß es hier dieses
> Objekt gibt.

Das verstehe ich, in diesem Spezialfall jedoch wäre es einfacher, weil 
dann der Hardwaredesigner (also eh auch ich...) nur eine Datei und zwar 
config.h ändern muss.

Rufus Τ. Firefly schrieb:
> Nochwas: Variablennamen, wie Dein DIGITAL_OUT_PIN, gehören nicht in
> Großbuchstaben geschrieben. Das ist Macros, also mit #define definierten
> Dingen vorbehalten - und je nach Philosophie des Entwicklers einzelnen
> enum-Werten sowie typedefs.

jetzt hast du mich erwischt.

Rufus Τ. Firefly schrieb:
> Wenn diese nicht als statisch deklariert
> sind, d.h. nur innerhalb der Objektdatei sichbar, dann beschwert sich
> der Linker --zu Recht-- über mehrfach definierte Symbole.

Was, wenn ich die Deklarationen der const Arrays ausserhalb des 
Include-Guards in die header Datei schreibe, aber als static.
Dann müssten sie pro .o einmal zur Verfügung stehen. Wäre das eine 
Lösung?

Auch Interessant ist das Macro aus dem Beitrag:
Beitrag "Re: Globale Variablen, mehrere Dateien"
1
#ifndef EXTERN
2
#define EXTERN extern
3
#endif
4
5
EXTERN int GlobaleVar1;
6
EXTERN int GlobaleVar2;

Aber ich denke sowas geht nur wenn ich die Variable nicht initialisiere.
Oder frisst der Compiler sowas:
1
extern int meine_lieblingszahlen[2] =
2
{
3
666,1337
4
};

von dotm (Gast)


Lesenswert?

dotm schrieb:
> Was, wenn ich die Deklarationen der const Arrays ausserhalb des
> Include-Guards in die header Datei schreibe, aber als static.
> Dann müssten sie pro .o einmal zur Verfügung stehen. Wäre das eine
> Lösung?

AAAAHH!!!:

Stefan Ernst schrieb:
> Ein #define wirkt sich nicht Modul übergreifend aus. Zweck der
> Include-Guards ist ausschließlich, das mögliche mehrfache Einbinden
> eines Headers in ein und das selbe Modul zu unterbinden.

von Mark B. (markbrandis)


Lesenswert?

Stefan Ernst schrieb:
> Rufus Τ. Firefly schrieb:
>> In Headerdateien gehören nur Definitionen, also Erklärungen, daß es
>> irgendwo ein Objekt mit diesen und jenen Eigenschaften gibt, aber
>> nicht die Deklaration des Objektes, die festlegt, daß es hier dieses
>> Objekt gibt.
>
> Bedeutung von "Definition" und "Deklaration" ist genau anders herum.

Richtig. Deklaration = ich erkläre dem Compiler, dass eine Variable oder 
Funktion mit diesem Namen und Typ irgendwo existiert.  Definition = 
Ausprogrammieren einer Funktion, bzw. Anlegen (und ggf. Initialisieren) 
einer Variablen im Speicher.

von Karl H. (kbuchegg)


Lesenswert?

dotm schrieb:

> Aber ich denke sowas geht nur wenn ich die Variable nicht initialisiere.
> Oder frisst der Compiler sowas:
>
>
1
> extern int meine_lieblingszahlen[2] =
2
> {
3
> 666,1337
4
> };
5
>

Um das noch zu beantworten:
Schreiben kannst du es. Aber das Problem an der Sache ist, dass eine 
Initialisierung aus einer Deklaration eine Definition macht. D.h. durch 
die Initialisierung fällt das 'extern' stillschweigend unter den Tisch.

von dotm (Gast)


Lesenswert?

Also:
Verne schreibt oben dass es möglich ist zwischen const und extern zu 
schalten.
Ich denke aber dass das nicht möglich ist. Wie soll denn der Compiler 
wissen dass schon ein Objekt mit dem array erstellt worden ist?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Stefan Ernst schrieb:
> Bedeutung von "Definition" und "Deklaration" ist genau anders herum.

Oh, Mist. Hast recht. War ein langer Tag gestern -- manchmal macht das 
Hirn schlapp.

Habe das in o.g. Geschreibsel von mir jetzt korrigiert, siehe auch die 
dortige Anmerkung.

: Bearbeitet durch User
von Stefan W. (dl6dx)


Lesenswert?

dotm schrieb:
> Gibt es eine Möglichkeit dass ich das nur mit einer headerfile machen
> kann?
> Ich würde mir echt gerne die config.c (und auch das notwendige
> mitverlinken) und die doppelschreiberei ersparen...

Ein möglicher Weg wäre, ein spezielles Präprozessorsymbol für die 
"Umschaltung" zwischen Deklaration und Definition zu verwenden. Eine 
einzelne Kombi-Deklaration/Definition sähe dann in etwa so aus:
1
#ifndef CREATEVAR
2
extern
3
#endif
4
const uint16_t DIGITAL_OUT_PIN[DIGITAL_OUTn]
5
#ifdef CREATEVAR
6
 =
7
  {
8
  EN_FILTER_PIN, EN_MODEM_PIN, EN_SENSOR_PIN
9
  }
10
#endif
11
;

Ist das Makro CREATEVAR definiert, wird die Variable definiert 
(erzeugt), andernfalls als extern deklariert (bekannt gemacht).

In der Moduldatei, in der die Definitionen erzeugt werden sollen, muss 
entsprechend vor dem Include ein #define CREATEVAR stehen.
1
#define CREATEVAR
2
#include "config.h"

In allen anderen Modulen darf es nicht definiert sein.

Grüße

Stefan

von dotm (Gast)


Lesenswert?

Hallo Stefan.
Danke, ich habe die Lösung sogar schon gelesen. Das Problem daran ist 
dass ich stets das ganze Projekt neu builden muss. Wenn ich nur ein 
Modul kompiliere, dann muss ich das wieder manuell setzen. Wie siehts 
denn mit den build variables aus (in Eclipse kann ich die ja in den 
Projekteinstellungen setzen). Kann ich die aus dem code heraus zur 
Compilerlaufzeit ändern?

von Stefan W. (dl6dx)


Lesenswert?

dotm schrieb:
> Das Problem daran ist
> dass ich stets das ganze Projekt neu builden muss.
> Wenn ich nur ein
> Modul kompiliere, dann muss ich das wieder manuell setzen.

Ich bin mir nicht sicher, ob da nicht noch ein Missverständnis vorliegt.

Das Makro CREATEVAR wird innerhalb der Headerdatei nicht definiert. Da 
wird nur auf eine vorhergehende Definition abgefragt. Um ein Modul, das 
den Header verwendet, neu zu übersetzen wird da also nichts geändert.

Die Definition von CREATEVARS erfolgt in genau einer C-Datei, nämlich 
der, in der die Deklaration der Variablen erfolgen soll (ich nenn sie 
jetzt mal "config.c") und zwar direkt vor der #include-Anweisung für 
config.h.

In allen anderen C-Dateien, die die Deklarationen ("extern ...") 
verwenden sollen, wird es nicht definiert. Da steht nur ein #include 
"config.h".

An der Build-Umgebung musst du für diese Technik gar nichts anpassen. Es 
reicht, wenn dort die normalen Quelltextabhängigkeiten bekannt sind.

Grüße

Stefan

: Bearbeitet durch User
von dotm (Gast)


Lesenswert?

@stefan
ok danke!
danke auch an alle andern hilfreichen poster!

von Josef D. (jogedua)


Lesenswert?

Stefan Wagner schrieb:
> Das Makro CREATEVAR wird innerhalb der Headerdatei nicht definiert. Da
> wird nur auf eine vorhergehende Definition abgefragt. Um ein Modul, das
> den Header verwendet, neu zu übersetzen wird da also nichts geändert.

Deshalb verwendet man besser in jeder Datei einen eindeutigen Namen, 
z.B. so:
1
// Test.c ----------------------------
2
#define SRC_Test_C_   // SRC + Dateiname
3
#include "Test.h"
4
// ...
5
 
6
// Test.h ----------------------------
7
#ifndef TEST_H_
8
#define TEST_H_
9
10
#ifdef SRC_Test_C_  
11
   #define SRC_Test_C_INIT
12
#else
13
   #define SRC_Test_C_ extern
14
#endif // SRC_Test_C_
15
16
// **** hier kommen die Deklarationen / Definitionen hin
17
18
#endif // TEST_H_

und an der Stelle **** z.B.
1
SRC_Test_C_  int var1;
2
3
SRC_Test_C_  int var2
4
#ifdef SRC_Test_C_INIT
5
  = 15
6
#endif
7
;

Dann kann man auch in der .h-Datei gleich erkennen, zu welchem Modul die 
Variablen gehören (falls das nicht auch schon aus dem Namen der 
Variablen ersichtlich ist).
Die entsprechenden Templates für die *.h und *.c Dateien lassen ich mir 
von der IDE (Eclipse) erzeugen.

von Stefan W. (dl6dx)


Lesenswert?

Josef D. schrieb:
> Deshalb verwendet man besser in jeder Datei einen eindeutigen Namen,

Aber ja. Volle Zustimmung!

Grüße

Stefan

von dotm (Gast)


Lesenswert?

Zum Teufel!!
Das ist doch abstrus! Erstmal ein Auszug aus dem Code:

config.c:
1
#define CREATEVAR
2
#include "PAC20_config.h"
3
4
USART_TypeDef* COM_USART[COMn] =
5
{
6
MODEM_PORT
7
};

config.h
1
#define COMn  1
2
3
typedef enum
4
  {
5
  MODEM = 0,
6
} COM_TypeDef;
7
8
#define MODEM_PORT                   USART1
9
  
10
#ifndef CREATEVAR
11
extern USART_TypeDef* COM_USART;
12
#endif

modem.c
1
#include "config.h"
2
3
void ModemInit(COM_TypeDef COM)
4
  {
5
  USART_Cmd(COM_USART[COM], ENABLE); //Fehler!
6
  }

So! der Compiler sagt aber bei ModemInit (die Zeile wo ich Fehler dazu 
geschrieben hab):

error:  #167: argument of type "USART_TypeDef" is incompatible with 
parameter of type "USART_TypeDef *"

Was zum Teufel ist da falsch?
Ich rufe ModemInit so auf:
ModemInit(MODEM);
die enum löst modemInit mit MODEM = 0 auf.
COM_USART ist ein Array aus Pointern und an Stelle Null steht MODEM_PORT 
also USART1
Wo denk ich da fehlerhaft? Ein virtuelles wiener Schnitzel für 
denjenigen der mir da weiterhelfen kann.

von Stefan E. (sternst)


Lesenswert?

dotm schrieb:
> Was zum Teufel ist da falsch?
1
extern USART_TypeDef* COM_USART;
->
1
extern USART_TypeDef* COM_USART[];


Das "CREATEVAR" ist hier nicht nur überflüssig, sondern sogar 
kontraproduktiv. Ohne dem hätte der Compiler dir beim Übersetzen von 
config.c gleich gesagt, dass da zwei COM_USART mit inkompatiblen Typen 
sind.

von dotm (Gast)


Lesenswert?

@stefan
für dich:
http://www.figlmueller.at/files/figlmueller/test/startbg.jpg


Klaro ein array ist ja ein pointer!

von dotm (Gast)


Lesenswert?

Ok! Wer möchte sich ein weiteres Schnitzel verdienen?
Das Rennt jetzt alles so wie es soll, einzig allein bei
1
GPIO_InitStructure.GPIO_Speed = DIGITAL_OUT_SPEED[DIGITAL_OUT];

bekomm ich die Warning:

 warning:  #188-D: enumerated type mixed with another type

Zuerst hatte ich:
1
uint8_t DIGITAL_OUT_SPEED[DIGITAL_OUTn] =
2
{
3
  EN_FILTER_GPIO_SPEED, EN_MODEM_GPIO_SPEED, EN_SENSOR_GPIO_SPEED, N_RELAIS_GPIO_SPEED, SW_RELAIS_ON_GPIO_SPEED, SW_RELAIS_OFF_GPIO_SPEED, LED_GPIO_SPEED
4
};

wobei jeder Eintrag aus sowas besteht:
1
#define SW_RELAIS_OFF_GPIO_SPEED  GPIO_Speed_2MHz

unit8_t weil das folgendermassen aufgelöst wird:
stmf37x_gpio.h:
1
#define GPIO_Speed_10MHz GPIO_Speed_Level_1   /*!< Fast Speed:10MHz   */
2
#define GPIO_Speed_2MHz  GPIO_Speed_Level_2   /*!< Medium Speed:2MHz  */
3
#define GPIO_Speed_50MHz GPIO_Speed_Level_3   /*!< High Speed:50MHz   */

und im Endeffekt auch stm32f37x_gpio.h:
1
typedef enum
2
{
3
  GPIO_Speed_Level_1  = 0x01, /*!< Medium Speed */
4
  GPIO_Speed_Level_2  = 0x02, /*!< Fast Speed   */
5
  GPIO_Speed_Level_3  = 0x03  /*!< High Speed   */
6
}GPIOSpeed_TypeDef;

mein Versuch das Ganze dann so umzuschreiben:
1
GPIOSpeed_TypeDef DIGITAL_OUT_SPEED[DIGITAL_OUTn] =
2
{
3
  EN_FILTER_GPIO_SPEED, EN_MODEM_GPIO_SPEED, EN_SENSOR_GPIO_SPEED, N_RELAIS_GPIO_SPEED, SW_RELAIS_ON_GPIO_SPEED, SW_RELAIS_OFF_GPIO_SPEED, LED_GPIO_SPEED
4
};

oder auch
1
GPIOSpeed_TypeDef* DIGITAL_OUT_SPEED[DIGITAL_OUTn] =
2
{
3
  EN_FILTER_GPIO_SPEED, EN_MODEM_GPIO_SPEED, EN_SENSOR_GPIO_SPEED, N_RELAIS_GPIO_SPEED, SW_RELAIS_ON_GPIO_SPEED, SW_RELAIS_OFF_GPIO_SPEED, LED_GPIO_SPEED
4
};

fruchtet nicht (gleiche Warning ! - ??). Was gehört denn da jetzt rein 
und was will mir denn die Warning sagen?

von dotm (Gast)


Lesenswert?

AHOI! hat sich erledigt (hatt vergessen das bei extern auch noch 
umzuschreiben). Schönen Abend!

von Mark B. (markbrandis)


Lesenswert?

DIGITAL_OUT_SPEED

Das ist von der Nomenklatur her eine Konstante, hier aber der Name eines 
Arrays. Funktioniert latürnich, ist aber nicht schön ;-)

Edit: Ach so, hat Rufus Τ. Firefly ja schon geschrieben.

: Bearbeitet durch User
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.