Visual Studio sieht mehr als ich?

Hallo,

bei meinen Versuchen mit VS komme ich nicht weiter, es sieht Fehler die es selbst nicht sieht und ich erst recht nicht.
Gestern hat es mir beim kompilieren mit diesem Code ständig erzählt kalenderdaten hätte multiple Definitionen.
Zum testen habe ich kalenderdaten auskommentiert und

zeit_30s=34567;

eingefügt.
Spuckt er auch als multiple Definition aus -> gelöscht, kalenderdaten einkommentiert -> VS neu gestartet:


Jetzt meckert er schon an was gar nicht da ist?

Was ist denn hier an der Verwendung von kalenderdaten oder
zeit_30 = 34557;
falsch?

Die Einträge in definitionen.h:

int zeit_30s = 30000;
int zeit_1m = 60000;

String kalenderdaten;

Es werden natürlich keine Fehler angezeigt, erst beim kompilieren haperts.

cu

Hat es ja auch - und zwar wird es an jeder Stelle, an der Du ein #include <definitionen.h> hinschreibst, neu definiert.

???
Steht in der daten_holen #include definitionen.h erkennt er es doppelt, steht es nicht drin kennt er es gar nicht und alles andere auch nicht.

Das angemeckerte zeit_30s ist nicht mal drin?

Stellt sich die Frage was ich hier falsch verstehe?

README aus include:

