Forum: Mikrocontroller und Digitale Elektronik fragen zu const und static variablen


von Basti (Gast)


Lesenswert?

Hallo,
ich habe eine frage zum Programmieren in C.
eine Variable, die als const definiert ist z.B.
1
const uint8_t value = 0x35
Das const sagt doch nur aus, dass value nicht mehr verändert werden darf 
oder? Was wäre der unterschied zu einem define?
1
#define value 0x35

Das zweite wäre zu static.
Ist eine variable als static deklariert (ausserhalb jeder Funktion in 
einer c-file), ist diese für die ganze datei bekannt. ist eine variable 
innerhalb einer funktion als static deklariert, wird die Variable nur 
beim erstmaligen Aufruf definiert und behält den Wert nach der Funktion 
bei.

Haben diese beiden sachen auch irgendwas mit speichern zu tun? Was würde 
weniger speicher benötigen?

Angenommen, ich habe eine for-schlife, die 10000mal aufgerufen wird. In 
dieser schleife wird eine Funktion aufgerufen, welche einen Wert aus dem 
EEPRPOM liest
1
uint8_t readEEPROM(uint32 adresse)
2
{
3
  uint32 value;
4
  uint32 *valueAdresse = (uint32*) adresse;
5
  value = *valueAdresse;
6
  return value
7
}

gäbe es einen Unterschied, ob ich value als static deklarieren würde?

von Karl M. (Gast)


Lesenswert?

Frage dich bitte, welcher Datentyp dies hat:
1
#define value 0x35

Dann wirst Du dir auch selbst ein weitere Frage beantworten können.

von Stefan F. (Gast)


Lesenswert?

Eine Variable belegt Speicher im RAM oder Flash Speicher.

Mit #define definierst du hingegen Textersetzungen, die auf den 
Quelltext angewendet werden, bevor er compiliert wird. Die Zahlen landen 
daher meistens im Programmspeicher.

von Bernd K. (prof7bit)


Lesenswert?

static außerhalb einer Funktion bedeutet die Variable ist nur in dieser 
C-Datei sichtbar nicht außerhalb. Ohne static wäre sie global im ganzen 
Programm sichtbar. So kannst Du kurze knappe Namen verwenden ohne Dir 
über Kolissionen mit Variablen aus anderen Dateien Gedanken zu machen.

Grundsätzlich sollte man alle (modul-)globalen Variablen in einer Datei 
static machen (und auch alle Funktionen), es sei denn die Variable oder 
die Funktion soll wirklich programm-global von außerhalb dieser Datei 
aus erreichbar sein.

static innerhalb einer Funktion hast Du ja bereits selbst erklärt.

Beide (static in der Funktion und static außerhalb der Funktion) werden 
auf dem Heap gespeichert. Normale lokale Variablen die nur während der 
Dauer des Funktionsaufrufs existieren befinden sich auf dem Stack.

Das Wort "static" ist eigentlich etwas unglücklich gewählt weil es je 
nach Verwendung eigentlich 2 komplett verschiedene Dinge bedeutet. 
Eigentlich hätte man hier 2 verschiedene Schlüsselwörter wählen sollen 
als das selbe in einem anderen Kontext mit anderer Bedeutung 
wiedezuverwenden, aber man kann leider nicht alles haben.

: Bearbeitet durch User
von HildeK (Gast)


Lesenswert?

Basti schrieb:
> ich habe eine frage zum Programmieren in C.
> eine Variable, die als const definiert ist z.B.const uint8_t value =
> 0x35Das const sagt doch nur aus, dass value nicht mehr verändert werden
> darf oder?
Ja.

> Was wäre der unterschied zu einem define?
   #define value 0x35

Jeder gültigen Bezeichner 'value' im Quelltext wird mit '0x35' ersetzt - 
zur Compilezeit. Das ist keine Variable, sondern genau so, wie wenn du 
an der Stelle von 'value' einfach '0x35' schreiben würdest.

> Ist eine variable als static deklariert (ausserhalb jeder Funktion in
> einer c-file), ist diese für die ganze datei bekannt.
Wenn du außerhalb von 'main' oder Funktionen eine Variable definierst, 
ist sie auch ohne 'static' in der ganzen Datei bekannt. Mit 'static' ist 
sie nur in der Datei bekannt.

