Forum: PC-Programmierung C Programmierung ohne Pointer?


von Philipp Klaus K. (pkk)


Lesenswert?

Cyblord -. schrieb:
>
> Allerdings kostet die Überprüfung zur Laufzeit eben CPU Zeit und
> Speicher. Irgendwo müssen die Grenzen eingetragen sein, es muss ein Code
> laufen der diese Grenzen bei jedem Zugriff prüft. Sicherheitsgurte gibts
> hier nicht umsonst. Und grade im Embedded Umfeld will niemand
> "versteckten" Code der schnell mal 30% der Laufzeit in einer Schleife
> mit Arrayzugriffen ausmachen kann.

Klar. Drum ist es ja praktisch, dass es hier undefiniertes Verhalten 
gibt, dass den Implementierungen die Freiheit gibt, die 
unterschiedlichen Anforderungen verschiedener Programmierer umzusetzen.

von Jemand (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> C ist quasi die Ente/Käfer/Trabbi unter den Automobilen. Nicht schlecht,
> aber auch nicht deppensicher.

Wären da ein Donkervoort oder Caterham nicht passendere Autovergleiche? 
Ich mein, für besondere Fahrleistungen sind Enten, Trabbis und Käfer ja 
nun nicht gerade bekannt.

von Stefan F. (Gast)


Lesenswert?

Jemand schrieb:
> Wären da ein Donkervoort oder Caterham nicht passendere Autovergleiche?

Die kenne ich nicht. Wenn ich mir die Fotos bei Google anschaue: nein, 
so cool hat C noch nie ausgesehen. Obwohl - die offene Karosserie passt.

> Ich mein, für besondere Fahrleistungen sind Enten,
> Trabbis und Käfer ja nun nicht gerade bekannt.

C läuft auf prima mit kleinem "Motor".

Ich musste mal Java auf einem 386er nutzen, das war super ätzend.

von Sheeva P. (sheevaplug)


Lesenswert?

Stefan ⛄ F. schrieb:
> Jemand schrieb:
>> Wären da ein Donkervoort oder Caterham nicht passendere Autovergleiche?
>
> Die kenne ich nicht. Wenn ich mir die Fotos bei Google anschaue: nein,
> so cool hat C noch nie ausgesehen. Obwohl - die offene Karosserie passt.

Paßt auch sonst vieles: keine Servolenkung, kein Bremskraftverstärker, 
kein ABS oder ASR, wie Donkervoort auf der alten Seite schrieb: "the 
driver is in charge".

>> Ich mein, für besondere Fahrleistungen sind Enten,
>> Trabbis und Käfer ja nun nicht gerade bekannt.
>
> C läuft auf prima mit kleinem "Motor".
>
> Ich musste mal Java auf einem 386er nutzen, das war super ätzend.

Wärgs, mein herzliches Beileid!

von Sebastian W. (wangnick)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich musste mal Java auf einem 386er nutzen, das war super ätzend.

Was Pointer in C sind, sind Threadpools in Java. Man muss schon wissen 
was man tut ...

LG, Sebastian

von Nop (Gast)


Lesenswert?

Philipp Klaus K. schrieb:

> Wer diese Überprüfung will, kann das bei GCC und LLVM  per
> -fsanitize=array-bounds machen.

Leider funktioniert die nur, wenn direkt auf dem Array gearbeitet wird 
und nicht, wenn es an eine Funktion übergeben wird, wo es zum Pointer 
verflacht. Letzteres ist aber der häufigere Fall.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Stefan ⛄ F. schrieb:
> Jemand schrieb:
>> Wären da ein Donkervoort oder Caterham nicht passendere Autovergleiche?
>
> Die kenne ich nicht. Wenn ich mir die Fotos bei Google anschaue: nein,
> so cool hat C noch nie ausgesehen. Obwohl - die offene Karosserie passt.
>
>> Ich mein, für besondere Fahrleistungen sind Enten,
>> Trabbis und Käfer ja nun nicht gerade bekannt.
>
> C läuft auf prima mit kleinem "Motor".

Caterham und Donkervoort sind Sohn und Stiefsohn des legendären Lotus
Seven, und schon der war bekannt dafür, trotz des im Vergleich zur
Konkurrenz geringeren Hubraums abzugehen wie Schmidts Katze. Wie hat er
das gemacht? Durch Light-Weight. Auch das passt ganz gut zu C :)

von Stefan F. (Gast)


Lesenswert?

Yalu X. schrieb:
> Wie hat er das gemacht? Durch Light-Weight.
> Auch das passt ganz gut zu C

