Forum: Compiler & IDEs Wie Verwendung von Konstanten erzwingen?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Nowhereman (Gast)


Lesenswert?

Wie kann ich die Verwendung von Konstanten erzwingen?

Mein Beispielcode:
float a,b;
const float Winkel = 45.0;
a = b * sin(Winkel / 360  2  PI);

Worum es mir geht, dass der uC zur Laufzeit nicht jedes mal den Sinus 
von 45° ausrechnen muss, sondern dass der Compiler einfach eine 
Konstante 0.707106781 dafür einsetzt. Klar, ich kann das während der 
Quellcodeeingabe einfach selber mit dem Taschenrechner ausrechnen, will 
das aber nicht! Sinus ist auch nur ein Beispiel, genau so gut könnte da 
auch log oder atn stehen.

von Ben S. (bensch123)


Lesenswert?

Das macht der Compiler bereits für dich, ohne dass du es weißt - sofern 
du Optimierung eingeschaltet hast.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Ben S. schrieb:
> Das macht der Compiler bereits für dich, ohne dass du es weißt - sofern
> du Optimierung eingeschaltet hast.

Für den gcc ist das korrekt. Fragt sich nur, ob der TO überhaupt gcc 
verwendet oder gar die Frage ganz allgemein für alle üblichen C-Compiler 
stellt. Er verrät ja auch nicht den µC.

Code:
1
#include <math.h>
2
#include <stdio.h>
3
4
int main ()
5
{
6
    float a,b;
7
    const float Winkel = 45.0;
8
9
    b = 1; // Initialisierung hat der TO vergessen
10
    a = b * sin(Winkel / 360.0 * 2.0 * M_PI); // M_PI statt PI
11
12
    printf ("%f\n", a);
13
}

Unter Linux übersetzt:
1
$ cc -O -S sin.c && cat sin.s
2
        .file   "sin.c"
3
        .section        .rodata.str1.1,"aMS",@progbits,1
4
.LC1:
5
        .string "%f\n"
6
        .text
7
        .globl  main
8
        .type   main, @function
9
main:
10
.LFB14:
11
        .cfi_startproc
12
        subq    $8, %rsp
13
        .cfi_def_cfa_offset 16
14
        movsd   .LC0(%rip), %xmm0
15
        leaq    .LC1(%rip), %rdi
16
        movl    $1, %eax
17
        call    printf@PLT
18
        movl    $0, %eax
19
        addq    $8, %rsp
20
        .cfi_def_cfa_offset 8
21
        ret
22
        .cfi_endproc
23
.LFE14:
24
        .size   main, .-main
25
        .section        .rodata.cst8,"aM",@progbits,8
26
        .align 8
27
.LC0:
28
        .long   1610612736
29
        .long   1072079006
30
        .ident  "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
31
        .section        .note.GNU-stack,"",@progbits

Wenn der Optimizer eingeschaltet ist, muss man noch nichtmals die 
math-lib libm dazulinken:
1
$ cc -O sin.c -o sin && ./sin
2
0.707107

Die Sinus-Funktion wird also gar nicht aufgerufen - wie man aus dem 
Assembler-Listing auch erkennen kann. Sonst stünde da ein
1
call    sin@PLT
im Assembler-Code.

Ohne Optimizer:
1
$ cc sin.c -o sin && ./sin
2
/tmp/ccyuMhzd.o: In function `main':
3
sin.c:(.text+0x4e): undefined reference to `sin'
4
collect2: error: ld returned 1 exit status

Hier fehlt dann die Option "-lm", also:
1
$ cc sin.c -o sin -lm && ./sin
2
0.707107

Ohne die Optimierung wird demnach die Funktion sin() aus libm benötigt.

: Bearbeitet durch Moderator
von Nowhereman (Gast)


Lesenswert?

Frank M. schrieb:
> Ohne die Optimierung wird demnach die Funktion sin() aus libm benötigt.

Ganz herzlichen Dank. So konnte das endlich einmal geklärt werden.  :-)

von A. S. (achs)


Lesenswert?

Nowhereman schrieb:
> Klar, ich kann das während der Quellcodeeingabe einfach selber mit dem
> Taschenrechner ausrechnen, will das aber nicht!

Der Mittelweg wäre doch, Winkel als #define zu nehmen. Oder C++.

Echte Konstanten gibt es in C halt nicht, bzw. nur mit Compiler-options 
oder als #defines.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

ich verstehe das Problem nicht. Wenn 'const Winkel' in main() berechnet 
wird, dann wird 'Winkel' automatisch in while(1) zur Laufzeit überall 
verwendet.

