mikrocontroller.net

Forum: Compiler & IDEs Problem mit globalen Array


Autor: Norbert S. (norton)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich möchte folgendes realisieren:
main.c

.
.
uint16_t spg_tabelle[ MAX_U_VAUES ][3]={
  {890, 277, 225},   // 12,00 V   01
  {868, 278, 231},   // 11,75 V   02
  {853, 279, 230},   // 11,50 V   03
  .
  .
  .
  {366, 276, 445},   // 05,00 V   29
};
.
.


funk.c

extern uint16_t _spg_tabelle[ MAX_U_VAUES ][3];
.
.

void set_adc_value(void)
{
   int8_t i = 0;  
      for (i=0; i < MAX_U_VAUES; i++)     // Spannungstabelle durchsuchen
      {
      if (__adc_interrupt_value >= _spg_tabelle[i][0])       // Passenden Wert aus der Tabelle heraussuchen
      {
         _pwm_wert = _spg_tabelle[i][_pwm_spalte];                 // Wert Übergeben (_pwm_spalte entspricht ein / aus Impuls)
         break;
      }
   }
}

ich bekomme folgende Fehlermeldung:
C:\..\default/../funk.c:129: undefined reference to `_spg_tabelle'

Meine Fragen:

Wie sieht der richtige Umgang mit einem globalen 2 Dimensionalen Array 
aus?
Gibt es eine bessere Möglichkeit eine Kreuztabelle zu erstellen (kann je 
Projekt verschieden lang sein), vielleicht als Konstanten oder Defines?

Danke Norton

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht solltest du mal deine Affinität zu führenden Unterstrichen
überprüfen...  In erster Näherung sind Namen mit führenden Unter-
strichen für dich als Benutzer tabu -- sie sind für Compiler und
Bibliothek vorbehalten.  (In zweiter Näherung gibt es Ausnahmen von
dieser Regel, aber die sind weniger wichtig.)

Kommt hinzu, dass du dir offenbar nicht mal merken kannst, ob du
nun vor deinen Namen einen Unterstrich davor setzt oder nicht,
und dass du es dadurch mal so, mal so geschrieben hast.  Kein
Wunder also, dass der Linker das nicht zusammen popeln kann.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>In erster Näherung sind Namen mit führenden Unter-
>strichen für dich als Benutzer tabu -- sie sind für Compiler und
>Bibliothek vorbehalten.

Inwieweit?

Ich dachte bisher immer, dass doppelte Unterstriche für lib-interne 
Variablen verwendet werden.

Ich verwende einfache Unterstriche (zB _u8TempFor) immer als Synonym für 
lokale Variablen.

Autor: nixversteh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>       if (__adc_interrupt_value >= _spg_tabelle[i][0]) ...
             ^^
             !!
wird dort auch munter mißbraucht. Allerdings interessiert mich dazu auch 
Jörg's (allzeit kompetente) Erklärung der Sachlage. Weil, so richtig 
wissen tue ich es auch nicht.

Autor: Norbert S. (norton)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch wrote:
> Vielleicht solltest du mal deine Affinität zu führenden Unterstrichen
> überprüfen...  In erster Näherung sind Namen mit führenden Unter-
> strichen für dich als Benutzer tabu -- sie sind für Compiler und
> Bibliothek vorbehalten.  (In zweiter Näherung gibt es Ausnahmen von
> dieser Regel, aber die sind weniger wichtig.)

Das wußte ich leider nicht das die für mich tabu sind. Habe mir vor 
langer Zeit und anderer Programmiersprache angewöhnt globale Variablen 
mit "__" und lokale mit "_" zu markieren. Muss ich mir halt etwas neues 
einfallen lassen.

> Kommt hinzu, dass du dir offenbar nicht mal merken kannst, ob du
> nun vor deinen Namen einen Unterstrich davor setzt oder nicht,
> und dass du es dadurch mal so, mal so geschrieben hast.  Kein
> Wunder also, dass der Linker das nicht zusammen popeln kann.

Das mit der Namensinkonsistenz ist mir anscheinend beim zusammenkopieren 
passiert.
Ich habe die Namen jetzt im Code alle ohne unterstriche und durchgängig 
gemacht und bekomme trotzdem folgende Fehler:

C:\Daten\Projekte\S8\CPrg\S8Dusche\default/../lib_mv_schalten.c:123: 
undefined reference to `spg_tabelle'
C:\Daten\Projekte\S8\CPrg\S8Dusche\default/../lib_mv_schalten.c:123: 
undefined reference to `spg_tabelle'
C:\Daten\Projekte\S8\CPrg\S8Dusche\default/../lib_mv_schalten.c:129: 
undefined reference to `spg_tabelle'
C:\Daten\Projekte\S8\CPrg\S8Dusche\default/../lib_mv_schalten.c:129: 
undefined reference to `spg_tabelle'
C:\Daten\Projekte\S8\CPrg\S8Dusche\default/../lib_mv_schalten.c:129: 
undefined reference to `spg_tabelle'
lib_mv_schalten.o:C:\Daten\Projekte\S8\CPrg\S8Dusche\default/../lib_mv_s 
chalten.c:129:  more undefined references to `spg_tabelle' follow

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du im Modul lib_mv_schalten.c auch das extern spg_tabelle geändert?
                                                   ^
MW

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Norbert S. wrote:

> Das mit der Namensinkonsistenz ist mir anscheinend beim zusammenkopieren
> passiert.
> Ich habe die Namen jetzt im Code alle ohne unterstriche und durchgängig
> gemacht und bekomme trotzdem folgende Fehler:

Dann wäre noch deine Linker-Kommandozeile interessant.  Offenbar
versuchst du, nur main.o zu linken nicht aber funk.o (oder
genau andersrum? dein copy&paste verursacht mehr Unklarheiten
als es beseitigt).

Die tatsächlichen Regeln, welche Bezeichner mit Unterstrichen wo
zugelassen sind, sind leider etwas komplizierter.  Die entsprechenden
Bezeichner sind gemäß Standard "für die Implementierung reserviert",
das heißt, sie dürfen von Compiler uns Systembibliothek (das ist in
erster Linie die Bibliothek, die benötigt wird, um den C-Sprachstandard
zu erfüllen) für ihre eigenen Zwecke benutzt werden.  Wenn -- wie
bei AVR-GCC und avr-libc -- diese beiden Komponenten der Sprach-
implementierung nicht aus einer Hand kommen, dann müssen diese beiden
sich intern absprechen, wer welche Bezeichner für welche Zwecke
benutzt.  Für GCC-globale Dinge gibt in diesem Falle GCC einfach vor,
was er benutzt (das ist aber relativ wenig, da gehören so Dinge wie
_GNUC_ dazu), für die AVR-spezifischen Teile des Compiler arbeiten
die zuständigen GCC-Entwickler wiederum eng mit den avr-libc-
Entwicklern zusammen bzw. (Anatolij Sokolov) sogar in Personalunion.

Inwieweit man weitere allgemeine Bibliotheken (also beispielsweise
X11 unter Unix, diverse Grafikbibliotheken, allgemeine Kompressions-
algorithmen wie zlib, etc. pp.) auch als "zur Implementierung
gehörig" rechnen kann, sodass diese eigene Teilnamensräume aus dem
Unterstrich-Bereich für sich beanspruchen können, sei jetzt mal
dahin gestellt.  Im strengen Sinne des Standards dürfen sie nicht,
andererseits haben sie praktisch dasselbe Problem wie die C-Bibliothek
(Vermeidung von Namenskollision mit dem Anwenderprogramm).  Jedoch
für reine Bibliotheken auf der Applikationsseite, die von der gleichen
Gruppe von Entwicklern gepflegt werden wie die endgültige Applikation,
trifft dieser Status (Bestandteil der "Implementierung" zu sein)
nun wirklich nicht mehr zu.

Hier nun nochmal eine Kurzfassung der Regeln:

Bezeichner, die mit zwei Unterstrichen beginnen, sind immer für
die Implementierung reserviert, egal in welchem Kontext sie
auftauchen.  Teilweise kann die Implementierung natürlich diese
Namen dokumentieren.  So kann man sich auf _GNUC_ verlassen beim
GCC, und man kann mit _asm_ arbeiten, um unabhängig von der
-std= Option den Inline-Assembler zu benutzen.  Die avr-libc
dokumentiert __STDIO_FDEVOPEN_COMPAT_12, mit der man die stdio-
Funktionen rückwärtskompatibel zur Version 1.2.x benutzen kann,
usw. usf.

Gleiches trifft zu auf Namen, die mit einem Unterstrich, gefolgt
von einem Großbuchstaben beginnen.

Namen, die auf Ebene einer Quelldatei mit einem Unterstrich beginnen,
sind ebenfalls reserviert.  Das betrifft alle Namen von Variablen,
Datentypen einschließlich struct/union/enum und Makros (#define).

Das lässt Namen übrig, die mit einem Unterstrich beginnen, gefolgt
von einem Kleinbuchstaben für die folgende Verwendung:

. lokale Variablen in Funktionen
. struct/union/enum-Bezeichnungen in C (nicht in C++, da sie dort
  zugleich einen Typnamen bilden) sowie deren Elemente

Autor: Norbert S. (norton)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Dann wäre noch deine Linker-Kommandozeile interessant.  Offenbar
> versuchst du, nur main.o zu linken nicht aber funk.o (oder
> genau andersrum? dein copy&paste verursacht mehr Unklarheiten
> als es beseitigt).

Das wäre die Ausgabe die ich bekomme:
(mein main.c ist das "__S8Dusche.c" file und das funk.c ist das 
"lib_mv_schalten.c" file)

Bitte weitere Kommentare zu den Unterstrichen nur wenn sie relevant 
sind.

Code ist sonst wie im Beispiel oben mit gleichen namen und ohne 
Unterstriche.

Build started 2.9.2008 at 10:07:12
avr-gcc.exe 
-I"C:\Daten\Projekte\S8\CPrg\S8Dusche\..\..\..\AVR-C-Compiler\Programme\ 
_LIB"  -I"C:\Daten\Projekte\S8\CPrg\S8Dusche\."  -mmcu=atmega1281 -Wall 
-gdwarf-2 -std=gnu99 
-DF_CPU=4000000
UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums 
-MD -MP -MT __S8Dusche.o -MF dep/__S8Dusche.o.d  -c  ../__S8Dusche.c

../__S8Dusche.c: In function 'main':
../__S8Dusche.c:32: warning: unused variable 'spg_tabelle'
avr-gcc.exe -mmcu=atmega1281 -Wl,-Map=S8Dusche.map __S8Dusche.o 
lib_Print_S8-6-12.o lib_allgemein.o lib_dip_switch.o lib_adc_messung.o 
lib_ir_impuls.o lib_wertetabelle.o lib_spi_messung.o lib_mv_schalten.o 
lib_ventilator.o lib_uart.o lib_platinen_test.o li
b_fade.o     -o S8Dusche.elf

lib_mv_schalten.o: In function `set_adc_value':
C:\Daten\Projekte\S8\CPrg\S8Dusche\default/../lib_mv_schalten.c:124: 
undefined reference to `spg_tabelle'
C:\Daten\Projekte\S8\CPrg\S8Dusche\default/../lib_mv_schalten.c:124: 
undefined reference to `spg_tabelle'
C:\Daten\Projekte\S8\CPrg\S8Dusche\default/../lib_mv_schalten.c:130: 
undefined reference to `spg_tabelle'
C:\Daten\Projekte\S8\CPrg\S8Dusche\default/../lib_mv_schalten.c:130: 
undefined reference to `spg_tabelle'
C:\Daten\Projekte\S8\CPrg\S8Dusche\default/../lib_mv_schalten.c:130: 
undefined reference to `spg_tabelle'
lib_mv_schalten.o:C:\Daten\Projekte\S8\CPrg\S8Dusche\default/../lib_mv_s 
chalten.c:130:  more undefined references to `spg_tabelle' follow
make: *** [S8Dusche.elf] Error 1
Build failed with 6 errors and 1 warnings...

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ../__S8Dusche.c: In function 'main':
> ../__S8Dusche.c:32: warning: unused variable 'spg_tabelle'

Du hast spg_tabelle versehentlich als lokale Variable von main 
definiert, statt als globale Variable.
Wieder mal ein gutes Beispiel dafür, dass nicht nur die Fehlermeldungen 
interessant sind, sondern auch die Warnungen.

Autor: Norbert S. (norton)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst wrote:
>> ../__S8Dusche.c: In function 'main':
>> ../__S8Dusche.c:32: warning: unused variable 'spg_tabelle'
>
> Du hast spg_tabelle versehentlich als lokale Variable von main
> definiert, statt als globale Variable.
> Wieder mal ein gutes Beispiel dafür, dass nicht nur die Fehlermeldungen
> interessant sind, sondern auch die Warnungen.

Das wars! Jetzt funktionierts.
So ein blöder Fehler, aber ich habe ja immerhin viele andere Sachen 
dabei gelernt.

Danke auch allen.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Gängig" ist zum  Beispiel die Prefixe
g_ für globale Variablen und
m_ für member-Variablen (C++)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.