Ja. Man lässt alle Schnörkel und Anbauten weg, die man weglassen kann.

Sheeva P. schrieb:
> wie Donkervoort auf der alten Seite schrieb: "the
> driver is in charge".

Wer das nicht gut findet: völlig OK, es gibt andere Programmiersprachen 
mit anderen Zielen.

von Wilhelm M. (wimalopaan)


Lesenswert?

Nop schrieb:
> Philipp Klaus K. schrieb:
>
>> Wer diese Überprüfung will, kann das bei GCC und LLVM  per
>> -fsanitize=array-bounds machen.
>
> Leider funktioniert die nur, wenn direkt auf dem Array gearbeitet wird
> und nicht, wenn es an eine Funktion übergeben wird, wo es zum Pointer
> verflacht. Letzteres ist aber der häufigere Fall.

Auch ein Grund, warum C oder "das C in C++" nicht verwenden sollte.

Auch wer keine einzige Klasse schreibt, kann doch Vorteile aus C++ 
ziehen. Und mit einem Funktions-template vermeidet man das "decay".

von mh (Gast)


Lesenswert?

Wilhelm M. schrieb:
> Auch wer keine einzige Klasse schreibt, kann doch Vorteile aus C++
> ziehen. Und mit einem Funktions-template vermeidet man das "decay".

Das ist nun wirklich unsinn. In C++ nutzt man std::vector und std::array 
und hat das Problem mit dem decay gar nicht erst.

von Wilhelm M. (wimalopaan)


Lesenswert?

mh schrieb:
> Wilhelm M. schrieb:
>> Auch wer keine einzige Klasse schreibt, kann doch Vorteile aus C++
>> ziehen. Und mit einem Funktions-template vermeidet man das "decay".
>
> Das ist nun wirklich unsinn.

Sehe ganz und gar nicht so.
Dann hast Du mich falsch verstanden. Viele wollten kein C++ benutzen, 
oder können es nicht wegen unterschiedlichster Gründe. Etwa weil sie die 
stdlib nicht auf ihrer Plattform haben oder nutzen wollen/können.

Mir ging es nur darum.

> In C++ nutzt man std::vector und std::array
> und hat das Problem mit dem decay gar nicht erst.

s.o., wenn man das nutzen will oder kann.
Natürlich ist es klar, dass man das nutzt, wenn man C++ umfänglich 
verwendet. Hier geht es aber um "das C im C++".

von Rolf M. (rmagnus)


Lesenswert?

Wilhelm M. schrieb:
> Und mit einem Funktions-template vermeidet man das "decay".

Allerdings hat man dann für jede Array-Größe, mit der man die Funktion 
nutzt, eine eigene Instanz dieses Templates. Und die Größe muss zur 
Compilezeit feststehen.

: Bearbeitet durch User
von Wilhelm M. (wimalopaan)


Lesenswert?

Rolf M. schrieb:
> Allerdings hat man dann für jede Array-Größe, die im Programm vorkommt,
> eine eigene Instanz dieses Templates

Und das ist selbst in µC Umgebungen kein Problem, der befürchtete 
"bloat" ist wesentlich geringer, als man gemeinhin annimmt.

Rolf M. schrieb:
> Und die Größe muss zur Compilezeit
> feststehen.

Das stimmt: VLA sind C, aber:
1
const size_t n{10};
2
int a[n]{};

ist auch in C++ ok, wobei GCC "echte" VLAs als extension möglich macht.

von Rolf M. (rmagnus)


Lesenswert?

Wilhelm M. schrieb:
> Rolf M. schrieb:
>> Und die Größe muss zur Compilezeit
>> feststehen.
>
> Das stimmt: VLA sind C, aber:

Seit C11 aber nur noch optional.

> const size_t n{10};
> int a[n]{};
>
> ist auch in C++ ok,

Aber das ist trotzdem eine zur Compilezeit feststehende Größe. Einer 
Funktion, die einen Zeiger übergeben bekommt, ist es dagegen vollkommen 
egal, was das für ein Array ist. Man muss ihr natürlich die Größe 
mitteilen.

von Wilhelm M. (wimalopaan)


Lesenswert?

Rolf M. schrieb:
> Aber das ist trotzdem eine zur Compilezeit feststehende Größe.

Das habe ich ja auch oben unterschieden.

Rolf M. schrieb:
> Man muss ihr natürlich die Größe
> mitteilen.

Und das macht man am besten in einem 'struct'. Ja, und dann ist der Weg 
zu std::array<> oder etwas ähnlichem (falls man stdlib nicht benutzen 
will/kann) ja nicht mehr weit.

von 900ss (Gast)


Lesenswert?