Etwas anderes wäre es wenn man im Laufzeitcode überall die 
Berechnungsfunktion verwendet/aufruft statt der schon berechneten const 
Variablen. Dann kommt es auf den Compiler an wie er optimieren kann.

von A. S. (achs)


Lesenswert?

Veit D. schrieb:
> ich verstehe das Problem nicht. Wenn 'const Winkel' in main() berechnet
> wird, dann wird 'Winkel' automatisch in while(1) zur Laufzeit überall
> verwendet.

Winkel.ist.konstant. 45.0

Es geht um das a, das zur Laufzeit berechnet.wird (in C, nicht C++), 
statt vom Compiler.

von Klaus W. (mfgkw)


Lesenswert?

Wenn du
 nimmst statt
, kommt derselbe Wert raus

von Walter T. (nicolas)


Lesenswert?

Nur für mich als stiller Mitleser: Hat die Initialisierung von const 
float mit einem double-Literal keinen Overhead oder sonstige Nachteile?

(Ich hätte eine Compiler-Warnung erwartet.)

: Bearbeitet durch User
von Klaus W. (mfgkw)


Lesenswert?

Nein.
Bei der Initialisierung mit einer Konstanten bzw. einem Literal 
konvertiert der Compiler bereits und initalisiert nur mit einer float.

(Bei einer Zuweisung zur Laufzeit aus einer double-Variablen müsste 
konvertiert werden, ist hier aber nicht der Fall.)

von A. S. (achs)


Lesenswert?

Klaus W. schrieb:
> Wenn du
> 1/22–√ 1/2\sqrt{2}

Sehr missverständlich mit 1/2. Lieber

sqrt(2) / 2

oder besser


1 / sqrt(2)

(Und das in latech)

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

Hallo,

gut, dann war ich zum lesen schon zu müde. Dann beziehe ich mich nicht 
auf 'Winkel' sondern auf 'a'. Meine Aussage bleibt die Gleiche. Wenn a 
als Konstante initialisiert wird, dann kann und wird diese zur Laufzeit 
verwendet. Denn das ist kein Funktionsaufruf der an anderer Stelle 
wiederholt werden könnte sondern eine Initialisierung.
1
const float Winkel = 45.0;
2
const float b = 1.0;
3
const float a = b * sin(Winkel / 360 * 2 * M_PI);

von A. S. (achs)


Lesenswert?

Veit D. schrieb:
> Meine Aussage bleibt die Gleiche. Wenn a als Konstante initialisiert
> wird, dann kann und wird diese zur Laufzeit verwendet

Natürlich. Sie wird aber auch zur Laufzeit initialisiert, mit echter 
Berechnung des sin. Wenigstens im Default.

Du verwechselt anscheinend häufiger C und C++.

Hier steht die Sprache zwar nicht explizit, es wurde aber mehrfach 
darauf hingewiesen, da C++ das Problem nicht hat.

: Bearbeitet durch User
von Sven B. (scummos)


Lesenswert?

Das einzige mir bekannte Konstrukt, was dir das garantiert (abgesehen 
davon, einfach ein Literal hinzuschreiben), ist consteval aus C++. 
https://en.cppreference.com/w/cpp/language/consteval

In anderen Faellen musst du dich auf Compileroptimierungen verlassen.

von Veit D. (devil-elec)


Lesenswert?

Na gut.

von Wilhelm M. (wimalopaan)


Lesenswert?

A. S. schrieb:
> Du verwechselt anscheinend häufiger C und C++.

Er hat sich halt an das Bessere gewöhnt ;-)

von Wilhelm M. (wimalopaan)


Lesenswert?

Sven B. schrieb:
> Das einzige mir bekannte Konstrukt, was dir das garantiert (abgesehen
> davon, einfach ein Literal hinzuschreiben), ist consteval aus C++.

Mit consteval deklariert man immediate-functions: diese müssen zur 
Compilezeit ausgewertet werden.

Mit constexpr deklariert man Funktionen, die in einem constexpr-Kontext 
ausgewertet werden können, wenn es möglich ist, d.h. ihr Argumente 
ebenfalls constexpr sind.

