Hallo,
ich habe eine frage zum Programmieren in C.
eine Variable, die als const definiert ist z.B.
1
constuint8_tvalue=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_treadEEPROM(uint32adresse)
2
{
3
uint32value;
4
uint32*valueAdresse=(uint32*)adresse;
5
value=*valueAdresse;
6
returnvalue
7
}
gäbe es einen Unterschied, ob ich value als static deklarieren würde?
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.
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.
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.
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
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
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".
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.
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.
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.
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. ?
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
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?
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
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.
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
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.
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.
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.
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.