Wilhelm M. schrieb:
> Auch ein Grund, warum C oder "das C in C++" nicht verwenden sollte.

Es geht hier auch um C. Es ist echt anstrengend, deine C++ lobhudelei 
andauernd und an jeder unpassenden Ecke. Bekommst Geld dafür?

von Wilhelm M. (wimalopaan)


Lesenswert?

900ss schrieb:
> Wilhelm M. schrieb:
>> Auch ein Grund, warum C oder "das C in C++" nicht verwenden sollte.
>
> Es geht hier auch um C.

Sehr passend: ... auch ...

> Es ist echt anstrengend, deine C++ lobhudelei
> andauernd und an jeder unpassenden Ecke. Bekommst Geld dafür?

Das ist keine Lobhudelei, sondern einfach der Hinweis darauf, das es 
besser geht (in diesem Fall).
Da ja oben sogar über andere Programmiersprachen und auch über 
hypothetische Erweiterungen von C diskutiert wird, sollte es doch 
möglich sein, auch den Hinweis auf cherry-picking aus C++ möglich sein, 
oder?

von Sheeva P. (sheevaplug)


Lesenswert?

Yalu X. schrieb:
> Caterham und Donkervoort sind Sohn und Stiefsohn des legendären Lotus
> Seven, und schon der war bekannt dafür, trotz des im Vergleich zur
> Konkurrenz geringeren Hubraums abzugehen wie Schmidts Katze. Wie hat er
> das gemacht? Durch Light-Weight. Auch das passt ganz gut zu C :)

Sehr richtig, Colin Chapman -- der Gründer von Lotus -- hat sehr 
konsequent auf Leichtbau gesetzt und wird mit Aussagen wie "Any car 
which holds a whole race is too heavy" und "Adding Power makes you 
faster on the straights. Subtracting weight makes you faster everywhere" 
zitiert. Leider hat das dazu geführt, daß die Formel1 einige sehr 
heftige Unfälle erleben mußte, die bekanntesten davon vermutlich die 
Crashes von Martin Donelly 1990, Jochen Rindt 1969 in Barcelona, sowie 
im darauf folgenden Jahr der tödliche Unfall von Jochen Rindt -- 
allesamt, weil wichtige Teile an ihren Fahrzeugen gebrochen waren.

von db8fs (Gast)


Lesenswert?

Lothar schrieb:
> Viele glauben das geht nur in C++ aber es geht auch in C - und ist in
> der Embedded Programmierung sogar teilweise vorgeschrieben - kein
> malloc()
>
> Hier ein Beispiel: C struct wie C++ Klasse

Schönes Beispiel von dir, super! Ich geb dir recht, grundsätzlich kann 
man mit Stack-Kopien schön hantieren und kann möglicherweise auch eine 
Aufblähung in zu große Structs vermeiden (was die Sache u.U. testbarer 
machen kann). In Verbindung mit Designated Initializers (C99) wirds fast 
lesbar:

struct DATA test = { .x = 1 };

Dennoch kosten Funktionsrahmen beim Aufruf potentiell mehr und die 
Rücksprunge ebenso durch entweder Daten-Kopiererei oder -Verschiebung.

Einen richtigen Vorteil sehe ich eigentlich nicht gegenüber einem 
"struct DATA restrict *const"

^^

von mh (Gast)


Lesenswert?

db8fs schrieb:
> Dennoch kosten Funktionsrahmen beim Aufruf potentiell mehr und die
> Rücksprunge ebenso durch entweder Daten-Kopiererei oder -Verschiebung.

Hat jemand Erfahrung mit RVO in C? Ist das von Standard ausgeschlossen? 
Ich habe eben etwas getestet und konnte gcc nicht dazu bringen eine 
Kopie mit RVO zu vermeiden.

von mh (Gast)


Lesenswert?

mh schrieb:
> db8fs schrieb:
>> Dennoch kosten Funktionsrahmen beim Aufruf potentiell mehr und die
>> Rücksprunge ebenso durch entweder Daten-Kopiererei oder -Verschiebung.
>
> Hat jemand Erfahrung mit RVO in C? Ist das von Standard ausgeschlossen?
> Ich habe eben etwas getestet und konnte gcc nicht dazu bringen eine
> Kopie mit RVO zu vermeiden.

Ok, clang hat keine Probleme RVO zu nutzen.

von Rolf M. (rmagnus)


Lesenswert?

mh schrieb:
> db8fs schrieb:
>> Dennoch kosten Funktionsrahmen beim Aufruf potentiell mehr und die
>> Rücksprunge ebenso durch entweder Daten-Kopiererei oder -Verschiebung.
>
> Hat jemand Erfahrung mit RVO in C? Ist das von Standard ausgeschlossen?