Constexpr-"Variablen" sind Variablen, deren Initialisierung zur 
Compilezeit bestimmt wird, entweder durch constexpr (falls möglich) oder 
consteval Funktionen. Das Verwenden einer solchen "Variablen" ist als 
eine constant-expression. Übeall dort, wo sie eingesetzt wird, für das 
zur einer constant-expression (wie ein Literal) und der Compiler wird 
dasselbe damit machen wie mit einem Literal. Das führt im Endeffekt 
dazu, dass die constexpr-"Variablen" keine Variablen (benannte Objekte) 
mehr sind und deswegen sich nicht materialisieren.

von A. S. (achs)


Lesenswert?

Wilhelm M. schrieb:
> Das führt im Endeffekt dazu, dass die constexpr-"Variablen" keine
> Variablen (benannte Objekte) mehr sind und deswegen sich nicht
> materialisieren.

Das gilt doch prinzipiell auch für const Variablen, die zur kompilezeit 
bzw. Linkzeit bekannt sind, also wie beim TO. Nur das es halt keinen 
Fehler gibt, wenn das nicht der Fall ist.

von Wilhelm M. (wimalopaan)


Lesenswert?

A. S. schrieb:
> Wilhelm M. schrieb:
>> Das führt im Endeffekt dazu, dass die constexpr-"Variablen" keine
>> Variablen (benannte Objekte) mehr sind und deswegen sich nicht
>> materialisieren.
>
> Das gilt doch prinzipiell auch für const Variablen, die zur kompilezeit
> bzw. Linkzeit bekannt sind, also wie beim TO. Nur das es halt keinen
> Fehler gibt, wenn das nicht der Fall ist.

Ja.

constexpr bedeutet const, und const (bei global bzw. namespace) bedeutet 
internal-linkage. Solange man nicht die Adresse bestimmt, wird nicht 
materialisiert.

extern const kann man zwar schreiben und ist dann eine Deklaration. Die 
wieder kann sich nur auch eine vorher definiertes const-Objekt beziehen 
(e.g. im Header).

Mit mehrfachen const-Objekte bekommt man also in unterschiedlichen TU 
unterschiedliche Adresse für const.

constexpr ist implizit inline. Hier bekommt man dieselbe Adresse. Das 
kann man mit const auch machen, dann als inline const etwa in Headern.

Ja, und wie schon gesagt, constexpr Objekte erzwingen ein Compile-Zeit 
Initialisierung, const nicht.

von Klaus W. (mfgkw)


Lesenswert?

Um jetzt etwas pingelig zu werden:
In C und C++ heißt const genau genommen nicht, daß ein Objekt konstant 
ist.
Sondern nur, daß man es im Geltungsbereich des const nicht ändert.

Beispiel:
  const volatile  int i = 0;
heißt: hier wird i nicht mehr geändert, aber in einem anderen Thread 
oder einem Signalhandler, Interrupt o.ä. kann es geändert werden. Dort 
muß es dann ohne const deklariert werden natürlich.

von Wilhelm M. (wimalopaan)


Lesenswert?

Klaus W. schrieb:
> Um jetzt etwas pingelig zu werden:

Das ist nicht pingelig, sondern absolut korrekt:

const == read-only

von Vincent H. (vinci)


Lesenswert?

Wilhelm M. schrieb:
> constexpr ist implizit inline. Hier bekommt man dieselbe Adresse. Das
> kann man mit const auch machen, dann als inline const etwa in Headern.

Das stimmt nicht. Constexpr Variablen sind nicht implizit inline.

von A. S. (achs)


Lesenswert?

Wilhelm M. schrieb:
> const == read-only

Für C++ heißt const auch konstant. Zumindest bei const int x=3;

Und wie bitte wird in C bei

Klaus W. schrieb:
> Beispiel:
>   const volatile  int i = 0;
> heißt: hier wird i nicht mehr geändert, aber in einem anderen Thread
> oder einem Signalhandler, Interrupt o.ä. kann es geändert werden.

i ins RAM gelegt wird?

: Bearbeitet durch User
von Wilhelm M. (wimalopaan)


Lesenswert?

Vincent H. schrieb:
> Constexpr Variablen sind nicht implizit inline.

Ja, da hast Du Recht. hatte ich mit Funktionen verwechselt. Danke.

von Wilhelm M. (wimalopaan)


Lesenswert?

A. S. schrieb:
> Für C++ heißt const auch konstant.

Nein. Und das Beispiel mit const volatile hast Du ja selbst geliefert.

Oder
1
int x;
2
const int& rx = x;

Hier ist ganz klar ersichtlich, dass const hier read-only bedeutet.

von A. S. (achs)


Lesenswert?