> Angenommen, ich habe eine for-schlife, die 10000mal aufgerufen wird. In
> dieser schleife wird eine Funktion aufgerufen, welche einen Wert aus dem
> EEPRPOM liest
> uint8_t readEEPROM(uint32 adresse)
> {
>   uint32 value;
>   uint32 *valueAdresse = (uint32*) adresse;
>   value = *valueAdresse;
>   return value
> }
>
> gäbe es einen Unterschied, ob ich value als static deklarieren würde?
Ja, ohne 'static' wird sie nur temporär in einem Register angelegt. Mit 
'static' dürfte dafür ein fester Platz im RAM belegt werden.

von leo (Gast)


Lesenswert?

Stefanus F. schrieb:
> Die Zahlen landen
> daher meistens im Programmspeicher.

Das hat doch nichts mit #define zu tun. Eher mit Harward vs. v.Neumann 
Architektur, Befehlssatz und -groesse usw.

leo

von leo (Gast)


Lesenswert?

leo schrieb:
> Stefanus F. schrieb:
>> Die Zahlen landen
>> daher meistens im Programmspeicher.
>
> Das hat doch nichts mit #define zu tun. Eher mit Harward vs. v.Neumann
> Architektur, Befehlssatz und -groesse usw.

BTW re. Komplikation von Zahlenkonstanten in Assembler, e.g:
https://alisdair.mcdiarmid.org/arm-immediate-value-encoding/
wo und wie die dann stehen ist kompliziert ;-)

leo

von P. S. (namnyef)


Lesenswert?

Basti schrieb:
> Das const sagt doch nur aus, dass value nicht mehr verändert werden darf
> oder? Was wäre der unterschied zu einem define?

Eine wichtige Präzisierung: Const Variablen dürfen vom Code nicht 
geändert werden. Beispielsweise kann eine Variable, die auf ein 
ADC-Ergebnis-Register gemappt ist, "const" sein. Die Variable wird aber 
logischerweise von der Hardware geändert.

Ein passenderer Begriff für "const" wäre als eher "read only".

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

P. S. schrieb:
> Beispielsweise kann eine Variable, die auf ein
> ADC-Ergebnis-Register gemappt ist, "const" sein.

? ?

Der Zeiger auf diese Zelle darf const sein.
Aber doch nicht die Zelle selber.
Eher volatile.

von Bernd K. (prof7bit)


Lesenswert?

P. S. schrieb:
> "const" sein. Die Variable wird aber
> logischerweise von der Hardware geändert.

Weshalb man sie dann auch konsequenterweise

volatile const

deklarieren sollte, eine durchaus überraschende Wortkombination, aber 
notwendig um dem Compiler mitzuteilen daß dieser Zugriff eine Eingabe 
des Programmes darstellt und so stattzufinden hat wie er programmiert 
wurde.

Zitat CMSIS:
1
/* IO definitions (access restrictions to peripheral registers) */
2
/**
3
    \defgroup CMSIS_glob_defs CMSIS Global Defines
4
5
    <strong>IO Type Qualifiers</strong> are used
6
    \li to specify the access to peripheral variables.
7
    \li for automatic generation of peripheral register debug information.
8
*/
9
#ifdef __cplusplus
10
  #define   __I     volatile             /*!< Defines 'read only' permissions                 */
11
#else
12
  #define   __I     volatile const       /*!< Defines 'read only' permissions                 */
13
#endif
14
#define     __O     volatile             /*!< Defines 'write only' permissions                */
15
#define     __IO    volatile             /*!< Defines 'read / write' permissions              */

: Bearbeitet durch User
von P. S. (namnyef)


Lesenswert?

Arduino Fanboy D. schrieb:
> P. S. schrieb:
>> Beispielsweise kann eine Variable, die auf ein
>> ADC-Ergebnis-Register gemappt ist, "const" sein.
>
> ? ?
>
> Der Zeiger auf diese Zelle darf const sein.
> Aber doch nicht die Zelle selber.
> Eher volatile.

