Forum: Mikrocontroller und Digitale Elektronik #define Variablen


von Sven (Gast)


Lesenswert?

Wenn ich Variablen so deklariere:
#define G 9.81
Was für einen Datentyp wird den da erzeugt? double, float,..?

von Helmut -. (dc3yc)


Lesenswert?

Sven,

so definierst du überhaupt keine Variable. Du sagst nur dem Precompiler, 
dass er überall, wo G steht, das durch 9.81 ersetzen soll.

Servus,
Helmut.

von Sven (Gast)


Lesenswert?

ja und wenn ich dann beispielweise eine operation ausführe:

10*G;

dann muss das doch irgeindein datentyp sein dass man damit rechnen kann?

von Detlev T. (detlevt)


Lesenswert?

Du hast den Hintergrund noch nicht verstanden. #define ist eine 
Anweisung für den Precompiler, das Programm VOR (Pre) dem Compiler. Das 
ist ein Programm, das einen Text (G) durch einen anderen (9.81) ersetzt. 
Der Compiler, nur der kennt Datentypen, bekommt das G nie zu sehen. In 
deinem Beispiel stünde da: 10*9.81 .

Wenn du Constanten mit Typ definieren willst, musst du das mit "const 
double g = 9.81;" machen. Das wird vom Compiler verarbeitet.

von Peter D. (peda)


Lesenswert?

Detlev T. wrote:

> Wenn du Constanten mit Typ definieren willst, musst du das mit "const
> double g = 9.81;" machen.

Damit wird allerdings eine Variable angelegt, d.h. SRAM verbraucht.
Außerdem dauert das Adressieren einer Variablen länger als das Laden 
einer Konstanten.

Das ist in der Regel bei Konstanten auch nicht nötig.

Besser daher:
1
#define G ((double)9.81)

Aber einbuchstabige defines und Variablen sind generell schlecht (zu 
finden oder umzubenennen). Man sollte mindestens 3 Zeichen nehmen.


Peter

von Ralph (Gast)


Lesenswert?

aus 10*G wird nach dem PreProzessor 10*9.81
Der Compiler wird daraus eine FLOAT Berechung machen, also die 
entsprechenden Libaries einbinden, falls er sie hat, oder eine 
Fehlermeldung ausgeben.

von Gast (Gast)


Lesenswert?

Ich habe auch eine Frage am Rand.
Wenn ich eine funktion xy() habe und darin ein Variable vom Typ char 
deklariere, wahn und wo lohnt sich diese Variable zu initialisieren, 
wenn man sowieso davon ausgeht, dass dieser Variable ein neuer Wert 
erteilt wird?

Z.B.

u8 xy(u8 a)
{
  u8 b;
  b = a;
  return b;
}

oder

u8 xy(u8 a)
{
  u8 b=0x00;
  b = a;
  return b;
}

von Frank (Gast)


Lesenswert?

@Ralph
Der Compiler wird, wenn er einigermassen was taugt, deshalb keine Libs 
einbinden, denn er wird den Wert schon beim compilieren berechnen!

von Karl H. (kbuchegg)


Lesenswert?

Gast wrote:
> Wenn ich eine funktion xy() habe und darin ein Variable vom Typ char
> deklariere, wahn und wo lohnt sich diese Variable zu initialisieren,
> wenn man sowieso davon ausgeht, dass dieser Variable ein neuer Wert
> erteilt wird?
>
> Z.B.
>
> u8 xy(u8 a)
> {
>   u8 b;
>   b = a;
>   return b;
> }
>
> oder
>
> u8 xy(u8 a)
> {
>   u8 b=0x00;
>   b = a;
>   return b;
> }

Wenn du Variable dann sowieso einen neuen Wert bekommt, warum
initialisierst du sie dann nicht einfach mit genau diesem 'neuen'
Wert

u8 xy(u8 a)
{
   u8 b = a;
   return b;
}

von Ralph (Gast)


Lesenswert?

@Frank

Ok einverstanden für 10*9.81 setzt der Compiler direkt 98.1 ein

Aber dieser Wert (98.1) wird ja irgendwo verwendet werden. Bei der 
nächsten Verwendung kommen die Float Libs.. zum Zuge.


Variablen initialisierung:

Sauber und Sicher ist es, wenn du jede Variable bei oder nach der 
Deklaration sofort Initialisiert.

Wenn du sicherstellen kannst, das ein definierter Schreibzugriff vor dem 
1.Lesezugriff auf die Variable durchgeführt wird, dann kannst du die 
Initialierung weglassen.
Aber Achtung, du spart damit eine Zuweisung,also geringfügig Code, aber 
nimmst damit ein großes Risiko in Kauf das du bei einem Lesezugriff 
einen ungültigen Wert in einer Variable hast.

von Detlev T. (detlevt)


Lesenswert?

Peter Dannegger wrote:
>> Wenn du Constanten mit Typ definieren willst, musst du das mit "const
>> double g = 9.81;" machen.
>
> Damit wird allerdings eine Variable angelegt, d.h. SRAM verbraucht.

Das sollte eigentlich nicht passieren, wenn der Compiler was taugt. Eine 
solche Konstruktion nennt man "benannte Konstante". Da "weiß" der 
Compiler, dass sie unveränderlich ist und daher keinen Speicherplatz 
braucht.

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Ralph wrote:
> @Frank
>
> Ok einverstanden für 10*9.81 setzt der Compiler direkt 98.1 ein
>
> Aber dieser Wert (98.1) wird ja irgendwo verwendet werden. Bei der
> nächsten Verwendung kommen die Float Libs.. zum Zuge.

Wenn die Zuweisung an eine Integervariable erfolgt dann werden da gar 
keine Libs dazugebunden da der Compiler bereits zur Compilezeit die 
Umwandlung vornehmen kann.

Detlev T. wrote:
> Peter Dannegger wrote:
>>> Wenn du Constanten mit Typ definieren willst, musst du das mit "const
>>> double g = 9.81;" machen.
>>
>> Damit wird allerdings eine Variable angelegt, d.h. SRAM verbraucht.
>
> Das sollte eigentlich nicht passieren, wenn der Compiler was taugt. Eine
> solche Konstruktion nennt man "benannte Konstante". Da "weiß" der
> Compiler, dass sie unveränderlich ist und daher keinen Speicherplatz
> braucht.

Bei einem "const double" weiß er das nicht da das Ding noch in einem 
anderen Modul (dort sogar als einfaches "double") verwendet werden kann. 
Somit muss der Compiler Speicherplatz reservieren. Der Linker der das 
dann auflösen könnte weiß aber nichts mehr über evtl. vorhandene 
Modifizierer. Der kennt nur noch Namen und Größen. Was man allerdings 
machen kann ist das Teil "static const double" zu machen. Dann kann es 
der Compiler wirklich wegoptimieren da die Variable in anderen Modulen 
nicht sichtbar ist.

Matthias

von Detlev T. (detlevt)


Lesenswert?

@Matthias
Aus meiner Sicht gibt so ein Modifier zusätzliche Informationen an den 
Compiler für zwei Aufgaben:
1) Der Compiler kann den Code besser optimieren (auch z.B. const 
Variablen ins ROM)
2) Er kann Inkonsistenten detektieren und den Programmierer warnen. 
Beispiel:
1
#include <stdio.h>
2
3
const int x_const = 1;
4
      int x_var   = 2;
5
6
void foofunc(int * x)
7
{
8
 *x = 4;
9
}
10
11
int main(void)
12
{
13
  foofunc(&x_var);
14
  x_const = 3;  
15
  foofunc(&x_const);
16
17
  printf("%i,%i\r\n", x_var, x_const); 
18
  return 0;
19
}
gcc meint dazu:
consttest.c:14: Fehler: Zuweisung der schreibgeschützten Variable 
»x_const«
consttest.c:15: Warnung: Übergabe des Arguments 1 von »foofunc« entfernt 
Kennzeichner von Zeiger-Ziel-Typ

Lässt man Zeile 14 weg, erhält man zwar ein ausführbares Compilat, das 
aber mit einem "Segmentation fault (core dumped)" abbricht, wohl weil 
man schreibend auf einen schreibgeschützten Bereich zugreifen will. Bei 
einem µC könnte das, wie gesagt, auch das ROM sein.

Eine benannte Konstante belegt also keineswegs automatisch Platz im RAM.

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.