Wilhelm M. schrieb:
> A. S. schrieb:
>> Für C++ heißt const auch konstant.
>
> Nein. Und das Beispiel mit const volatile hast Du ja selbst geliefert.
>
> Oder
>
1
> int x;
2
> const int& rx = x;
3
>
>
> Hier ist ganz klar ersichtlich, dass const hier read-only bedeutet.

Wilhelm, Du hast Klaus Behauptung

Klaus W. schrieb:
> C++ heißt const genau genommen nicht, daß ein Objekt konstant
> ist.

bestätigt mit

Wilhelm M. schrieb:
> const == read-only

Natürlich gibt es Fälle, wie Dein Beispiel, wo es nur Read-Only 
bedeutet.

Hier im Forum verwechseln Leute häufig den Fundamentalen Unterschied 
eines Objektes mit const in C und C++: In C nur Read-Only, in C++ jedoch 
konstant.

Dass bei einem Zeiger oder einer Referenz etwas anderes gilt, bleibt da 
unbenommen. Ein Zeiger auf ein Objekt ist kein Objekt.

von Klaus W. (mfgkw)


Lesenswert?

A. S. schrieb:
> Dass bei einem Zeiger oder einer Referenz etwas anderes gilt, bleibt da
> unbenommen. Ein Zeiger auf ein Objekt ist kein Objekt.

Aber das, worauf der Zeiger zeigt, ist ein Objekt.
Und auf dasselbe Objekt kann auch in C++ ein Zeiger zeigen, der es als 
const sieht, und ein anderer, über den es geändert werden kann.

A. S. schrieb:
> Klaus W. schrieb:
>> Beispiel:
>>   const volatile  int i = 0;
>> heißt: hier wird i nicht mehr geändert, aber in einem anderen Thread
>> oder einem Signalhandler, Interrupt o.ä. kann es geändert werden.
>
> i ins RAM gelegt wird?

Auch in C++ kann ich von einer const-Variablen eine Adresse bilden.
Spätestens dann wird der Compiler die auch im RAM halten.

von Wilhelm M. (wimalopaan)


Lesenswert?

A. S. schrieb:
> In C nur Read-Only, in C++ jedoch
> konstant.

Das musst Du mal erklären.

A. S. schrieb:
> Ein Zeiger auf ein Objekt ist kein Objekt.

Eine Variable ist (im engeren Sinn) ein benanntes Objekt - auch eine 
Zeigervariable.

Ein Objekt ist ein Speicherbereich, in dem ein Wert abgelegt ist.

Ein Wert ist eine Bitfolge, die entsprechend einem Datentyp 
interpretiert wird.

Ein Datentyp beschreibt die möglichen Operationen und die möglichen, 
(beobachtbaren) Werte.

von A. S. (achs)


Lesenswert?

Wilhelm M. schrieb:
> A. S. schrieb:
>
>> In C nur Read-Only, in C++ jedoch
>> konstant.
>
> Das musst Du mal erklären

const int x = 2;

In C++ kann ich das x als Konstante verwenden, z.b. int a[x];

X ist konstant, eine Konstante.

von Wilhelm M. (wimalopaan)


Lesenswert?

A. S. schrieb:
> In C++ kann ich das x als Konstante verwenden, z.b. int a[x];

Und die meinst, das geht in C nicht?

A. S. schrieb:
> X ist konstant, eine Konstante.

Nö:
[c]
*const_cast<int*>(&x) = 42;
[c]

von Klaus W. (mfgkw)


Lesenswert?

Wilhelm M. schrieb:
> Nö:
> [c]
> *const_cast<int*>(&x) = 42;
> [c]

Wobei das durch den Compiler geht, aber nicht zwangsläufig zur Laufzeit 
auch funktioniert (unabhängig davon ob C oder C++).
Es könnte nämlich sein, daß es x in einem Speicher abgelegt wird, der 
gar nicht beschreibbar ist zur Laufzeit.

von A. S. (achs)


Lesenswert?

Wilhelm M. schrieb:
> Und die meinst, das geht in C nicht?

nein.

Wilhelm M. schrieb:
> *const_cast<int*>(&x) = 42;

Ändert nichts mehr daran, dass der Compiler 2 für x eingetragen hat.

Sag mal, was soll das. Du kennst C++ deutlich besser als ich und das 
sind doch wirklich Anfängersachen.

von Wilhelm M. (wimalopaan)


Lesenswert?

A. S. schrieb:
> Sag mal, was soll das. Du kennst C++ deutlich besser als ich und das
> sind doch wirklich Anfängersachen.