Nein, diese darf auch const sein, um dem Compiler zu sagen, dass der 
Inhalt vom Programm nicht geändert werden darf (in der Regel kann das 
das Programm in diesem Fall auch gar nicht). Die Änderung erfolgt durch 
die Hardware. Deswegen ist es - wie von Bernd K. erwähnt - sinnvoll den 
Inhalt "volatile const" zu machen.
Wie gesagt, kommt des der Realität näher, wenn man sich "const" als 
"read only" vorstellt.

: Bearbeitet durch User
von Finde den Unterschied (Gast)


Lesenswert?

Stefanus F. schrieb:
> Eine Variable belegt Speicher im RAM oder Flash Speicher.
> ... Die Zahlen landen
> daher meistens im Programmspeicher.

Denk da noch einmal darüber nach. ?

von bestucki (Gast)


Lesenswert?

P. S. schrieb:
> Nein, diese darf auch const sein, um dem Compiler zu sagen, dass der
> Inhalt vom Programm nicht geändert werden darf (in der Regel kann das
> das Programm in diesem Fall auch gar nicht). Die Änderung erfolgt durch
> die Hardware.

const (ohne volatile) ist ein Versprechen an den Compiler, dass sich die 
Variable niemals und unter keinen Umständen ändern wird. Dieser darf 
dann den Code optimieren, z.B. dass der Wert der Variable in einer 
Schleife nur einmal gelesen wird und dies kann zu einem Fehlverhalten 
des Programms führen. volatile ist in diesem Fall immer zwingend 
notwendig.
Siehe auch: 
https://stackoverflow.com/questions/4592762/difference-between-const-const-volatile

von Stefan F. (Gast)


Lesenswert?

Finde den Unterschied schrieb:
> Stefanus F. schrieb:
>> Eine Variable belegt Speicher im RAM oder Flash Speicher.
>> ... Die Zahlen landen daher meistens im Programmspeicher.
>
> Denk da noch einmal darüber nach. ?

Anscheinend hast du Gegenteile Erwartet, wie: Die Variable dreht sich 
links herum und #define dreht sich rechts herum. So einfach ist das aber 
nicht.

Eine Variable steht im Quelltext stellvertretend für eine Speicherzelle 
in einem Daten Segment. Normalerweise ist das im RAM, aber wenn die 
Variable Konstant ist kann sie bei bestimmten Prozessoren auch im Flash 
(ROM) stehen.

#define ist eine einfache Textersetzung. Meistens benutzt man das als 
Parameter bei einem Funktionsaufruf oder als Teil einer Mathematischen 
Berechnung. In diesen Fällen werden die Zahlen in der Regel zum 
Bestandteil des Programmcodes und dann stehen im Programmspeicher.

Der Programmspeicher kann sich je nach Architektur mit dem Datenspeicher 
überlappen oder physikalisch getrennt sein. Darum geht es bei dieser 
Betrachtung aber nicht. Es geht um die logischen Speichersegmente:

- Variable Daten
- Konstante Daten
- Programmcode

War das jetzt klarer?

von Michael U. (amiga)


Lesenswert?

Hallo,

bestucki schrieb:
> const (ohne volatile) ist ein Versprechen an den Compiler, dass sich die
> Variable niemals und unter keinen Umständen ändern wird. Dieser darf
> dann den Code optimieren, z.B. dass der Wert der Variable in einer
> Schleife nur einmal gelesen wird und dies kann zu einem Fehlverhalten
> des Programms führen. volatile ist in diesem Fall immer zwingend
> notwendig.

read only für const wäre hier meiner Meinung nach wirklich zutreffender, 
ist aber eben nicht so.

const a;
b = a; ist ok,
a = 23; nicht zulässig.

volatile sagt, das er die Variable jedesmal lesen muß, wenn er sie 
nutzen will, ok.
volatile a;
b = a; ok
a = 23 auch ok, niemand verbietet das. a kann ja z.B. ein Timerregister 
sein, das vom Timer geändert wird, das man aber auch auf einen Wert 
setzen kann.
Beim ADC-Ergebnis wäre das sinnlos, wenn das wie meist ein read only 
Register ist. Da wäre also dann
volatile const zwingend angebracht, damit der Compiler einmal den Wert 
auch bei jedem Zugriff liest (volatile) und ein
a = 23; als unzulässig anmault (const).