A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in src folder
by including it, with the C preprocessing directive `#include'.

cu

Ich weiß nicht, was du falsch verstehst.
Aber offensichtlich interessieren dich nicht die grundlegenden C++ Sprach und Compiler Zusammenhänge.
Das ist einerseits schade, weil du so auch unsere Antworten nicht verstehen wirst, und andererseits noch viel häufiger in solche Probleme stolpern willst.

Erster Tipp:
Denke in Übersetzungseinheiten.

Zweiter:
Unterscheide zwischen Deklaration und Definition.

Soweit ich mich erinnern kann, wurde dir schon mal ein C++ Buch empfohlen.
Hast du das auswendig gelernt?
Wenn nein, dann bitte machen.

Ganz sicher werde ich mit knapp 70 wegen eines Hobbys in den Wintermonaten nicht anfangen mich in etwas einzulernen das Jahre dauert und mit dem der Großteil der heutigen Jugend restlos überfordert sein dürfte.
Bei speziellen Sachen knie ich mich rein, aber das reicht mir. Meine Programme müssen nicht high-End-Ansprüchen genügen, sie sollen machen was ich will.

Wenn Du nicht helfen willst lass es und warte auf das Alter, vielleicht begreifst Du dann meinen Ansatz.

cu

Versuche es mal mit

#pragma once

int zeit_30s = 30000;
int zeit_1m = 60000;

String kalenderdaten;

int zeit_1m = 60000; wird auch in die Hose gehen. Musst Du „unsigned int“ draus machen. Bei Int ins bei 32767 Ende… danach wird es negativ.

Das hilft leider nicht, da der Guard in jeder einzelnen Übersetzungseinheit greift, aber nicht über alle Übersetzungseinheiten hinweg.

Wer liest, mag verstehen.
Wer Wissen ignoriert wird straucheln

Ich habe dir, auf den Punkt genaue, Stichworte/Tipps geliefert.
Natürlich darfst du das als "Nicht Hilfe" bezeichnen.

Ja stimmt.

#pragma once 

#include <Arduino.h>
constexpr unsigned int zeit_30s {30000};
constexpr unsigned int zeit_1m {60000};

extern String kalenderdaten;

sollte aber funktionieren.

Wäre eine gute Ergänzung zu deinen recht allgemein gehaltenen Tips gewesen, @combie.

Ist ein Scherz der nicht viel besser kommt als

"Hast du nicht zugehört, als ich dir das Buch vorgelesen habe?"

Weißt du noch, wo das Buch ist? Wenn nicht, google "C++ Variablen-Deklaration und -Definition". Das ist auch --oder speziell-- für uns Ü70 Pflicht, bevor wir uns hier über VisualStudio beschweren.

Um Größenordnungen besser!

Wobei mir da ein paar Sachen nicht gefallen, die auf anderer Ebene wohnen.
Quasi andere Themen betreffen.

Da stecken 2 Unsauberkeiten drin!

  1. unsigned int mag auf 32Bit Systemen funktionieren, auf AVR/8Bit eher nicht.
  2. Die 30 ist eine doppelte/redundante Information. Redundanzen sollte man vermeiden.

Vielleicht!
Vielleicht auch nicht.
Es gibt ja auch noch das genannte constexpr und das Päärchen static und inline.
Die alle drei oder vier(mit extern) das gleiche Problem lösen würden, mit etwas unterschiedlichen Seiteneffekten.

constexpr unterbindet den Fehler dadurch, dass gar kein adressierbares Speicheropjekt erzeugt wird.

static würde die Variable lokal zur Übersetzungseinheit definieren. Jede Übersetzungseinheit hätte dann eine Variable mit gleichem Namen.

inline definierte Variablen dürfen in mehreren Übersetzungseinheiten definiert sein, diese Definitionen müssen aber identisch sein, sonst UB(undefined Behavier)

extern ist nur deklarierend, die Definition muss woanders erfolgen.

Es ist also nicht ganz so leicht, zu entscheiden, was hier der richtige Weg ist.
Ich finde, er soll sein Buch lesen und verstehen. Das wird seine Handlungen leiten.

Dann kann ihm faktenbasierende Entscheidungen treffen.

Warum? Auch auf den 8 Bit Systemen ist „int“ ein Zwei-Byte Wert. Zumindest in der „Arduinotoolbox Welt“….

Sicher… um die Millisekunden zu speichern ist uint32_t vielleicht besser. Aber für eine 60.000 reichen zwei Byte.

Mit dem Namen stimme ich Dir zu. Den habe ich mir aber nicht ausgedacht. :wink:

Ich will auch was lernen, also ich verstehe das so das man zB. int zeitKurz = 3000; schreiben sollte?

Du musst kein komplettes C++ Buch auswendig lernen. Aber die Grundlagen musst Du kennen sonst wird auch das:

nicht funktionieren. Zu den Grundlagen gehört z.B. den Unterschied zwischen einer Deklaration und einer Definition zu kennen. Dann versteht man auch das:

D.h. in ein Header file gehören C-Deklarationen, aber keine C-Definitionen. Insofern ist eigentlich schon der Name 'definitionen.h' falsch.
Und das:

int zeit_30s = 30000;
int zeit_1m = 60000;

String kalenderdaten;

sind alles Definitionen. D.h. da wird Speicher im Ram für die Variable reserviert, und es wird diesem Speicherbereich ein Name zu geordnet. Und das darf es nur einmal geben, denn aus verständlichem Grund darf es keine 2 Variablen mit dem gleichen Namen geben. ( wir reden jetzt hier erstmal nur über globale Variable :wink: ).

Bei einer Deklaration informierst Du den Compiler nur darüber, dass es 'irgendwo' im Ram einen entsprechenden Speicherbereich für eine Variable mit diesem Namen gibt, die wird aber durch eine Deklaration nicht erneut eingerichtet. So entstehen dann auch keine doppelten gleichnamigen Variablen. Eine Deklaration ist dadurch gekennzeichent, dass man das Schlüsselwort 'extern' davor schreibt.

Natürlich muss die entsprechende Variable an EINER Stelle auch definiert werden, sonst ist sie ja gar nicht vorhanen, und der Linker meckert.

Gut ist auch, zu erkennen ob der Linker oder der Compiler meckert.

1 Like

Ja, es hilft immens bei der Fehlersuche wenn man das unterscheiden kann :smile: :smile:

Ich würde einfach
constexpr uint32_t halbeMinute {30000}; // Einheit ms
constexpr uint32_t minute {2*halbeMinute};
schreiben.

Kann man (fast) lesen wie einen normalen Satz. Und man weiß was gemeint ist.

Im Prinzip, ja!

Etwas aufgeblasen, unter Verwendung einer meiner Libs:

#include <Streaming.h> // die Lib findest du selber ;-)
Print &cout = Serial; // cout Emulation für "Arme"

#include <CombieTypeMangling.h> 
using namespace Combie::Millis;

constexpr Millis kurzeZeit {30_Sekunden};

void setup() 
{
  Serial.begin(9600);
  cout << F("Start: ") << F(__FILE__) << endl;
  cout << kurzeZeit << endl;
}

void loop() 
{

}

Danke !

Ein hohes Alter ist keine Ausrede, die hier akzeptiert wird. Vieleicht gefällt es Dir ja und Du steigst richtig in Arduino ein.

Grüße Uwe

Da muss man sich aber auch erst mal mit Operatoren für Literale beschäftigen, um diesen Ausdruck wirklich zu verstehen.