Warum sollte es? In C++ muss es ja nur deshalb explizit erlaubt sein, 
weil das Kopieren eines Objekts "side effects" haben kann - über 
Konstruktor und Destruktor, und wenn die Kopie nicht gemacht wird, 
finden die nicht statt. Das gibt es bei C aber nicht, und daher ist es 
von der "as if"-Rule abgedeckt.

> Ich habe eben etwas getestet und konnte gcc nicht dazu bringen eine
> Kopie mit RVO zu vermeiden.

Also ich hab's grad probiert, und es funktioniert bei mir mit gcc, wenn 
man mindestens mit -O1 optimiert.

von mh (Gast)


Lesenswert?

Rolf M. schrieb:
> mh schrieb:
>> db8fs schrieb:
>>> Dennoch kosten Funktionsrahmen beim Aufruf potentiell mehr und die
>>> Rücksprunge ebenso durch entweder Daten-Kopiererei oder -Verschiebung.
>>
>> Hat jemand Erfahrung mit RVO in C? Ist das von Standard ausgeschlossen?
>
> Warum sollte es? In C++ muss es ja nur deshalb explizit erlaubt sein,
> weil das Kopieren eines Objekts "side effects" haben kann - über
> Konstruktor und Destruktor, und wenn die Kopie nicht gemacht wird,
> finden die nicht statt. Das gibt es bei C aber nicht, und daher ist es
> von der "as if"-Rule abgedeckt.
Das ist mir klar. Deswegen hab ich gefragt, ob es ausgeschlossen wird.

Rolf M. schrieb:
>> Ich habe eben etwas getestet und konnte gcc nicht dazu bringen eine
>> Kopie mit RVO zu vermeiden.
>
> Also ich hab's grad probiert, und es funktioniert bei mir mit gcc, wenn
> man mindestens mit -O1 optimiert.
Ok RVO mit nem rvalue macht gcc bei mir auch. Hast du zufällig mal NRVO 
also mit nem RVO mit nem lvalue getestet?
1
struct Data {
2
    int b[64];
3
};
4
struct Data make_Data(int a) {
5
    struct Data tmp;
6
    for(int i=0; i<64; ++i) {
7
        tmp.b[i] = a + i;
8
    }
9
    return tmp;
10
}

von Rolf M. (rmagnus)


Lesenswert?

mh schrieb:
> Ok RVO mit nem rvalue macht gcc bei mir auch. Hast du zufällig mal NRVO
> also mit nem RVO mit nem lvalue getestet?

Ja. Aber ich glaub, ich bin einer Optimierung aufgesessen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Arduino Fanboy D. schrieb:
> Eigentlich ist es sogar noch schlimmer:
1
   char *t1 = "Beispiel";
2
   char *t2 = "Beispiel";
3
   t2[0] = '*';

Das erzeugt unter Betriebssystemen wie Linux in der Regel einen 
Programmabbruch aka Core Dump. Dass Du es unterlässt, t2 als 
non-const-Pointer anzugeben, hindert den Compiler noch lange nicht 
daran, den konstanten String "Beispiel" in das Text-Segment zu legen. 
Kommt dieser String mehrfach im Code vor, optimiert der Compiler das und 
erzeugt nur einen String im Text-Segment. Das darf er, da Zeichenketten 
nicht beschreibbar sind. Und damit zeigen t1 und t2 auf denselben 
String.

Die Zeile
1
   t2[0] = '*';
versucht dann, ins Text-Segment zu schreiben. Das gibt unter Linux (und 
auch anderen Betriebssystemen) einen harten Programm-Abbruch.

Schreib einfach:
1
   char t1[] = "Beispiel";
2
   char t2[] = "Beispiel";
und Dein "Problem" löst sich in Luft auf.

: Bearbeitet durch Moderator
von Einer K. (Gast)


Lesenswert?

Frank M. schrieb:
> und Dein "Problem" löst sich in Luft auf.

Das ist nicht mein Problem, und zudem erwähne ich wohl schon, dass es 
eine Ausnahmen werfen kann, oder sonst ein Drama generieren.
Da eben die Ablage des Strings "Implementatition Defined" ist und der 
schreibende Zugriff dann ein "Undefined Behavior" nach sich zieht.

Eigentlich diente es eher der Vorführung, dass Pointer und Arrays eben 
NICHT das gleiche sind.
Es gibt Äquivalenzen, aber mehr auch nicht.
Da schienen mir einige der Vorposter falsch abgebogen zu sein.

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.