Für mich eigentlich völlig einleuchtend, ich weiß doch, was ich da 
programmiere, dem Compiler muß ich es eben nur richtig mitteilen.

Gruß aus Berlin
Michael

von Stefan F. (Gast)


Lesenswert?

Michael U. schrieb:
> Für mich eigentlich völlig einleuchtend, ich weiß doch, was ich da
> programmiere, dem Compiler muß ich es eben nur richtig mitteilen.

In Zeiten on KI, wo man Alexa befehlen kann "Alexa, führe mich an einen 
Ort, wo ich Spaß haben werde", fällt es manchen Leuten schwer, dem 
Computer haarklein und unmissverständlich zu befehlen, was er tun soll.

von Michael U. (amiga)


Lesenswert?

Hallo,

@Stefanus F.:
und völlg OT...

Ein Computer macht nicht immer, was er soll.
Er macht aber immer das, was ihm sagt. :-)

Meine Alexa kann ich gerade nicht fragen, seit mein Kabel-I-Net 
Versorger mich mit einer neuen Kabelbox beglückt hat, kommt Alexa nicht 
mehr in mein WLAN, trotz Werkreset usw. Meine diversen ESPs usw. habe 
aber kein Problem.
ok, den Kabelrouter darf ich alle 1-2 Tage neu starten, mit fast 20 
Geräten per DHCP kommt das Ding nicht richtig klar...

Gruß aus Berlin
Michael

von Stefan F. (Gast)


Lesenswert?

Michael U. schrieb:
> seit mein Kabel-I-Net
> Versorger mich mit einer neuen Kabelbox beglückt hat, kommt Alexa nicht
> mehr in mein WLAN, trotz Werkreset usw. Meine diversen ESPs usw. habe
> aber kein Problem.

Das gleiche Problem hatte ich auch mit einigen aber nicht allen Geräten. 
Offensichtlich genügt es den ESP, einen Router mit der gleichen SSID zu 
finden, wie der alte vorher hatte. Bei anderen geräten musts ich die 
WLAN Konfiguration löschen und neu anegen. Am Router liegt es jedenfalls 
nicht.

> den Kabelrouter darf ich alle 1-2 Tage neu starten

Ich auch. Mache ich mittlerweise per Zeitschaltuhr, so spare ich Nacht 
ein paar Stunden Strom. Seit dem verweigert er die WLAN Anmeldung nur 
noch 1-2x pro Monat.

Haben wir das gleiche Gerät- diese quadratische beidseitig gelochte 
Connect Box von Unitymedia? Den haben die mir aufgezwungen, als mein 
Internet Anschluss unzuverlässig wurde. Das ist er jetzt aber immer 
noch. Ich will das alte Motorola Modem zurück, aber das geht laut 
Unitymedia nicht. Es sei jetzt inkompatibel zum Anschluss.

von Basti (Gast)


Lesenswert?

Ich habe noch mal eine nachfrage bezüglich von defines.
Diese werden ja beim compiliren mit dem wert ersetzt.
Wenn ich zu viele Defines habe (welche nicht im code verwendet werden), 
benötigt das Projekt dadurch aber nicht mehr speicher oder? Da die 
defines, welche nicht verwendet werden nirgends ersetzt werden und auch 
nicht gespeichert werden.

von B. S. (bestucki)


Lesenswert?

Basti schrieb:
> Wenn ich zu viele Defines habe (welche nicht im code verwendet werden),
> benötigt das Projekt dadurch aber nicht mehr speicher oder?

Nur deine Header/Sourcen auf deiner Festplatte, nicht aber dein 
Programm. Die defines werden vor dem compilieren vom Präprozessor 
ersetzt.

von Stefan F. (Gast)


Lesenswert?

Basti schrieb:
> Wenn ich zu viele Defines habe (welche nicht im code verwendet werden),
> benötigt das Projekt dadurch aber nicht mehr speicher oder?

#define definiert Textersetzungen, keine Variablen. Nur Variablen 
belegen Platz in den Daten Segmenten. Nur Programmcode belegt Platz im 
Code Segment.

Ungenutzte #defines erzeugen gar nichts, also belegen sie keinen 
Speicher auf dem Zielcomputer.

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.