Ja, wohl geistige Umnachtung mit Traum im UB-Land.
Danke für den Weckruf!

von Klaus W. (mfgkw)


Lesenswert?

Vielleicht zur allgemeinen Erbauung ein kleines Programm?

Es wird eine const i vereinbart, mit 12 initialisiert, und ein Zeiger 
darauf. Der ist jetzt nicht ein Zeiger auf const i, sondern auf const 
(was man natürlich nicht machen sollte, aber der Compiler verwehrt es 
nicht.

Man hat also im RAM nur eine int-Variable.

Die wird zweimal ausgegeben, erst als i selbst und dann über den Zeiger.

Über den Zeiger wird sie dann zu 42 geändert und wieder auf beide Arten 
ausgegeben.
1
#include <iostream>
2
3
void zeigeInt( const char *kommentar, const int i )
4
{
5
  std::cout << kommentar << i << std::endl;
6
}
7
8
int main( int nargs, char **args )
9
{
10
  const  int     i = 12;
11
12
  int           *non_const_ptr_i = const_cast<int*>(&i); // böse, aber nicht verboten
13
14
  zeigeInt( "vorher i direkt      ", i );
15
  zeigeInt( "vorher ueber Zeiger  ", *non_const_ptr_i );
16
  *non_const_ptr_i = 42;
17
  zeigeInt( "nachher i direkt     ", i );
18
  zeigeInt( "nachher ueber Zeiger ", *non_const_ptr_i );
19
20
  return 0;
21
}
1
klaus@lap7:~$ g++ -Wall -std=c++14 a.cpp -o a && ./a
2
vorher i direkt      12
3
vorher ueber Zeiger  12
4
nachher i direkt     12
5
nachher ueber Zeiger 42
6
klaus@lap7:~$ g++ -Wall -std=c++17 a.cpp -o a && ./a
7
vorher i direkt      12
8
vorher ueber Zeiger  12
9
nachher i direkt     12
10
nachher ueber Zeiger 42
11
klaus@lap7:~$ g++ -Wall -O3 -std=c++0x a.cpp -o a && ./a
12
vorher i direkt      12
13
vorher ueber Zeiger  12
14
nachher i direkt     12
15
nachher ueber Zeiger 42
16
klaus@lap7:~$


Weil der böse cast zu undefiniertem Verhaöten führt, kann das Ergebnis 
mit einem anderen Compiler theoretisch auch anders aussehen.

Aber zumindest sieht man hier, was der gcc sich dabei denkt:
Die Variable i ist als const deklariert, also denkt sich der gcc, daß 
sie sich nicht ändert und nimmt bei der Verwendung des Werts gar nichts 
aus dem Speicher, sondern setzt gleich direkt den Wert 12 jeweils ein.

Weil ich aber die Adresse von i verwende, ist er gezwungen, tatsächlich 
auch eine int-Variable anzulegen (was er sonst zumnindest mit 
Optimierung weglassen würde).

Über diese Adresse kann ich in der zweiten Ausgabe ebenfalls 12 sehen,

Ebenfalls über die Adresse ändere ich den Wert zu 42, und gebe wieder 
auf beide Arten aus. Bei i nimmt der Code gar nicht den Wert aus dem 
Speicher ("ist ja const..."), sondern der Compiler setzt wieder gleich 
die vermutete 12 ein.
Über den Zeiger gebe ich dagegen den wirklichen Wert 42 aus.

Interessant: ändere ich i von const i zu const volatile i, dann verlässt 
sich der Compiler nicht mehr auf das const, sondern macht es richtig:
1
#include <iostream>
2
3
void zeigeInt( const char *kommentar, const int i )
4
{
5
  std::cout << kommentar << i << std::endl;
6
}
7
8
int main( int nargs, char **args )
9
{
10
  const volatile  int     i = 12;
11
12
  int           *non_const_ptr_i = const_cast<int*>(&i); // böse, aber nicht verboten
13
14
  zeigeInt( "vorher i direkt      ", i );
15
  zeigeInt( "vorher ueber Zeiger  ", *non_const_ptr_i );
16
  *non_const_ptr_i = 42;
17
  zeigeInt( "nachher i direkt     ", i );
18
  zeigeInt( "nachher ueber Zeiger ", *non_const_ptr_i );
19
20
  return 0;
21
}
1
klaus@lap7:~$ g++ -Wall -O3 -std=c++0x a.cpp -o a && ./a
2
vorher i direkt      12
3
vorher ueber Zeiger  12
4
nachher i direkt     42
5
nachher ueber Zeiger 42

Mir ist klar, daß man so nicht programmieren soll.
Aber vielleicht erhellt es etwas die Diskussion um const.

: Bearbeitet durch User
von A. S. (achs)


Lesenswert?

Klaus W. schrieb:
> volatile

Ich vermute Mal, das volatile in C++ eine ähnliche Bedeutung hat, wie in 
C. Nämlich das Objekt tatsächlich auszulesen.

Überraschend für mich wäre, wenn Du nach der Änderung von x ein Array 
char a[x] anlegst. Und sizeof(a) dann 42 ergibt. Das wäre ein Hinweis, 
dass der Compiler x nicht als Konstante sieht.

von Rolf M. (rmagnus)


Lesenswert?

Wilhelm M. schrieb:
> Das führt im Endeffekt dazu, dass die constexpr-"Variablen" keine Variablen
> (benannte Objekte) mehr sind und deswegen sich nicht materialisieren.

Im Sine der Sprache sind sie immer noch Variablen.

Wilhelm M. schrieb:
> A. S. schrieb:
>> Für C++ heißt const auch konstant.
>
> Nein. Und das Beispiel mit const volatile hast Du ja selbst geliefert.
>
> Oder
> int x;
> const int& rx = x;
>
> Hier ist ganz klar ersichtlich, dass const hier read-only bedeutet.

rx ist aber kein Objekt.

A. S. schrieb:
> Dass bei einem Zeiger oder einer Referenz etwas anderes gilt, bleibt da
> unbenommen. Ein Zeiger auf ein Objekt ist kein Objekt.

Ein Zeiger ist schon ein Objekt. Aber das const bezieht sich in nicht 
auf den Zeiger. Ein const int* ist kein konstanter Zeiger, sondern ein 
Zeiger, über den man das Objekt, auf das er zeigt, nicht ändern kann. 
Das sagt weder etwas über die Konstantheit des Zeigers aus, noch etwas 
darüber, ob das Zielobjekt selbst eine Konstante ist.

Klaus W. schrieb:
> A. S. schrieb:
>> Klaus W. schrieb:
>>> Beispiel:
>>>   const volatile  int i = 0;
>>> heißt: hier wird i nicht mehr geändert, aber in einem anderen Thread
>>> oder einem Signalhandler, Interrupt o.ä. kann es geändert werden.
>>
>> i ins RAM gelegt wird?
>
> Auch in C++ kann ich von einer const-Variablen eine Adresse bilden.
> Spätestens dann wird der Compiler die auch im RAM halten.

Er muss sie so oder so ins RAM legen, wenn sie volatile ist.

A. S. schrieb:
> Wilhelm M. schrieb:
>> A. S. schrieb:
>>
>>> In C nur Read-Only, in C++ jedoch
>>> konstant.
>>
>> Das musst Du mal erklären
>
> const int x = 2;
>
> In C++ kann ich das x als Konstante verwenden, z.b. int a[x];
>
> X ist konstant, eine Konstante.

Ja. In C++ gibt es allerdings zwei Arten von Initialisierung, nämlich 
statische und dynamische. Statische Initialisierung erfolgt zur 
Compilezeit, dynamische zur Laufzeit. In C könnten Objekte mit 
statischer Lebensdauer auch nur statisch initialisiert werden, während 
diese Einschränkung in C++ nicht besteht. Dein x kann hier verwendet 
werden, weil es statisch initialisiert wurde. Würde es dynamisch 
initialisiert, z.B. durch einen Funktionsaufruf, dann würde das nicht 
mehr gehen, obwohl x const ist.

Wilhelm M. schrieb:
>> A. S. schrieb:
>>
>>> In C nur Read-Only, in C++ jedoch
>>> konstant.

In C++ konstant oder nur read-only, je nach Kontext.

> A. S. schrieb:
>> In C++ kann ich das x als Konstante verwenden, z.b. int a[x];
>
> Und die meinst, das geht in C nicht?

Es geht in C nur, wenn das Array lokal ist und VLAs unterstützt werden. 
Sonst geht es nicht, da eben nur konstante Ausdrücke als Array-Größen 
verwendet werden dürfen und x kein solcher ist.

> A. S. schrieb:
>> X ist konstant, eine Konstante.
>
> Nö:
> [c]
> *const_cast<int*>(&x) = 42;
> [c]

Das hat undefiniertes Verhalten, und es wird in der Praxis auch oft 
nicht so funktionieren, wie du dir das denkst.

: Bearbeitet durch User

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]
  • [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.

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