Forum: PC-Programmierung C Programmierung ohne Pointer?


von Zwitter (Gast)


Lesenswert?

Kann man in C ohne Pointer überhaupt programmieren?
Wenn es um Zuverlässigkeit und Sicherheit geht stehen Pascal und ADA 
ganz oben.
Heutzutage wird aber viel in C geschrieben, nur "geht" C überhaupt ohne 
Pointer?
Ist C nicht sehr Pointerlastig?
Wird in der Kernelentwicklung auf Pointer gesetzt?

: Verschoben durch Admin
von Zwitter (Gast)


Lesenswert?

weiß jemand, ZUBERLÄSSIG! welche Porgammiersprache in Autos für 
sicherheitskritische Komponenten verwendet wird?

von Benedikt S. (Gast)


Lesenswert?

Zwitter schrieb:
> Wird in der Kernelentwicklung auf Pointer gesetzt?

Natürlich.
Guckste du hier
Z. B. In der Funktion tty_ready
https://elixir.bootlin.com/linux/latest/source/drivers/tty/tty_io.c

Wer pointer versteht kann damit guten und schnellen, sicheren Code 
schreiben.

von Frank (Gast)


Lesenswert?

Zwitter schrieb:
> Kann man in C ohne Pointer überhaupt programmieren?

Ein Leben ohne Pointer ist möglich, aber sinnlos.

von Benedikt S. (Gast)


Lesenswert?

Geben Frage wie willst du jemals Dma ohne pointer verwenden weil der Dma 
Controller doch eine Speicheradresse verlangt.

von Einer dümmer als der andere (Gast)


Lesenswert?

Geht lieber Ostereier sammeln...

von Zwitter (Gast)


Lesenswert?

Um nun weitere Informationen zu geben.
Ich weiß aus sicherer Quelle das eben beim LFZ, solche Steuergeräte eben 
NICHT mit Pointer programmiert werden.
Diese sind strikt verboten von den die die Vorgaben machen.
Leider konnte mir diese Person (die eben diese Vorgaben macht) nicht 
sagen, wie die Programmiersprache heißt, mit der KFZ ABS etc. 
Steuergeräte programmiert werden.
Und das würde mich eben interessieren.
C ist es dann offenbar nicht, wenn mit C nicht vernünftig ohne Pointer 
programmiert werden kann.
Obwohl sie vermutete das es ein C Unterbau ist aber diese vom Hersteller 
modifiziert sein könnte
Und nein,  nur weil ein guter Programmierer ´mit Pointern umzugehen 
weiß, sind diese dennoch unsicher!!
Wer verbreitet immer diesen Quatsch.
Auch die besten machen Fehler! wer das nicht sieht, leidet unter 
gnadenloser Selbstüberschätzung

von Michael B. (laberkopp)


Lesenswert?

Zwitter schrieb:
> Kann man in C ohne Pointer überhaupt programmieren?

Jein, nur wenn man keinen heap-Speicher verwendet und
Übergabe in Funktionen als Array-Referenz a[] akzeptiert.

In embedded Applikationen ist es aber oftmals sinnvoll,
auf heap zu verzichten.

Wer statt C auf C++ umschwenkt, kann pointer in Klassen
verstecken und nur mit Referenzen arbeiten, dann entfällt
die Pointerarithmetik und die Freigabeproblematik.

Damit C Programme sicherer werden, gibt es Programmierstile
(z.B. wie WIN32 API: Buffer nur mit Längenangabe übergeben)
und Checkprogramme (lint, Fortify).

So lässt sich nicht nur funktionierende Software schrieben,
sondern auch viele Fehler von vorrneherein vermeiden.

Unsere Erfahrungen mit C und C++ sagen aber, daß viele C++
Compiler aus korrektem C++ Quellcode leider falschen
Maschinencode generieren (z.B. IBM Mainframe, uC)
während bei C zumindest der Compiler meist funktioniert
(die Zeiten, wo der fehlerhaft war, wie beispielsweise
Borland C, sind inzwischen wohl weitgehend überwunden).

Warum ein C Programm nicht läuft, sieht man also am Quelltext,
bei C++ muss man teilweise auf den Maschinencode starren
und sehr lange nach der Ursache forschen.

von Zwitter (Gast)


Lesenswert?

KFZ nicht LFZ, also im Auto

von temp (Gast)


Lesenswert?

Michael B. schrieb:
> Warum ein C Programm nicht läuft, sieht man also am Quelltext,
> bei C++ muss man teilweise auf den Maschinencode starren
> und sehr lange nach der Ursache forschen.

Hast du die letzten 20 Jahre im Dornröschenschlaf verbracht? 10 davon 
setzte ich wenigstens schon C++ auf kleinen Controllern ein und falschen 
Maschinencode musste ich noch nie debuggen.

von Mark B. (markbrandis)


Lesenswert?

Zwitter schrieb:
> Kann man in C ohne Pointer überhaupt programmieren?

Ja, kann man.

> Wenn es um Zuverlässigkeit und Sicherheit geht stehen Pascal und ADA
> ganz oben.

Pascal hat viele andere Sprachen inspiriert, von daher hat es schon 
seinen Verdienst. In der Industrie eingesetzt

Ada hat seinen Platz in der Luft- und Raumfahrtbranche, wird aber 
außerhalb dieser nur wenig genutzt.

> Heutzutage wird aber viel in C geschrieben, nur "geht" C überhaupt ohne
> Pointer?

Ja.

> Ist C nicht sehr Pointerlastig?

Das kommt darauf an.

> Wird in der Kernelentwicklung auf Pointer gesetzt?

Ja sicher, zum Beispiel im Linux-Kernel. Freilich ist es nur eine 
Minderheit aller Programmierer, die überhaupt auf so einer niedrigen 
Abstraktionsebene arbeiten. Die meisten nutzen doch eher Betriebssysteme 
und Treiber, die von anderen bereitgestellt werden, anstatt diese selbst 
zu entwickeln.

von F. M. (foxmulder)


Lesenswert?

Zwitter schrieb:
> weiß jemand, ZUBERLÄSSIG! welche Porgammiersprache in Autos für
> sicherheitskritische Komponenten verwendet wird?

Misra C zB.

von Mark B. (markbrandis)


Lesenswert?

Zwitter schrieb:
> weiß jemand, ZUBERLÄSSIG! welche Porgammiersprache in Autos für
> sicherheitskritische Komponenten verwendet wird?

In der Automobilbranche wird sehr oft C und C++ eingesetzt, und zwar 
nach dem MISRA-Standard:

https://de.wikipedia.org/wiki/MISRA-C

von Mark B. (markbrandis)


Lesenswert?

Mark B. schrieb:
> Pascal hat viele andere Sprachen inspiriert, von daher hat es schon
> seinen Verdienst. In der Industrie eingesetzt

Das sollte heißen: "In der Industrie eingesetzt wird es aber nur wenig."

von g457 (Gast)


Lesenswert?

> Kann man in C ohne Pointer überhaupt programmieren?

Ja.

> Wenn es um Zuverlässigkeit und Sicherheit geht stehen Pascal und
> ADA ganz oben.

Nicht wirklich.

> Heutzutage wird aber viel in C geschrieben, nur "geht" C überhaupt
> ohne Pointer?

Selbstverständlich.

> Ist C nicht sehr Pointerlastig?

Das Eine hat mit dem Anderen genau garnix zu tun.

> Wird in der Kernelentwicklung auf Pointer gesetzt?

Selbstverständlich.

Du stellst die falschen Fragen. Die korrekten Antworten auf die 
richtigen Fragen lauten in etwa "Ja, selbstverständlich kann man in C 
sicherheitskritische Applikationen schreiben. Wird tagtäglich 
millionenfach erfolgreich getan. Wie in allen(!! - sinnvollen -) 
Sprachen gibt es auch in C Feature, die man beherrschen muss um sie dann 
adäquat und sicher zu nutzen."

HTH

von Zwitter (Gast)


Lesenswert?

ah ok, stimmt von MISRA hatte ich auch schon mal gehört.
Ich werde wohl langsam alt:-)

von Udo (Gast)


Lesenswert?

Zwitter schrieb:
> weiß jemand, ZUBERLÄSSIG! welche Porgammiersprache in Autos für
> sicherheitskritische Komponenten verwendet wird?

Ja: Es wird zwischen Handcode und Autocode unterschieden. Autocode 
zumeist mit Simulink, ist dann aber nach dem Code-Generieren auch C. 
Einiges wird auch händisch in C programmiert.
Sicherheitskritisch = ISO26262, ASIL B, C, D
Mit entsprechenden Coding-Guidelines kein Problem. Programmierung mit 
Pointern ist zumeist explizit untersagt, ebenso das Benutzen der 
Standardbibliotheken. Dynamische Speicherverwaltung (malloc, new) ist im 
ASIL-Kontext zwar nicht verboten, aber man hat das Nachweisproblem, dass 
es sicher funktioniert. Der einfachere Weg ist darauf zu verzichten.

von Zwitter (Gast)


Lesenswert?

"Ist C nicht sehr Pointerlastig?

Das Eine hat mit dem Anderen genau garnix zu tun."

Das liest sich in vielen Lehrbüchern aber ganz anders...da wird auch die 
Enge Bindung von Pointern und dem häufigen Einsatz gesprochen...daher 
meine Frage..

von P. S. (namnyef)


Lesenswert?

Natürlich wird auch sicherheitsrelevante Software in C und unter 
Verwendung von Pointern geschrieben. Allerdings kann es bei 
Pointer-Arithmetik gewisse Einschränkungen geben, da hier leicht Unsinn 
passieren kann.

von Zwitter (Gast)


Lesenswert?

Wie sehe denn bei diesem Beispiel die GUTE Version aus?
Was könnte man denn deutlicheres als if (I == a)
Schreiben? Also um dem häufigen Fehler mit  = und == zu begegnene?

Die folgende Variante ist schlecht, weil man nicht nachvollziehen kann, 
ob der Programmierer einen Fehler gemacht hat, oder absichtlich dieses 
Konstrukt gewählt hat:
1
if ( i = a )
2
{
3
   /* Anweisung */
4
}
Der Compiler würde diese Variante erkennen und übersetzen zu:
1
/* Zuweisung                       */
2
i = a;
3
/* dann ein Vergleich              */
4
if ( i != 0 )
5
{
6
   /* Anweisung */
7
}
Möglicherweise meinte der Programmierer == und hat versehentlich = 
geschrieben, so dass die Anweisung nur bei Gleichheit von i und a 
ausgeführt werden soll:
1
if ( i == a )
2
{
3
   /* Anweisung */
4
}

von Zwitter (Gast)


Lesenswert?

wäre es dann für einen Anfänger nicht viel Sinnvoller gleich Misra C 
konform zu lernen?

von Zwitter (Gast)


Lesenswert?


von DoS (Gast)


Lesenswert?

Einer dümmer als der andere schrieb:
> Geht lieber Ostereier sammeln...

Am Todestag des Herrn? Ein echter Katholik hat heute gar keinen Spaß, 
geht auch nicht ins Internet sondern in sich (geistig) und trauert. 
Ostereier  ist erst Montag. Arbeitgeberfreundlicher wäre ein Ableben am 
Samstag und eine Auferstehung am nächsten Tag gewesen, aber so weit 
haben die Verfasser des neuen Testaments nicht gedacht.
Und um noch eins drauf zu Setzen: Ich liebe Pointer. Warum was durch die 
Gegend kopieren, wenn ich nur die Adesse übergeben muss?

von Zwitter (Gast)


Lesenswert?

ODer ist damit gemeint das es wie in Pascal gemacht werden muss
Also eine Zuweisung nur so erlaubt ist und eben nicht innerhalb einer IF 
Schleife erlaubt ist?
1
/* Zuweisung                       */
2
i = a;
3
/* dann ein Vergleich              */
4
if ( i != 0 )
5
{
6
   /* Anweisung */
7
}

"Ich liebe Pointer. Warum was durch die
Gegend kopieren"
Weil wie oben erwähnt, es im KFZ ABS Steuergeräten etc, schlicht nicht 
erlaubt ist, da kannst du sie noch so sehr lieben, du würdest dort nicht 
arbeiten..

Beitrag #6641958 wurde von einem Moderator gelöscht.
von Blechbieger (Gast)


Lesenswert?

Zwitter schrieb:
> Also um dem häufigen Fehler mit  = und == zu begegnene?

= an dieser Stelle in den eigenen Coding-Regeln verbieten. Das alleine 
hilft nicht aber wenn man die entsprechenden bzw. alle Compiler-Warnings 
anschaltet und vor allem dann auch alle Warnings abarbeitet. Ziel muss 
es sein warningsfreien Code zu haben.

Pointer sind in sicherheitskritischer Software nicht grundsätzlich 
verboten aber die meisten Standards verbieten explizite 
Pointerarithmetrik. Wie oben schon gesagt ist implizite 
Pointerarithmetrik, d.h. Arrays erlaubt.

von Zwitter (Gast)


Lesenswert?

"Lachen, umdrehen, weggehen. So muss man mit diesen Subjekten 
verfahren."
Und warum kommentierst du es dann?
 Irgendwie bekommst du nicht mal deine eigenen Regeln eingehalten du 
Clown.
Hoffen wir mal das du nicht als Programmierer arbeitest

von Mladen G. (mgira)


Lesenswert?

Pascal ist keine Sprache die in der Industrie eingesetzt wurde, 
moeglicherweise Turbo Pascal oder Delphi, und das auch nur selten IMO.

Zwitter schrieb:
> Die folgende Variante ist schlecht, weil man nicht nachvollziehen kann,
> ob der Programmierer einen Fehler gemacht hat, oder absichtlich dieses
> Konstrukt gewählt hat

Wenn jemand sowas absichtlich gewaehlt hat, darf man ruhig ruhig eine 
Rede halten ueber den Programmmierdstil.

Da C auch eine Zuweisung als Anweisung versteht, kann der Compiler nicht 
wirklich wissen ob "das so gemeint war", als Mensch darf man schon 
wissen dass "man das so nicht macht".
Dafuer gibt es ja vorgaben, code rewiews, statische code analyse etc. 
pp.

von Zwitter (Gast)


Lesenswert?

Der genannte Text
"Die folgende Variante ist schlecht, weil man nicht nachvollziehen kann,
> ob der Programmierer einen Fehler gemacht hat, oder absichtlich dieses
> Konstrukt gewählt hat"
stammt nicht von mit und ich wollte auch nicht über den Text 
philosophieren, es geht darum wie es gemeint ist wie man es dann richtig 
macht.
NAch MiSRA Standard ist es NICHT erlaubt, also gibt es da nichts zu 
diskutieren oder Reviewen.

Wie gesagt, daher meine Frage, wie es denn nach MISRA Standard RICHTIG 
wäre

von (prx) A. K. (prx)


Lesenswert?

Bei Strings lassen sich Pointer in C nur schwer vermeiden.

: Bearbeitet durch User
von wendelsberg (Gast)


Lesenswert?

Zwitter schrieb:
> Leider konnte mir diese Person (die eben diese Vorgaben macht) nicht
> sagen, wie die Programmiersprache heißt, mit der KFZ ABS etc.
> Steuergeräte programmiert werden.

Ganz grosses Kino.
Die Person macht Vorgaben, weiss aber nicht wofuer.

wendelsberg

von malsehen (Gast)


Lesenswert?

DoS schrieb:
> Warum was durch die
> Gegend kopieren, wenn ich nur die Adesse übergeben muss?

Frage ich mich auch schon die ganze Zeit.

von Michael B. (laberkopp)


Lesenswert?

temp schrieb:
> falschen Maschinencode musste ich noch nie debuggen

Ja nun, wenn man nur Kinderprogramme schreibt, wird das vielleicht auch 
so bleiben.

Ich bin auch kein Freund davon, die modernsten Sprachkonstrukte z.B. aus 
C++11, C++14, C++17, C++20 zu verwenden, aber nicht jeder hat die 
Erfahrung warum das Verzichten besser ist.

von Karatona (Gast)


Lesenswert?

Michael B. schrieb:
> temp schrieb:
>> falschen Maschinencode musste ich noch nie debuggen
>
> Ja nun, wenn man nur Kinderprogramme schreibt, wird das vielleicht auch
> so bleiben.
>
> Ich bin auch kein Freund davon, die modernsten Sprachkonstrukte z.B. aus
> C++11, C++14, C++17, C++20 zu verwenden, aber nicht jeder hat die
> Erfahrung warum das Verzichten besser ist.

Braucht auch kein Schwein. Jedes Jahr kommt neuer syntactical sugar 
dazu, die in extrem seltenen Fällen irgendwelche Vorteile bieten. Blickt 
doch eh keiner mehr durch. Demnächst klatscht man da vermutlich noch ne 
garbage collection rein. dann ist die kloake voll xD

von Zwitter (Gast)


Lesenswert?

"Ganz grosses Kino.
Die Person macht Vorgaben, weiss aber nicht wofür."
Keine Ahnugn, Sie ist ING. und das ist ihre Aufgabe, aber sie 
programmiert halt nicht sondern macht Vorgaben bzw überprüft ob diese 
umgesetzt wurden, sie sitzt aber ÜBER den Programmierern, daher wird die 
eigentlich Überprüfung wohl ein untergebener durchführen und das Häkchen 
setzen.
Ich hab auch nicht gefragt, weil welcher Firma sie arbeitet, aber sie 
ist dennoch bei TEstfahren gelegentlich dabei.
Ob das nun speziell zum Aufgabenbereich gehört oder mehr dem Ausgleich 
und Erfahrungsammlung dient kann ich dir nicht sagen

von Cyblord -. (cyblord)


Lesenswert?

Kann noch nicht mal in einem Forum zitieren, will aber bei den Großen 
über Code mitreden. Mit Dingen vom Hörensagen. Wie lächerlich wird es 
noch?

von A. S. (Gast)


Lesenswert?

DoS schrieb:
> Ein echter Katholik hat heute gar keinen Spaß, geht auch nicht ins
> Internet sondern in sich (geistig) und trauert.

Du meinst Protestant. Katholiken gehen morgens den Kreuzweg und 
nachmittags zur Karfreitagsliturgie.

Dazwischen wird gearbeitet, ausmisten, schrubben und so, alles was 
keinen Krach macht (da gesetzlicher stiller Feiertag)

von 900ss (900ss)


Lesenswert?

Zwitter schrieb:
> IF Schleife

Autsch

von db8fs (Gast)


Lesenswert?

Macht halt keinen Sinn das ganze. Man würde jegliche dynamische 
Allokierung wegschmeißen (egal wo der mempool liegt, ob nu auf stack 
oder heap). Zusätzlich jegliche Call-by-Reference wegschmeißen. Function 
Pointer haste dann auch keine mehr, also keine Callbacks, ja, noch nicht 
mal ein "Hello world" ließe sich programmieren, weil String-Literale 
konstante Pointer sind - das wäre eine sehr seltsame 
Programmiersprache...

von Einer K. (Gast)


Lesenswert?

Michael B. schrieb:
> Ich bin auch kein Freund davon, die modernsten Sprachkonstrukte z.B. aus
> C++11, C++14, C++17, C++20 zu verwenden, aber nicht jeder hat die
> Erfahrung warum das Verzichten besser ist.

Hier bin ich nicht mit dir einverstanden!
"Modern" sollte meiner Ansicht nach, kein Argument sein, um eine 
Spracheigenschaft abzulehnen.
Es sei denn, man muss aufgrund irgendwelcher Vorgaben zu der pre C++11 
Zeit kompatibel bleiben.

Natürlich sind auch die "modernen" Spracheigenschaften, und 
mitgelieferten Tools/Libs nicht per se der heilige Gral und mit der 
gewohnten Vorsicht einzusetzen. Das gilt allerdings genauso für uralte 
Features, wie z.B. Goto, Pointer usw.


Einfaches Beispiel:
Die Iteration über ein Array wird durch den "range based for loop" um 
Größenordnungen einfacher und sicherer.
Es gibt keine Chance, sich da mit Pointern oder Array Indices zu 
verheddern.

Unter solchen Umständen kann "modern" doch kein schlaues Argument sein.

von Peter Panda2 (Gast)


Lesenswert?

Da es MISRA aber nun mal gibt, ist halt die Frage wie solche Sachen dann 
umgesetzt werden.
Daher steht es hier zur Diskussion

von Günni (Gast)


Lesenswert?

Mladen G. schrieb:
> Pascal ist keine Sprache die in der Industrie eingesetzt wurde

Doch. Man muss nur weit genug zurückgehen. 1960 gab es zwei Richtungen, 
die damals etwa gleich stark vertreten waren:
Von HP gab es Rechner, die in Basic programmiert wurden, IBM / Siemens 
wurde meist in der ähnlichen Sprache Fortran IV programmiert, wie auch 
oftmals die PDP- (und später) VAX- Rechner von Digital Equipment.
Philips Electrologica und Telefunken setzten mehr auf Algol, aus dem 
Pascal weiterentwickelt wurde. Turbo Pascal und Delphi kamen erst 
später, als die Firmen, die auf Pascal setzten, langsam an Marktanteil 
verloren.
Ich habe im industriellen Umfeld mit allen diesen Rechnern gearbeitet. 
Algol / Pascal hat mehr Spaß gemacht, weil es eleganter war. Aber wegen 
der großen Verbreitung von IBM /360 und /370 bzw. Siemens 4004 musste 
ich hauptsächlich in Fortran programmieren.

von Cyblord -. (cyblord)


Lesenswert?

Peter Panda2 schrieb:
> Da es MISRA aber nun mal gibt, ist halt die Frage wie solche Sachen dann
> umgesetzt werden.
> Daher steht es hier zur Diskussion

1.) MISRA verbietet keine Pointer.

2.) Man darf Ausnahmen machen, diesen müssen begründet und dokumentiert 
sein.

3.) MISRA ist auf dem absteigenden Ast und heute oft nur noch ein 
Schimpfwort.

4.) Hör auf dir vom Not-Hauptschulabschluss Zwitter Dinge einreden zu 
lassen. Meine verwelkte Zimmerpflanze hat mehr Ahnung von C als der.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Günni schrieb:
> 1960 gab es zwei Richtungen,
> die damals etwa gleich stark vertreten waren:
> Von HP gab es Rechner, die in Basic programmiert wurden

1960 BASIC auf einem HP? Hmm. Beitrag für gestern, oder 1980?
BASIC gibts seit 1964 und HP Computer seit 1966.

: Bearbeitet durch User
von Peter Panda2 (Gast)


Lesenswert?

warum werden Leute die Cylord eigentlich in solchen Foren nicht 
gesperrt?
Zu seinem eigenen Schutz.
Es ist ja offensichtlich das er Probleme hat.
Ich die Bezeichnung Clown auch etwas unpassend, aber das bei ihm was 
nicht stimmt ist offensichtlich.

von Harry L. (mysth)


Lesenswert?

Peter Panda2 schrieb:
> Es ist ja offensichtlich das er Probleme hat.

Nö!
Er spricht nur aus, was viele Andere denken, wenn man so einen Thread 
liest...

von Peter Panda2 (Gast)


Lesenswert?

hat nur mit dem Thema nichts zu tun...in andern Foren wird sowas 
gelöscht

von Michael B. (laberkopp)


Lesenswert?

Arduino Fanboy D. schrieb:
> Unter solchen Umständen kann "modern" doch kein schlaues Argument sein

Fanboy halt, keinen Realtitätskontakt.

Es geht darum, daß neue Compilererweiterungen leider nur mangelhaft 
getestet sind, und damit keineswegs portabel auch auf Plattformen die 
angebnliche die jeweilige Sprachversion schon unterstützen.

Manches lernt man halt nur der Erfahrung und Schmerz, andere bleiben 
Fans.

von OhMann (Gast)


Lesenswert?

Günni schrieb:
> Siemens 4004
Die kenne ich auch noch, allerdings von der HW Seite.
Zu der Zeit hatten wir bei einem Kunden noch eine
3003 am Leben gehalten.
Das war noch richtig HW, Heavy Ware würde man heute sagen.
Sorry für diesen Exkurs, es gibt leider nur wenige, die diese Zeit 
erlebt haben. Es freut mich immer, wenn jemand aus dieser Epoche hier 
schreibt.

von Einer K. (Gast)


Lesenswert?

Michael B. schrieb:
> Fanboy halt, keinen Realtitätskontakt.

Michael B. schrieb:
> Manches lernt man halt nur der Erfahrung und Schmerz, andere bleiben
> Fans.

Was ist denn mit dir los?
Der "range based for loop" hat sich seit über 10 Jahren bewährt.

Wenn dein Compiler Ersteller es, in der Zeit, nicht geschafft hat, das 
stabil zu implementieren, dann gute Nacht.

Mir scheint, deine Argumentation wurzelt eher in paranoiden Ängsten.
Was auch die persönlichen Angriffe, wenigstens zum Teil, erklären würde.

von Cyblord -. (cyblord)


Lesenswert?

Peter Panda2 schrieb:
> hat nur mit dem Thema nichts zu tun...in andern Foren wird sowas
> gelöscht

Also ich bin bisher On-Topic, im Gegensatz zu dir.

von Thilo R. (harfner)


Lesenswert?

Hallo Zwitter, was war eigentlich genau Deine Frage? Es klingt, als 
hätte Dich die halb verstandene Aussage dieser Person aufgeregt.

Völlig ohne Pointer in C programmieren ist theoretisch möglich, aber 
nicht sehr praktisch. C kennt als Übergabemethode für Variablen nur 
call-by-value, und das heißt, dass eine Funktion ihre Parameter nicht 
verändern kann. Es können über Parameter also nur Informationen in die 
Funktion hinein fließen, aber nicht hinaus. Da in C zusätzlich die 
Rückgabewerte von Funktionen recht eingeschränkt sind, man also z.B. 
keine Tupel zurück geben kann, ist auch dieser Weg im allgemeinen nicht 
möglich. Dann könnte man noch die Ergebnisse über globale Variablen 
zurück geben, aber das wäre wirklich völlig abwegig und gerade der 
Sicherheit NICHT zuträglich.

Der in C absolut übliche Weg aus dem Problem besteht darin, der Funktion 
einen Pointer auf dem Parameter statt des Parameters selbst zu 
übergeben. Das führt zwar zu Lästigkeiten bei der Syntax, funktioniert 
aber wunderbar und ist auch in sicherheitskritischen Umgebungen absolut 
zulässig.

Was z.B. nach MISRA-C NICHT zulässig ist, ist Pointerarithmetik wie z.B 
int i = p2 - p1 oder p2 = p1 + 3. Also rechnen "per Hand" mit Pointern, 
alles was über das Weiterreichen der Adresse eines konkreten Objekts 
hinaus geht.
Dynamischer Speicher, sprich malloc, ist im Regelfall auch nicht 
zulässig. Die Laufzeit ist schwierig abzuschätzen und es könnten 
komplexe Fehlerzustände entstehen.

Das Problem mit dem if hast Du möglicherweise nicht verstanden.
1
if (a = b) { ...
 ist absolut legales C. Es setzt a auf den Wert von b und führt den 
abhängigen Code aus, falls a != 0.
Dummerweise ist das vergleichsweise selten das, was wirklich vom 
Entwickler beabsichtigt ist.
Wenn man das verbietet und stattdessen
1
a = b; if (a) { ... }
 fordert, kann das Problem nicht durch einen Tippfehler entstehen.

von A. S. (Gast)


Lesenswert?

Zwitter schrieb:
> Und das würde mich eben interessieren.
> C ist es dann offenbar nicht, wenn mit C nicht vernünftig ohne Pointer
> programmiert werden kann.
> Obwohl sie vermutete das es ein C Unterbau ist aber diese vom Hersteller
> modifiziert sein könnte
> Und nein,  nur weil ein guter Programmierer ´mit Pointern umzugehen
> weiß, sind diese dennoch unsicher!!

Sorry, Du hast keine Ahnung.

Mit 90% ist das C, wenn es erfolgreich und sicher ist.

Für das, wo man Pointer unbedingt braucht, haben andere Sprachen 
ähnliche Probleme.

Du kannst mit statischer Codeprüfung praktisch jede programmiervoschrift 
relativ umfassend prüfen.

Einem ABS hilft es nur bedingt, wenn ADA einen falschen Arrayzugriff 
erkennt.

Wenn ich ein falsches ptr++ mache, ist das schlimmer als ein > statt ein 
<?

Wenn Anfänger = statt == schreiben und nicht gewarnt werden, dann ist 
das Hybris. Das wird aber nicht dadurch besser, dass man stattdessen 
spezialsprachen entwickelt statt Warnungen einzuschalten

von Peter D. (peda)


Lesenswert?

Zwitter schrieb:
> Kann man in C ohne Pointer überhaupt programmieren?

Natürlich.
Du kannst alle Pointer auf Arrayzugriffe mit Index umschreiben. Auf den 
erzeugten Code wird das nur wenig Einfluß haben.

von Lothar (Gast)


Lesenswert?

Zwitter schrieb:
> Kann man in C ohne Pointer überhaupt programmieren?

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

struct DATA
{
  int x;
};

struct DATA Data(int x)
{
  struct DATA data;
  data.x = x;
  return data;
}

int main(void)
{
  struct DATA test = Data(1);
  printf("%i", test.x);
  return 0;
}

von Einer K. (Gast)


Lesenswert?

Thilo R. schrieb:
> if (a = b) { ...
Die mir bekannte übliche Vorgehensweise/Konvention ist....

Alle Warnungen aktivieren!
Dann zeigt der Kompiler mit seinem Finger genau auf die Stelle.

Sollte der Programmierer exakt das meinen, was er da geschrieben hat, 
dann Klammern drum.
Die kosten nix.

if (a = b) { ... // evtl unbeabsichtigt, wirft Warnung
if ((a = b)) { ... // beabsichtigt, wirft keine Warnung

von Zwitter (Gast)


Lesenswert?

ah, ok danke. Das bringt etwas mehr an Erkenntnis:-)
Danke auch an Thilo R.

Und ja,A. S
Ich habe keine Ahnung, deshalb frage ich hier so unwissend;-)

Und Cyloard, nein ich bin kein Hauptschüler, selbst wenn wäre ginge dich 
das so gar nichts an.
Ich bin Realschüler aber Legastheniker, kannst ja mal googeln was das 
ist, etwas Bildung würde dir offensichtlich auch nicht schaden

von Cyblord -. (cyblord)


Lesenswert?

Zwitter schrieb:

> Ich bin Realschüler aber Legastheniker, kannst ja mal googeln was das
> ist, etwas Bildung würde dir offensichtlich auch nicht schaden

Es ist interessant dass du ständig insistierst, anderen hätten zu wenig 
Bildung. Damit kannst du dein de-facto Unwissen auch nicht ausgleichen.

von A. S. (Gast)


Lesenswert?

Zwitter schrieb:
> Und ja,A. S
> Ich habe keine Ahnung, deshalb frage ich hier so unwissend;-)

Dafür haust Du aber einige Behauptungen raus, die einfach falsch sind:

Zwitter schrieb:
> NAch MiSRA Standard ist es NICHT erlaubt, also gibt es da nichts zu
> diskutieren oder Reviewen.

Zwitter schrieb:
> Und nein,  nur weil ein guter Programmierer ´mit Pointern umzugehen
> weiß, sind diese dennoch unsicher!!

von Cyblord -. (cyblord)


Lesenswert?

A. S. schrieb:
> Dafür haust Du aber einige Behauptungen raus, die einfach falsch sind:

Er ist halt ein Schulbub. Und mit dem diskutiert ihr hier ob C gut oder 
schlecht ist? Hättet ihr mal auf mich gehört, hättet ihr euch nicht so 
zum Affen machen müssen.

: Bearbeitet durch User
von Philipp Klaus K. (pkk)


Lesenswert?

Zwitter schrieb:
> wäre es dann für einen Anfänger nicht viel Sinnvoller gleich Misra C
> konform zu lernen?

Eher nicht:

* Erstmal muss man die Grundlagen lernen. Direkt mit MISRA-C einzusteien 
wäre wohl vergleichbar mit jemand der eine natürliche Sprache nur 
mittelsGedichten lernt.
* Ohne C zu verstehen, kann man MISRA-C auch nicht verstehen. MISRA-C 
besteht aus Regeln der Art "mach das in C nicht" (wenige) und vielen der 
Art "wenn du das in C machst, musst du dokumentieren, warum" (viele).
* MISRA-C hinkt meist dem aktuellen C Standard etwas hinterher, sodass 
MISRA-C für neue C-Standards erst einige Jahre später verfügbar wird.
* Für Standard C gibt es reichlich gute Lehrbücher. Für einen Einstieg 
direkt (also ohne C-Vorkenntnisse) mit MISRA-C gibt es meines Wissens 
nach keine.

von vn nn (Gast)


Lesenswert?

Zwitter schrieb:
> NAch MiSRA Standard ist es NICHT erlaubt, also gibt es da nichts zu
> diskutieren oder Reviewen.

Blödfug, Pointerarithmetik ist nicht erlaubt, Pointer natürlich schon. 
Wär ja schön blöd, alles immer durch die Gegend zu kopieren, und 
Objektorientierung gar nicht möglich.

Zwitter schrieb:
> Und Cyloard, nein ich bin kein Hauptschüler, selbst wenn wäre ginge dich
> das so gar nichts an.
> Ich bin Realschüler aber Legastheniker, kannst ja mal googeln was das
> ist, etwas Bildung würde dir offensichtlich auch nicht schaden

Ein bisschen Manieren würden dir nicht schaden, und weniger oft 
uninformiert durch die Gegend tönen.

Zwitter schrieb:
> IF
> Schleife

Und du willst anderen erklären was in MISRA steht. Alles klar.

von Pandur S. (jetztnicht)


Lesenswert?

Ich programmiere auch auf controllern, allerdings Pascal. Und lasse 
Pointer weg. Falls ein Algorithmus mal Pointer wollte, wird er 
umgeschrieben auf ohne Pointer. Also zB einen sortierterten Binaerbaum 
habe ich ohne Pointer. Die Anzahl Elemente ist auch beschraenkt.

von Spassbremse (Gast)


Lesenswert?

Darum Assembler, das ist aber nur was für echte Hartholzprogrammierer.

von Karatona (Gast)


Lesenswert?

Spassbremse schrieb:
> Darum Assembler, das ist aber nur was für echte
> Hartholzprogrammierer.

eher was für hinterwäldler

von Johannes (Gast)


Lesenswert?

Sicherheit bzw. Zuverlässigkeit erreicht man nicht durch einen einzelnen 
Baustein. Von daher sind die Erwartungen die einige hier an z.B. MISRA 
stellen völlig überzogen.

Erst mit einer Kette von Bausteinen bekommt man ein sicheres 
Gesamtsystem, wobei natürlich die Zahl der 9en (99%, 99.9%, ...) 
diktiert wie viele und welche von diesen Bausteinen man einsetzen muss.

Als da wären z.B. Coding Guidelines, Code Reviews, Design Reviews, Code 
Tests, Hardware Tests, Redundanz, parallele Implementierung von 
verschiedenen Firmen, Ausfallanalysen, ...


Und egal wie man programmiert - am Ende hat man immer Zeiger. Vielleicht 
versteckt sie die Programmiersprache vor einem, vielleicht bedient man 
sich eines Kniffs wie z.B. [] in C, aber der Zeiger ist da, 99% aller 
System funktionieren nur mit Zeigern in irgendeiner Form.

Wer meint komplexe Systeme ohne Zeiger programmieren zu können macht 
Murks.

von Pandur S. (jetztnicht)


Lesenswert?

Nun, ja. Wenn man mit arrays arbeitet ist der Index etwas wie ein 
pointer, aber er stimmt schon in der Granularitaet. Dann muss nur der 
Index noch im erlaubten Bereich der Elemente sein.
Ein Index++ ist eben nicht dasselbe wie ein Pointer++

Was dahinter ist, kann dir ja eigenlich egal sein.

von Johannes (Gast)


Lesenswert?

Viel entscheidender ist, dass Arrayzugriffe in C keine "Arrayzugriffe" 
sind, sondern simple Pointerarithmetik. Es gibt keine Prüfung auf 
Indexverletzungen und damit hast du einfach ein Einfallstor für Fehler.

Aber schon mit C++ ließe sich das sauber umgehen, zumindest dahingehend, 
dass ein ordentlicher Laufzeitfehler generiert wird. (So wie in allen 
anderen Programmiersprachen auch.) Indexüberprüfungen zur Compilezeit 
kann AFAIK keine Programmiersprache.

von Johannes (Gast)


Lesenswert?

Btw. "index++" ist schon das gleiche wie "pointer++" - sofern der 
Pointer vom gleichen Typ ist wie das Array, auf das sich der Index 
bezieht. Es ist sogar exakt das gleiche - und da liegt das Problem.

von Einer K. (Gast)


Lesenswert?

Pandur S. schrieb:
> Nun, ja. Wenn man mit arrays arbeitet ist der Index etwas wie ein
> pointer,

In c und C++ gibt es die garantierte Äquivalenz zwischen Indexiertem und 
Pointer Zugriff.

Damit ist es völlig gleichwertig, welche der drei Zugriffsvarianten man 
nutzt:
1
  int test[3] = {1,2,3};
2
  int t1 = *test+2;
3
  int t2 = test[2];
4
  int t3 = 2[test];
Wobei die 2te sich wohl intuitiv am leichtesten erfassen lässt

von Yalu X. (yalu) (Moderator)


Lesenswert?

Zwitter schrieb:
> Kann man in C ohne Pointer überhaupt programmieren?

Ja, aber nur ganz primitive Dinge. Schon in einem Hello-World-Programm
wird der Textstring als Pointer an die printf-Funktion übergeben.

> Wenn es um Zuverlässigkeit und Sicherheit geht stehen Pascal und ADA
> ganz oben.

Auch in Pascal und Ada gibt es Pointer

Pointer gibt es in praktisch jeder Programmiersprache, nur heißen sie
oft anders. An sich stellen sie auch kein Problem dar, sondern höchstens
die Art und Weise wie damit umgegangen wird. In C hat man dafür von
Hause aus viele Freiheiten, bspw. die Konvertierung von Integers in
Pointer und Pointer-Arithmetik. Diese Dinge werden in der hardwarenahen
Programmierung benötigt und können bei Unachtsamkeit gefährlich werden.

Ur-Pascal war in solchen Dingen recht restriktiv, aber seit Turbo-Pascal
bieten alle verbreiteten Pascal-Dialekte diesbezüglich praktisch
dieselben Möglichkeiten (und damit auch Gefahren) wie C.

In Ada muß für die hardwarenahe Programmierung ein Modul namens
Interfaces.C.Pointers eingebunden werden, dann hat man auch dort alle
Freiheiten wie in C. Immerhin wird durch die Auslagerung in ein externes
Modul versehentlicher Unfug mit Pointern in normalem Anwendungscode
weitgehend vermieden.

Was sicherheitskritische Anwendungen betrifft:

- Auch diese benötigen i.Allg. direkten Hardwarezugriff. Man sollte
  diesen aber Kapseln und auf ganz wenige Programmteile der Anwendung
  beschränken oder gleich einem Betriebssystem überlassen. Diese Teile
  müssen logischerweise ganz besonders sorgfältig entwickelt und geprüft
  werden. Die Trennung von hardwarenahem und Anwendungscode lässt sich
  in Ada leichter kontrollieren als in C oder Pascal.

- Ein Fehler in der Verwendung von Pointern kann fatal sein, jeder
  andere Programmierfehler aber ebenso. Insofern bringen sprachbasierte
  Restriktionen bzgl. der Verwendung von Pointern zwar gewisse Vorteile,
  sie sollten aber nicht überbewertet werden. Entsprechendes gilt für
  künstliche auf C aufgesetzte Regelwerke wie bspw. MISRA. Diese lassen
  vielleicht die Softwareverantwortlichen besser schlafen und decken
  auch den einen oder anderen groben Schnitzer bei der Programmierung
  auf, sie sollten aber keineswegs dazu verleiten zu glauben, dass die
  damit entwickelte Software wesentlich sicherer oder gar garantiert
  perfekt sicher wird.

Arduino Fanboy D. schrieb:
> int t1 = *test+2;

Da fehlen noch zwei Klammern:

1
int t1 = *(test+2);

Diese holprige Schreibweise mit 4 Sonderzeichen dürfte einer der
Hauptgründe dafür sein, das es die gezuckerte Variante

1
int t1 = test[2];

gibt.

In ähnlicher Weise werden auch bei a->b statt (*a).b zwei Sonderzeichen
eingespart.

: Bearbeitet durch Moderator
von Einer K. (Gast)


Lesenswert?

Yalu X. schrieb:
> Arduino Fanboy D. schrieb:
>> int t1 = *test+2;
>
> Da fehlen noch zwei Klammern:
>
> int t1 = *(test+2);
Da hast du allerdings Wahr!
Die Klammerung ist mir durch die Lappen gegangen.

von Löthans (Gast)


Lesenswert?

Michael B. schrieb:
> Unsere Erfahrungen mit C und C++ sagen aber, daß viele C++
> Compiler aus korrektem C++ Quellcode leider falschen
> Maschinencode generieren (z.B. IBM Mainframe, uC)
> während bei C zumindest der Compiler meist funktioniert
> (die Zeiten, wo der fehlerhaft war, wie beispielsweise
> Borland C, sind inzwischen wohl weitgehend überwunden).

Sehr interessant! So einen Blödsinn habe ich noch nie gelesen

von Einer K. (Gast)


Lesenswert?

Löthans schrieb:
> Sehr interessant! So einen Blödsinn habe ich noch nie gelesen

Oha...
Kritik mag der laberkopp gar nicht!
Dann wird er ganz fix, ganz fies.

von Klaus H. (klummel69)


Lesenswert?

Michael B. schrieb:
> Unsere Erfahrungen mit C und C++ sagen aber, daß viele C++
> Compiler aus korrektem C++ Quellcode leider falschen
> Maschinencode generieren (z.B. IBM Mainframe, uC)
Das ist mir jetzt etwas zu sehr verallgemeinert. Das deckt sich 
zumindest nicht mit meiner Erfahrung.
Hast Du konkrete Beispiele?
Compilerfehler hatte ich bisher eine Hand voll im Laufe der Jahre. Und 
die waren meist halb C halb C++.
Vielmehr waren die meisten Fehler eher Fehler der Programmierer. C++ hat 
halt komplexere Strukturen als C und man kann sich deutlich mehr ins 
Knie schießen.

Schönes aktuelles Beispiel von oben:
Arduino Fanboy D. schrieb:
> int t1 = *test+2;

Yalu X. schrieb:
> Da fehlen noch zwei Klammern:
> int t1 = *(test+2);

Un das ist genau der Grund, weshalb Pointer mit Vorsicht zu geniessen 
sind.
(Ich spreche bewusst nicht von Verbot). Man sollte einfach wissen, 
welche Stolpersteine eine Sprache hat. Und hier wäre es in beiden 
Varianten (C / C++) passiert.

von DoS (Gast)


Lesenswert?

A. S. schrieb:
> DoS schrieb:
>
>> Ein echter Katholik hat heute gar keinen Spaß, geht auch nicht ins
>> Internet sondern in sich (geistig) und trauert.
>
> Du meinst Protestant. Katholiken gehen morgens den Kreuzweg und
> nachmittags zur Karfreitagsliturgie.
> Dazwischen wird gearbeitet, ausmisten, schrubben und so, alles was
> keinen Krach macht (da gesetzlicher stiller Feiertag)

Fuck! Dann haben meine Eltern mich gehörig Verars*ht. Und wurden wohl 
von ihren Eltern...
Boah!

von Horst G. (horst_g532)


Lesenswert?

Zwitter schrieb:
> Weil wie oben erwähnt, es im KFZ ABS Steuergeräten etc, schlicht nicht
> erlaubt ist,

Soso; du kennst also die Interna aller KFZ-Steuergeräte, um diese 
Aussage so in dieser Allgemeinverbindlichkeit treffen zu können?
Interessant - ich wusste offenbar noch gar nicht, was in meinen eigenen 
Entwicklungsprojekten bis dato so vor sich ging.
Muss ich mal sehen, dass ich meine ganzen alten Entwicklungsteams 
nochmal an einen Tisch bekomme - wir müssen nachträglich die Pointer 
herauspatchen, weil der Zwitter vom Mikrocontrollerforum gesagt hat, 
dass das verboten ist.
Mal sehen, was die OEMs dazu sagen - hätten sie ja auch damals schon 
während ihrer Reviews merken können, dass wir hier Verbrechen begehen...

von Zeno (Gast)


Lesenswert?

Mladen G. schrieb:
> Pascal ist keine Sprache die in der Industrie eingesetzt wurde,
> moeglicherweise Turbo Pascal oder Delphi

Man erkläre mal den Unterschied zwischen Pascal und Turbopascal/Delphi.

Pascal gab es auch von MS und da da kenne ich mindestens 1 Programm, das 
industriell eingesetzt wurde.
Ach ja, ich habe selbst ein Programm mit Delphi geschrieben, welches 
weltweit industriell eingesetzt wird.

von Zeno (Gast)


Lesenswert?

(prx) A. K. schrieb:
> 1960 BASIC auf einem HP?

Basic gab es auf alle Fälle auf dem HP. Ob das 1960 schon so war kann 
ich nicht sagen. Ich habe aber noch 1990 HP-Basic gelernt/lernen müssen. 
Habe selbst noch einen 216'er von HP mit etwas 300'er Peripherie im 
Keller stehen. Das Ding funktioniert sogar noch und ich hatte den vor 
nicht allzu langer Zeit sogar noch mal angeworfen, um eine uralt 
Diskette zu kopieren.

von Der Robs (Gast)


Lesenswert?

Zwitter schrieb:
> Kann man in C ohne Pointer überhaupt programmieren?
> Wenn es um Zuverlässigkeit und Sicherheit geht stehen Pascal und ADA
> ganz oben.
> Heutzutage wird aber viel in C geschrieben, nur "geht" C überhaupt ohne
> Pointer?
> Ist C nicht sehr Pointerlastig?
> Wird in der Kernelentwicklung auf Pointer gesetzt?

Von welchem Kernel redest Du?
Dem Linux-Kernel? Da gibts Pointer.

Na klar kann man C auch ohne Pointer programmieren, aber warum sollte 
man.
Ist ungefähr so:
Kann man ein Auto (keine Automatikschaltung), auch ohne die 
Gangschaltung zu benutzen, fahren? Klar geht, aber warum um alles in der 
Welt?

Pointer in C sind effizient und schnell, und auch kein Hexenwerk. 
Solange man versteht was man und Pointer so tun, gibt es keine Probleme.

Um die Wahrscheinlichkeit von Programmierfehlern zu verringern, gibt es 
mehrere Ansätze. Einer davon sind die MISRA-C regeln. Diese 
mehr-oder-weniger Sinnvollen Regeln sollen helfen (nicht abschließend):

- Code-Verhalten nicht von zufälligen Implementierungen des Compilers 
abhängig zu machen (der C-Standard ist leider nicht immer eindeutig)
- typische potentielle Programmierfehler (z.b. if (a=b)) auszuschließen, 
entweder MISA-C Regel für diese Zeile ausschalten oder auf 2 Zeilen 
aufteilen.
- Sich Gedanken zu machen (z.B. if - else if ==> dann muß es auch ein 
abschließendes else geben) und zu dokumentieren
....

Andere Möglichkeiten sind z.B. unit-tests.

Aber mit oder ohne Pointer: Man darf bei Software per Definition nie 
davon ausgehen, daß diese Fehlerfrei ist. Man muß immer in 2 Richtungen 
arbeiten: Fehlervermeidung (z.B. Programmieren nach MISRA-C) und 
Fehlerbeherrschung (ein einzelner Programmierfehler darf nicht zum 
Flugzeugabsturz führen).

Gruß

Robert

von IEC61508 (Gast)


Lesenswert?

Zwitter schrieb:
> Leider konnte mir diese Person (die eben diese Vorgaben macht) nicht
> sagen, wie die Programmiersprache heißt, mit der KFZ ABS etc.
> Steuergeräte programmiert werden.

Schaust du in einschägige Normen. Dort steht, welche Sprachen 
'empfohlen' werden und welche nicht.

Zwitter schrieb:
> "geht" C überhaupt ohne
> Pointer?

Beim Funktionsaufruf mit Parameter 'call by reference' wird s eng. Sonst 
kein Problem solange man bei arrays eine Feldüberschreitung abfängt. Ach 
ja, für die Schreihälse: ein C array ist kein pointer. ;-)

von IEC61508 (Gast)


Lesenswert?

Der Robs schrieb:
> (ein einzelner Programmierfehler darf nicht zum
> Flugzeugabsturz führen)

Du kennst die Geschichte zum MAX Flieger?

von Johannes (Gast)


Lesenswert?

Syntaktisch mag ein C Array kein Pointer sein, aber in allen weiteren 
belangen ist es das gleiche. Der Compiler erzeugt auch den gleichen Code 
daraus.

Gegenbeweis: Formuliere ein Beispiel, das als Array funktioniert, aber 
nicht als Pointer. Beispiele die aufzeigen, dass es identisch ist, 
gibt's oben schon.

Nur mal so zum Ausholen ein Beispiel wo ein Array kein Pointer ist: In 
Java darf die JVM Arrays so anlegen wie sie möchte. Sie müssen weder am 
Stück im Speicher liegen, noch überhaupt vollständig allokiert sein.

von Wühlhase (Gast)


Lesenswert?

In Java würde ein ungültiger Arrayindex aber auch sofort zu einer 
OutOfBoundsException führen und nicht irgendeinen Mist liefern, den man 
fälschlicherweise für valide halten könnte.

von Michael B. (laberkopp)


Lesenswert?

Klaus H. schrieb:
> Das ist mir jetzt etwas zu sehr verallgemeinert. Das deckt sich
> zumindest nicht mit meiner Erfahrung.
> Hast Du konkrete Beispiele?

Sicher, aber die Darlegung was der Compiler wann falsch macht, ist schon 
zusammengerafft meistens ein ganzes Heft, mit Source code, 
disassemblierten Maschinencode, Beispielzahlen und Beispielergebnissen. 
Da glauben Schleifen daß Register erhalten blieben, oder floating point 
units daß sie Werte schon in andere Register übertragen hatten, früher 
gab es z.B. bugs in malloc/free von Borland, heute eher Bugs bei der 
expansion von templates. Ich rede eher nicht über 
Pointer-aliasing-Probleme, die sind ja oft mit Compileroptionen 
herbeigeredet.

> Compilerfehler hatte ich bisher eine Hand voll im Laufe der Jahre. Und
> die waren meist halb C halb C++.

So ist es auch bei mir. Früher C (als es noch kein C++ gab), inzwischen 
C++. Da wir auf 10 Plattformen compilieren, fallen solche Fehler auf. 
Dann wird analysiert, der Sprachstandard genau durchgeguckt, und 
manchmal ist halt einfach ein Fehler im Compiler. IBM z.B. 'xc' freut 
sich über eine gute Fehleranalyse und liefert dann auch in einiger Zeit 
einen gefixten Compiler. Microsoft (Template-Problem) kümmerte sich eher 
weniger.

Löthans schrieb:
> Sehr interessant! So einen Blödsinn habe ich noch nie gelesen

Ja nun, wenn man keine Erfahrung hat...

von Bluebeer (Gast)


Lesenswert?

Johannes schrieb:
> Syntaktisch mag ein C Array kein Pointer sein, aber in allen weiteren
> belangen ist es das gleiche. Der Compiler erzeugt auch den gleichen Code
> daraus.

Nein, tut er nicht. Sehr Compilerabhängig. pointercode ist effizienter 
in der regel, kürzer und schneller.

von Johannes (Gast)


Lesenswert?

Beispiele? Normalerweise sind Pointer eher problematisch in Sachen 
Optimierung bzgl. Aliasing.

von Cyblord -. (cyblord)


Lesenswert?

Bluebeer schrieb:
> Johannes schrieb:
>> Syntaktisch mag ein C Array kein Pointer sein, aber in allen weiteren
>> belangen ist es das gleiche. Der Compiler erzeugt auch den gleichen Code
>> daraus.
>
> Nein, tut er nicht. Sehr Compilerabhängig. pointercode ist effizienter
> in der regel, kürzer und schneller.

So viele Möglichkeiten hat der Compiler hier nicht. Da ein Array in C 
jederzeit zu einem Pointer degenerieren kann, und dann via diesem 
Pointer jederzeit angesprochen werden kann, muss der Compiler das Array 
entsprechend vorhersehbar im Speicher anlegen. Genau das ist ja der 
Unterschied zu anderen Hochsprachen.

Und wenn das Array immer gleich im Speicher liegen muss, kann auch der 
Zugriff darauf nicht sehr verschieden sein, von Compiler zu Compiler.

: Bearbeitet durch User
von IEC61508 (Gast)


Lesenswert?

Johannes schrieb:
> aber in allen weiteren
> belangen ist es das gleiche.

Was irgendein Compiler dahin optimiert, sollte keine allgemeingültige 
Referenz sein. :-(

Wirf einen Blick darauf, wie sich die Dinge im Speicher darstellen. ;-)

von Jobst Q. (joquis)


Lesenswert?

IEC61508 schrieb:
> Ach
> ja, für die Schreihälse: ein C array ist kein pointer. ;-)

Aber die Adresse des Arrays ist ein Pointer. Und der Zugriff auf ein 
Arrayelement enthält eine Pointerarithmetik.

Also dasselbe, nur versteckt für Leute, die Angst vor Pointern haben.

von IEC61508 (Gast)


Lesenswert?

Jobst Q. schrieb:
> die Adresse des Arrays
Ist eine Zahl, wo du das Feld im Speicher findest.

Jobst Q. schrieb:
> Pointer
Ist ein Speicher, in dem eine Zahl steht. Diese Zahl kann z. B. eine 
Adresse eines arry sein. ;-)

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

IEC61508 schrieb:
> Der Robs schrieb:
>> (ein einzelner Programmierfehler darf nicht zum
>> Flugzeugabsturz führen)
>
> Du kennst die Geschichte zum MAX Flieger?

Und wo war da der Programmierfehler? Der Fisch stinkt ja wirklich vom 
Kopf her. Die 737MAX hatte Probleme im Systemdesign und irgendwelchen 
Specs. Die reine Programmierung war nach allem was ich gelesen habe 
Spezifikationskonform.

Matthias

von A. S. (Gast)


Lesenswert?

DoS schrieb:
> Fuck! Dann haben meine Eltern mich gehörig Verars*ht. Und wurden wohl
> von ihren Eltern...
> Boah!

Frag mal nach. Meist stellt sich dann raus, dass der Hausherr doch 
Protestant war oder so.

Fasten (also kein Internet) gerne, aber arbeiten war völlig normal. 
Zumindest wenn man Eigentum hat. In einer Mietswohnung hat man 
vielleicht weniger bock, sich 4 Mal umzuziehen (Kreuzweg->Sonntagstaat, 
Arbeit->Alltagsklamotten, Liturgie->Sonntagstatt, 
Arbeit->Alltagsklamotten. .

von Sheeva P. (sheevaplug)


Lesenswert?

Peter Panda2 schrieb:
> Da es MISRA aber nun mal gibt, ist halt die Frage wie solche Sachen dann
> umgesetzt werden.
> Daher steht es hier zur Diskussion

Jaein. Tatsache ist, daß MISRA und andere Standards existieren, und daß 
sie in verschiedenen Bereichen zwingend vorgeschrieben sind.

Die Frage ist aber, ob diese Regularien tatsächlich das vorschreiben, 
was hier so gerne behauptet wird, nämlich, daß Pointer in C verboten 
seien.

Nun, die Juristen haben da einen Standardspruch: "Ein Blick ins Gesetz 
vereinfacht die Rechtsfindung". Analog dazu gilt hier: "Ein Blick in die 
Vorgaben..." Und ach, siehe da: Pointer sind in C keineswegs verboten, 
sogar Pointerarithmetik ist dabei unter bestimmten Umständen erlaubt. 
Alle mir bekannten Standards empfehlen nämlich nur, nach Möglichkeit (!) 
aus Pointer zu verzichten, und Pointerarithmetik ist nur bei 
Arrayzugriffen und mit gleichzeitiger Überprüfung der Feldgrenzen sowie 
einer Prüfung auf Nullpointer erlaubt. Huch.

von Cyblord -. (cyblord)


Lesenswert?

Sheeva P. schrieb:
> Und ach, siehe da: Pointer sind in C keineswegs verboten,
> sogar Pointerarithmetik ist dabei unter bestimmten Umständen erlaubt.
> Alle mir bekannten Standards empfehlen nämlich nur, nach Möglichkeit (!)
> aus Pointer zu verzichten, und Pointerarithmetik ist nur bei
> Arrayzugriffen und mit gleichzeitiger Überprüfung der Feldgrenzen sowie
> einer Prüfung auf Nullpointer erlaubt. Huch.

Das wurde alles schon mehrfach hier geschrieben, nur noch nicht von 
Sheeva. Huch.

von Sheeva P. (sheevaplug)


Lesenswert?

Arduino Fanboy D. schrieb:
> Löthans schrieb:
>> Sehr interessant! So einen Blödsinn habe ich noch nie gelesen
>
> Oha...
> Kritik mag der laberkopp gar nicht!
> Dann wird er ganz fix, ganz fies.

Möglicherweise -- also, es ist jetzt natürlich nur so eine Vermutung -- 
ist sein Nickname ja nicht zufällig, sondern durchaus passend gewählt. 
Wobei ich mich bei seinen "Beiträgen" regelmäßig frage, was ein so 
fortschrittsfeindlicher Mensch in der Softwareentwicklung macht; als 
Peitschenmacher, Faßbinder, Wagner oder Köhler wäre er vermutlich 
glücklicher und nicht ständig mit modernen Zeugs kontrontiert. Zumal das 
seine Argumentation ja auch schon beweist, daß er mit abstrakten Dingen 
heillos überfordert ist: wenn Compilerbauer einen fehlerhaften Compiler 
liefert, dann ist natürlich nicht sein Compilerbauer daran schuld, 
sondern die modernen features in der Sprachspezifikation... ;-)

von Sheeva P. (sheevaplug)


Lesenswert?

Cyblord -. schrieb:
> Sheeva P. schrieb:
>> Und ach, siehe da: Pointer sind in C keineswegs verboten,
>> sogar Pointerarithmetik ist dabei unter bestimmten Umständen erlaubt.
>> Alle mir bekannten Standards empfehlen nämlich nur, nach Möglichkeit (!)
>> aus Pointer zu verzichten, und Pointerarithmetik ist nur bei
>> Arrayzugriffen und mit gleichzeitiger Überprüfung der Feldgrenzen sowie
>> einer Prüfung auf Nullpointer erlaubt. Huch.
>
> Das wurde alles schon mehrfach hier geschrieben, nur noch nicht von
> Sheeva. Huch.

Tatsächlich hat meines Wissens bisher noch niemand genauer geschrieben, 
wie die tatsächlichen Einschränkungen von MISRA-C in diesem Bereich 
aussehen -- und der Unsinn, daß Pointer in entsprechenden Regularien 
verboten seien, wurde ja auch bereits mehrfach behauptet. Wo ist Dein 
Problemchen, Junge?

Beitrag #6643014 wurde von einem Moderator gelöscht.
von Cyblord -. (cyblord)


Lesenswert?

Sheeva P. schrieb:
> Tatsächlich hat meines Wissens bisher noch niemand genauer geschrieben,
> wie die tatsächlichen Einschränkungen von MISRA-C in diesem Bereich
> aussehen

Doch, wurde hier schon gemacht. Lesen hilft.

Beitrag #6643043 wurde von einem Moderator gelöscht.
Beitrag #6643051 wurde von einem Moderator gelöscht.
Beitrag #6643060 wurde von einem Moderator gelöscht.
Beitrag #6643061 wurde von einem Moderator gelöscht.
Beitrag #6643065 wurde von einem Moderator gelöscht.
Beitrag #6643072 wurde von einem Moderator gelöscht.
Beitrag #6643073 wurde von einem Moderator gelöscht.
von Löthans (Gast)


Lesenswert?

Michael B. schrieb:
>> Hast Du konkrete Beispiele?
>
> Sicher, aber die Darlegung was der Compiler wann falsch macht, ist schon
> zusammengerafft meistens ein ganzes Heft, mit Source code,
> disassemblierten Maschinencode, Beispielzahlen und Beispielergebnissen.
> Da glauben Schleifen daß Register erhalten blieben, oder floating point
> units daß sie Werte schon in andere Register übertragen hatten, früher
> gab es z.B. bugs in malloc/free von Borland, heute eher Bugs bei der
> expansion von templates. Ich rede eher nicht über
> Pointer-aliasing-Probleme, die sind ja oft mit Compileroptionen
> herbeigeredet.

Eine andere als eine dermaßen unspezifische habe ich nicht erwartet. Und 
sie kommt dann ja auch.

Die Frage war aber nicht nach Deinem "ganzen Heft", sondern nach "einem 
konkreten Beispiel". Tja.

Beitrag #6643354 wurde von einem Moderator gelöscht.
von M. K. (sylaina)


Lesenswert?

Zwitter schrieb:
> Kann man in C ohne Pointer überhaupt programmieren?

Kann man aber das macht die ganze Sache erheblich aufwendiger und 
unübersichtlicher, warum also sollte man das tun? Häufig verwendet man 
schon Pointer, ohne dass man es überhaupt merkt, Beispiel Arrays.

von Stefan F. (Gast)


Lesenswert?

Neue Java Kollegen bitten mich oft Referenzen und Garbage Collector zu 
erklären. Da lange man zwangsläufig ganz schnell bei den Pointern, die 
unter der Haube dahinter stecken.

Dass Pointer von gewissen Leuten verteufelt werden, kann ich nicht 
nachvollziehen.

Ja sie sind fehlerträchtig. Aber andere Ersatz-Konstrukte sind ebenso 
Fehlerträchtig, wenn man sie nicht voll verstanden hat.

Das Thema "Pufferüberlauf" hat nur indirekt mit Zeigern zu tun. 
Pufferüberläufe kann man mit Array-Indizies und Referenzen ebenso 
auslösen, wenn es keine speziellen Schutzmechanismen gibt.

Pointer geben einem die Freiheit, auf Schutzmechanismen zu verzichten 
und sie zu hintergehen. Das bedeutet aber umgekehrt nicht, dass man das 
tun sollte.

Also sind nicht die Pointer "böse", sondern das, was man daraus macht.

Beitrag #6643998 wurde von einem Moderator gelöscht.
Beitrag #6644017 wurde von einem Moderator gelöscht.
von Al Fine (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Dass Pointer von gewissen Leuten verteufelt werden, kann ich nicht
> nachvollziehen.
>
> Ja sie sind fehlerträchtig. Aber andere Ersatz-Konstrukte sind ebenso
> Fehlerträchtig, wenn man sie nicht voll verstanden hat.

Alles, was über Parameterübergabe hinausgeht ist relativ fehleranfällig.
Und gerade C hat nun einmal die Eigenschaft, dass man dort andauernd 
wieder bei irgendwelcher Pointer-Arithmetik landet. Niemand scheint sich 
die Mühe zu machen, zB irgendwelche Container-Klassen abzukapseln. Da 
wird grundsätzlich der Pointer mit einem "size" Parameter übergeben 
und dann raw darauf zugegriffen. Ist natürlich "völlig ungefährlich". 
Stimmt auch meistens.
uC Programmierung sieht naturgemäß ein wenig anders aus als der meiste 
Application-Code, aber bei open-source Projekten in C weiß ich immer 
schon: Wenn irgendwo etwas geparsed wird oder interne Strukturen 
gebraucht werden, ist da ein endloser Block an Pointer-gefrickel zu 
erwarten. Da wirft man nur einen Blick drauf und weiß Bescheid: Der Code 
ist derartig schlecht strukturiert, dass an tausenden Stellen verwendete 
Operationen wie "Interpretiere jetzt einen Pointer als einen Header mit 
3 shorts zb" da auch einfach immer wieder so im Code stehen
```
char *p ....
...
x = *(header*)p;
p += 6;
```
Die zwei Zeilen sind zu kurz, als das jemand auf die Idee käme das in 
eine Funktion zu packen. Die Konsequenz von Schlampigkeit 2. Ordnung.

von Stefan F. (Gast)


Lesenswert?

Al Fine schrieb:
> Niemand scheint sich die Mühe zu machen,
> zB irgendwelche Container-Klassen abzukapseln.

Logisch, weil das in C nicht geht. In einigen anderen Sprachen hat die 
Möglichkeit geschaffen. Insofern ist dein "Niemand" nicht wirklich 
zutreffend.

Bei dem von dir genannten Parser-Code geht es um Effizienz. In Assembler 
sähre der noch schlimmer aus. Da muss man halt durch - oder eben die 
Prioritäten anders legen, dann kann man seinen Code auch schöner 
strukturieren.

von Al Fine (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Logisch, weil das in C nicht geht.

So einfach würde ich die C-Verfechter jetzt nicht vom heißen Stuhl 
lassen. Naturlich geht das mit C-typischen Mitteln wie Macros.

von Stefan F. (Gast)


Lesenswert?

Al Fine schrieb:
> Naturlich geht das mit C-typischen Mitteln wie Macros.

Du erzeugst Klassen in C mit Makros? Das will ich sehen!

von Al Fine (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Du erzeugst Klassen in C mit Makros? Das will ich sehen!

Sorry, aber "Nächster!"

Lern UML an der UNI und sag dem Prof in der Abschlussprüfung "Das geht 
nicht in C"

von Stefan F. (Gast)


Lesenswert?

Al Fine schrieb:
> Sorry, aber "Nächster!"
> Lern UML an der UNI und sag dem Prof in der Abschlussprüfung "Das geht
> nicht in C"

Ich erkenne darin keine Antwort auf meine Frage, wie man mit Makros in C 
Container-Klassen implementiert.

Mir ist durchaus bewusst, dass man in C objektorientiert programmieren 
kann. Aber nicht so, dass es automatisch Zeiger-, Typ- und 
Überlaufsicher wird und nicht so, wie man den Begriff "Klasse" 
heutzutage versteht.

von Laserfranz (Gast)


Lesenswert?

Huch, ich dachte hier gehts um solche komischen Laserpointer.

von Al Fine (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Mir ist durchaus bewusst, dass man in C objektorientiert programmieren
> kann.

Dann verstehe ich das Problem nicht. Alleine die Zugriffe auf Elemente 
in eine Funktion zu kapseln, macht es unglaublich viel einfacher, dort 
nach Belieben Gültigkeitsprüfungen durchzuführen. Ranges lassen sich 
auch darstellen und ableiten.

Google sagt, gibts alles:
https://github.com/LeoVen/C-Macro-Collections
https://github.com/P-p-H-d/mlib
....

von Al Fine (Gast)


Lesenswert?

Ach so, ja...
Dass das in C eine Qual ist, ist selbstverständlich richtig. Sollte man 
wissen, wenn man auf plain C beharrt.

von Stefan F. (Gast)


Lesenswert?

Al Fine schrieb:
> macht es unglaublich viel einfacher

Mag sein (sehe ich anders). Aber manchmal liegt die Priorität eben in 
der Effizienz des Codes. Und genau da benutzt man C.

Wo Effizienz weniger wichtig ist benutze ich Java. Da hast du den ganzen 
Schutz-Schnickschnack automatisch und unumgänglich.

von Al Fine (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Mag sein (sehe ich anders). Aber manchmal liegt die Priorität eben in
> der Effizienz des Codes.

Und genau das ist der Punkt, wo mir die Entwicklungen dieses 
Jahrtausends verschlafen scheinen. Wie kommst du auf jetzt auf Effizenz? 
Ist gekapselter Code ineffizent?

von Einer K. (Gast)


Lesenswert?

Al Fine schrieb:
> Ist gekapselter Code ineffizent?
Laufzeitprüfungen, heißen Laufzeitprüfungen, weil sie zur Laufzeit 
stattfinden müssen.
Das hat natürlich, wen soll es auch wundern, Auswirkungen auf die 
Laufzeit.

von Al Fine (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Laufzeitprüfungen, heißen Laufzeitprüfungen, weil sie zur Laufzeit
> stattfinden müssen.

Da sehe ich die Frage aber nicht beantwortet. Der Compiler kann 
bounds-Prüfungen statisch wegoptimieren, wenn man da p und p+1024 hat. 
Wenn nicht, hat man die halt nicht. Nein - wo ist der Nachteil, den 
pointer und den end-pointer gekapselt in einer Funktion zu haben? Warum 
keine Funktion, um den header da aus so einer Range zu ziehen? Ich 
verstehe das nicht...

von Stefan B. (Gast)


Lesenswert?

Mark B. schrieb:
> Zwitter schrieb:
>> weiß jemand, ZUBERLÄSSIG! welche Porgammiersprache in Autos für
>> sicherheitskritische Komponenten verwendet wird?
>
> In der Automobilbranche wird sehr oft C und C++ eingesetzt, und zwar
> nach dem MISRA-Standard:
>
> https://de.wikipedia.org/wiki/MISRA-C

Misra verbietet keine Pointer.

Beitrag #6644243 wurde von einem Moderator gelöscht.
von Meister E. (edson)


Lesenswert?

Stefan ⛄ F. schrieb:
> Al Fine schrieb:
>> Niemand scheint sich die Mühe zu machen,
>> zB irgendwelche Container-Klassen abzukapseln.
>
> Logisch, weil das in C nicht geht. In einigen anderen Sprachen hat die
> Möglichkeit geschaffen. Insofern ist dein "Niemand" nicht wirklich
> zutreffend.
>
> Bei dem von dir genannten Parser-Code geht es um Effizienz. In Assembler
> sähre der noch schlimmer aus. Da muss man halt durch - oder eben die
> Prioritäten anders legen, dann kann man seinen Code auch schöner
> strukturieren.

Erstens gibt es nicht den Einen Assembler, zweitens ist das keine 
Hochsprache und drittens ist das als Beispiel an dieser Stelle total 
unpassend. Aber Hauptsache mitgeredet...

Beitrag #6644312 wurde von einem Moderator gelöscht.
von A. S. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Mag sein (sehe ich anders). Aber manchmal liegt die Priorität eben in
> der Effizienz des Codes. Und genau da benutzt man C.
>
> Wo Effizienz weniger wichtig ist benutze ich Java. Da hast du den ganzen
> Schutz-Schnickschnack automatisch und unumgänglich.

Das ist jetzt nicht Dein Ernst, oder? Die hackst in C wegen der 
Effizienz? Falls Du mit Effizienz hier Code-Größe oder -Geschwindigkeit 
meinst, dann sei Dir versichert, dass Du eine Ausnahme bist.

Die allermeisten verwenden C wegen einfach, verfügbar, erforscht, 
bekannt, eindeutig, verlässlich, breite Toolchain. Und für diese 
allermeisten ist es wichtiger, zuverlässig als performant zu 
programmieren.

Beitrag #6644332 wurde von einem Moderator gelöscht.
von Stefan F. (Gast)


Lesenswert?

A. S. schrieb:
> Das ist jetzt nicht Dein Ernst, oder? Die hackst in C wegen der
> Effizienz?

Ja sicher. In C programmiere ich kleine Mikrocontroller, z.B den 
ATtiny13. Was anderes läuft darauf auch nicht (außer Assembler, aber das 
Wort wurde mir hier ja verboten).

Auf dem Arbeitsplatz programmiere ich überwiegend in Java und gar nicht 
in C. Eben weil da Zuverlässigkeit wichtiger ist. Das sind aber auch 
völlig andere Maschinen, um die es dort geht.

C ist dort regelrecht verboten, weil man sich damit zu schnell ins 
eigene Knie schießen kann. Kann man mit Java zwar auch, aber nicht ganz 
so schnell.

von Klaus H. (klummel69)


Lesenswert?

A. S. schrieb:
> Die allermeisten verwenden C wegen einfach, verfügbar, erforscht,
> bekannt, eindeutig, verlässlich, breite Toolchain. Und für diese
> allermeisten ist es wichtiger, zuverlässig als performant zu
> programmieren.

Also ohne jetzt zuviel Öl ins Feuer zu giessen: C hat knapp 200 cases of 
undefined behavior.
Zuverlässig ist anders, vor allem wenn sich bei einem Compilerupdate das 
undefined behavior ändert.
Ich nutze C deshalb, weil es oft nichts anderes gibt. Mir wäre eine 
Sprache viel lieber, die "zuverlässig" hilft, dass Programmierer weniger 
Fehler einbauen. Im embedded Bereich ist einfach weniger Auswahl...

von IEC61508 (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Das sind aber auch
> völlig andere Maschinen, um die es dort geht.

Was sind das denn für Maschinen?

von Stefan F. (Gast)


Lesenswert?

IEC61508 schrieb:
> Was sind das denn für Maschinen?

Server für Enterprise Anwendungen. Online Shops, Payment Gateways, 
Geschäftsanwendungen, etc.

Java macht auch auf kleineren Geräten Freude. Ich habe es zum Spaß lange 
Zeit mit Lego Mindstorms NXT eingesetzt. Aber auf ATtinies und geht es 
halt nicht.

von IEC61508 (Gast)


Lesenswert?

Ok, nix gefährliches. Dann ist es auch egal, ob C, Java oder sonst was. 
;-)

von Stefan F. (Gast)


Lesenswert?

IEC61508 schrieb:
> Ok, nix gefährliches

Ja. Wenn bei meinen Programmen etwas schief läuft, kann es "nur" teuer 
werden.

von Einer K. (Gast)


Lesenswert?

Klaus H. schrieb:
> vor allem wenn sich bei einem Compilerupdate das
> undefined behavior ändert.
Wer sich auf ein UB verlässt, das verhalten sich ändert, dann das 
Programm nicht mehr tut, was es vorher tat, der ist selber schuld.

Es heißt ja gerade UB, eben weil man sich nicht darauf verlassen kann, 
dass es immer und überall immer das gleiche tut.

Nein, das ist eine Schlampigkeit/Dummheit des Programmierers und kein 
Nachteil der Sprache.

von Stefan F. (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Nein, das ist eine Schlampigkeit/Dummheit des Programmierers und kein
> Nachteil der Sprache.

Allerdings wurden Hochsprachen erfunden, damit der Programmierer sich im 
Idealfall um solche Details keine Gedanken machen muss. Keine mir 
bekannte erfüllt diesen Anspruch vollständig. Doch C ist diesbezüglich 
eine der schlechtesten.

C ist quasi die Ente/Käfer/Trabbi unter den Automobilen. Nicht schlecht, 
aber auch nicht deppensicher.

Beitrag #6644495 wurde von einem Moderator gelöscht.
von Heiko L. (zer0)


Lesenswert?

Arduino Fanboy D. schrieb:
> Nein, das ist eine Schlampigkeit/Dummheit des Programmierers und kein
> Nachteil der Sprache.

Stefan ⛄ F. schrieb:
> Allerdings wurden Hochsprachen erfunden, damit der Programmierer sich im
> Idealfall um solche Details keine Gedanken machen muss.

Es ist sogar anders herum: Es ist ein Vorteil der Sprache, weil nur 
dadurch bestimmte Optimierungen möglich sind. Anders herum wurden viele 
Spachen danach eher nicht erfunden, um sich um undefined behaviour 
keine Gedanken machen zu müssen.

von Nop (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:

> Nein, das ist eine Schlampigkeit/Dummheit des Programmierers

Das ist zwar richtig, aber Bugs gibt es immer und überall. Speziell 
diese Bugs sind besonders eklig, weil sie schwer zu entdecken sind, 
solange sie keine Laufzeitauswirkungen haben. Den Compiler, mit dem das 
in zwei Jahren auffallen wird, hast Du jetzt ja noch nicht.

> und kein Nachteil der Sprache.

Es wäre nur dann kein Nachteil, wenn zuverlässig zumindest eine 
Compiler-Warnung käme. Das geschieht zwar oft, aber beileibe nicht 
immer. Bei Software, wo es darauf ankommt, verwendet man daher 
inzwischen recht aufwendige Tools zur statischen Codeanalyse.

von Einer K. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Allerdings wurden Hochsprachen erfunden, damit der Programmierer sich im
> Idealfall um solche Details keine Gedanken machen muss.

Wenn ich das richtig verstanden habe, wurde C nicht dafür entwickelt um 
jedem Deppen jede Schlampigkeit durchgehen zu lassen, oder sie ihm um 
die Ohren zu hauen.
Das war nicht das Ziel. Beides nicht.

Sondern, in erste Linie, um die Portierung der Unix Kerne zu 
erleichtern.
1. den Assembler weitgehend zu ersetzen.
2. einfach zu portierender Kompiler
3. Performance und nochmal Performance

Stefan ⛄ F. schrieb:
> Allerdings wurden Hochsprachen erfunden, damit der Programmierer sich im
> Idealfall um solche Details keine Gedanken machen muss.
Deine Erwartungshaltung entspricht nicht den Zielen der ursprünglichen 
Entwickler.
Deine Erwartungshaltung beruht also auf einem Irrtum, deinerseits.

Natürlich kann man in C heute noch 2 Buchstaben addieren, die Wurzel 
daraus ziehen und das Ergebnis dann als Pointer auffassen/nutzen.
OK, mittlerweile hauts dir einige Warnungen und Errors um die Ohren.
Mehr an "Benutzerfreundlichkeit" kann eine solche Sprache nicht liefern, 
welche ohne Laufzeitprüfungen auskommen muss.

von A. S. (Gast)


Lesenswert?

Nop schrieb:
> Es wäre nur dann kein Nachteil, wenn zuverlässig zumindest eine
> Compiler-Warnung käme. Das geschieht zwar oft, aber beileibe nicht
> immer. Bei Software, wo es darauf ankommt, verwendet man daher
> inzwischen recht aufwendige Tools zur statischen Codeanalyse.

Die Warnungen kommen doch, wenn man sie einschaltet. Und diese 
aufwendigen Tools sind zu Spottpreisen da und zuverlässig. Im Zweifel 
kann man die Sprachdefinition durchsuchen, so klein und präzise ist die.

Natürlich gibt es keinen Grund, Webserver oder Desktop-Anwendungen in C 
zu schreiben. Dafür gibt es Java, C++ etc.

von Nop (Gast)


Lesenswert?

A. S. schrieb:

> Die Warnungen kommen doch, wenn man sie einschaltet.

Oft, aber nicht 100% zuverlässig. Das ist auch gar nicht möglich.

> Und diese
> aufwendigen Tools sind zu Spottpreisen da und zuverlässig.

Die, die zu Spottpreisen verfügbar sind, sind schon gar nicht 
zuverlässig. Ich rede hier nicht über Müll wie PC-Lint, das vor allem 
durch falsch-positive Warnungen "glänzt", und auch nicht CppCheck, das 
zwar empfehlenswert ist, aber bei der interprozeduralen Analyse einfach 
nichts bietet.

> Im Zweifel
> kann man die Sprachdefinition durchsuchen, so klein und präzise ist die.

Die Sprachfefinition schon, aber die Codebasis nicht unbedingt.

von Mark B. (markbrandis)


Lesenswert?

Stefan B. schrieb:
> Mark B. schrieb:
>> Zwitter schrieb:
>>> weiß jemand, ZUBERLÄSSIG! welche Porgammiersprache in Autos für
>>> sicherheitskritische Komponenten verwendet wird?
>>
>> In der Automobilbranche wird sehr oft C und C++ eingesetzt, und zwar
>> nach dem MISRA-Standard:
>>
>> https://de.wikipedia.org/wiki/MISRA-C
>
> Misra verbietet keine Pointer.

Das hat zum Glück auch keiner behauptet. ;-)
MISRA schränkt aber die Verwendung von Zeigern ein. Nach den 
MISRA-Regeln kann man also nicht alles mit Zeigern tun, was vom 
Sprachstandard her möglich wäre.

von Rolf M. (rmagnus)


Lesenswert?

Klaus H. schrieb:
> A. S. schrieb:
>> Die allermeisten verwenden C wegen einfach, verfügbar, erforscht,
>> bekannt, eindeutig, verlässlich, breite Toolchain. Und für diese
>> allermeisten ist es wichtiger, zuverlässig als performant zu
>> programmieren.
>
> Also ohne jetzt zuviel Öl ins Feuer zu giessen: C hat knapp 200 cases of
> undefined behavior.
> Zuverlässig ist anders, vor allem wenn sich bei einem Compilerupdate das
> undefined behavior ändert.

Das klingt, als ob du undefined behavior als etwas betrachtet, das man 
routinemäßig überall einsetzt. Aber es ist im Standard deshalb erwähnt, 
weil man es eben nicht nutzen darf.

von Klaus H. (klummel69)


Lesenswert?

Rolf M. schrieb:
> Das klingt, als ob du undefined behavior als etwas betrachtet, das man
> routinemäßig überall einsetzt. Aber es ist im Standard deshalb erwähnt,
> weil man es eben nicht nutzen darf.

Um Gotteswillen nein, sorry das war ein Eigentor, die Intention war eine 
andere.
A. S. hatte geschrieben,
> Die allermeisten verwenden C wegen einfach, verfügbar, erforscht,
> bekannt, eindeutig, verlässlich, breite Toolchain. Und für diese
> allermeisten ist es wichtiger, zuverlässig als performant zu
> programmieren.
Das Argument "Zuverlässig" halte ich für falsch.
C nimmt man, weil es sich am embedded Markt durchgesetzt hat.
Die Zuverlässigkeit kommt in C nicht aus der Sprache, sondern aus dem 
Zusammenspiel Programmiererfahrung und einem guten Prozess (Codeanalyse, 
Reviews, guten Tests).

Zuverlässig im Sinne es hilft mir zuverlässig Fehler zu vermeiden (nicht 
zuverlässig undefiniertes Verhalten zu besitzen).
Genau deshalb sind ja in vielen Branchen bestimmte C Spracheigenschaften 
stark eingegrenzt worden: damit das Risiko sinkt, dass dadurch Fehler 
eingebaut werden.

von Wühlhase (Gast)


Lesenswert?

Rolf M. schrieb:
> Das klingt, als ob du undefined behavior als etwas betrachtet, das man
> routinemäßig überall einsetzt. Aber es ist im Standard deshalb erwähnt,
> weil man es eben nicht nutzen darf.

Also anders gesagt: Die behelfsmäßigen Korrekturen des Sprachstandards 
sind sehr umfangreich. 200 Fälle undefinierten Verhaltens finde ich 
nicht gerade wenig, allzumal C eine relativ übersichtliche Sprache ist. 
Und dann sind ja noch die ganzen Fälle, die zwar definiert sind, die man 
aber trotzdem unterlassen sollte.

Man muß C zugute halten daß es noch aus einer Zeit stammt in der viele 
Dinge, die heute möglich und selbstverständlich sind, damals einfach 
noch nicht gab oder einfach nur von nachrangiger Wichtigkeit waren. An 
einigen Punkten fehlte damals auch einfach die Erfahrung, die man heute 
hat.

Das ist aber kein Grund, die Unzulänglichkeiten von C nicht als solche 
zu benennen. Oder diese gar als Vorteil umzudeuten, das ist einfach zu 
lächerlich.

von Stefan F. (Gast)


Lesenswert?

Wühlhase schrieb:
> Man muß C zugute halten daß es noch aus einer Zeit stammt in der viele
> Dinge, die heute möglich und selbstverständlich sind, damals einfach
> noch nicht gab oder einfach nur von nachrangiger Wichtigkeit waren. An
> einigen Punkten fehlte damals auch einfach die Erfahrung, die man heute
> hat.

Ja, das sehe ich auch so. Auf den PC bezogen musste man bis zum 386er 
noch um jeden Takt feilschen, wenn man flüssige Grafik oder gar Sound 
erzeugen wollte.

Heute merkst du den Unterschied kaum noch, wenn ein Programm zugunsten 
der Sicherheit doppelt so viele Takte braucht. Weil die 
Gesamt-Performance eines PC eher durch die Leistung der Peripherie um 
die CPU herum dominiert wird.

Heite können wir uns eine Menge Sicherheit und Komfort leisten - 
weswegen hardwarenahe Programmiersprachen wie C in diesem Bereich 
allmählich obsolet werden. Auf Mikrocontrollern sieht die Welt noch 
anders aus. Aber auch dort machen sich sogar schon Scriptsprachen breit.

von Philipp Klaus K. (pkk)


Lesenswert?

Wühlhase schrieb:
>
> Also anders gesagt: Die behelfsmäßigen Korrekturen des Sprachstandards
> sind sehr umfangreich. 200 Fälle undefinierten Verhaltens finde ich
> nicht gerade wenig, allzumal C eine relativ übersichtliche Sprache ist.
> Und dann sind ja noch die ganzen Fälle, die zwar definiert sind, die man
> aber trotzdem unterlassen sollte.

Die meisten dieser ca 200 Fälle beziehen sich auf die 
Standardbibliothek. Wer die gesamte Liste sehen will: Anhang J.2 im 
C-Standard.

>
> Das ist aber kein Grund, die Unzulänglichkeiten von C nicht als solche
> zu benennen. Oder diese gar als Vorteil umzudeuten, das ist einfach zu
> lächerlich.

Wo es auf Effizienz ankommt, kann es durchaus ein Vorteil sein, dass es 
undefiniertes Verhalten ist, einen Nullzeiger zu dereferenzieren. Das 
zur Laufzeit abzufangen, wäre teuer. Und wenn es abgefangen würde, was 
wäre dann ein sinnvolles zu definierendes Verhalten? Den Wert 0 
zurückzuliefern? Dann hätte man an dieser Stelle zwar kein undefiniertes 
Verhalten mehr, aber meist immer noch einen Bug in dem Programm, das das 
macht.
dann hätte man zwar weniger undefiniertes Verhalten, aber wohl sogar 
mehr Bugs in Programmen, da ein Bug der heute, dank undefiniertem 
Verhalten auf vielen Systemem als SIGSEGV gut sichtbar ist plötzlich 
schwieriger zu debuggen wäre, da er erst an anderer Stelle im Programm 
Auswirkungen durch einen falschen Wert hätte.

von Rolf M. (rmagnus)


Lesenswert?

Philipp Klaus K. schrieb:
>> Das ist aber kein Grund, die Unzulänglichkeiten von C nicht als solche
>> zu benennen. Oder diese gar als Vorteil umzudeuten, das ist einfach zu
>> lächerlich.
>
> Wo es auf Effizienz ankommt, kann es durchaus ein Vorteil sein, dass es
> undefiniertes Verhalten ist, einen Nullzeiger zu dereferenzieren. Das
> zur Laufzeit abzufangen, wäre teuer. Und wenn es abgefangen würde, was
> wäre dann ein sinnvolles zu definierendes Verhalten? Den Wert 0
> zurückzuliefern? Dann hätte man an dieser Stelle zwar kein undefiniertes
> Verhalten mehr, aber meist immer noch einen Bug in dem Programm, das das
> macht.

Das ist der Punkt. In Java würde z.B. bei einem Zugriff "out of bounds" 
eine Exception ausgelöst. Die muss man auch erst mal abfangen und dann 
etwas sinnvolles damit machen. Und wie kann man sinnvoll reagieren, wenn 
man weiß, dass jetzt Daten durch einen gerade aufgetretenen 
Programmfehler kaputt sind?
Was bleibt, ist nur, dass das Programm definiert abstürzt, statt ggf. 
irgendwas zu tun.
Übrigens verbietet C solche Prüfungen nicht. Ein Compiler darf die 
durchaus auch einbauen, und es gibt Compiler, die so etwas auch können. 
Es wird nur von C nicht gefordert.

: Bearbeitet durch User
von Wühlhase (Gast)


Lesenswert?

Ehrlich gesagt sehe ich keinen Zusammenhang zwischen wohldefiniertem 
Verhalten und Effizienz (was immer Effizienz auch bedeuten mag).

Und wie gesagt: auf den meisten Prozessoren, die heute so eingesetzt 
werden, kann man sich zumindest gelegentliche teure Operationen leisten. 
Sicher nicht auf einem ATtiny, aber die meisten STM32 langweilen sich 
doch die meiste Zeit, wenn sie nicht gerade mit der HAL programmiert 
wurden.
Aber vor noch nicht allzulanger Zeit war das eben anders.

Und einen Nullpointer als Rückgabewert für eine fehlgeschlagene 
Operation wie z.B. abgelehnte Speicherallokation (das meintest du doch?) 
würde ich nicht als undefiniertes Verhalten bezeichnen. Denn was man 
damit tun soll, ist klar: nämlich nichts.

von A. S. (Gast)


Lesenswert?

Klaus H. schrieb:
> Das Argument "Zuverlässig" halte ich für falsch.

Mit Zuverlässig meinte ich hier: es ist abzusehen, was passiert.

Kaum ein C-compiler hat nennenswerte unbekannte Fehler. Oder fehlende 
Sprachfeatures. Bei UB habe ich ggf. Müll, aber es ist spezifiziert, was 
UB ist. Kein GB-Collector, der macht, wann er will.

Es ging im Beispiel ja darum, beim Parsen von Daten den Code zu 
strukturieren. Und Stefan erweckte den Eindruck, dass C vor allem wegen 
der Performance verwendet wir.

Stefan ⛄ F. schrieb:
> Aber manchmal liegt die Priorität eben in der Effizienz des Codes. Und
> genau da benutzt man C.
> Wo Effizienz weniger wichtig ist benutze ich Java.

Und das ist m. E. Falsch. C benutzt man auch dort, wo Zuverlässigkeit 
(Safety, Verfügbarkeit, Echtzeit) wichtig ist.

von Philipp Klaus K. (pkk)


Lesenswert?

Wühlhase schrieb:

> Und einen Nullpointer als Rückgabewert für eine fehlgeschlagene
> Operation wie z.B. abgelehnte Speicherallokation (das meintest du doch?)
> würde ich nicht als undefiniertes Verhalten bezeichnen. Denn was man
> damit tun soll, ist klar: nämlich nichts.

Das es den Nullzeiger als Rückgabewert gibt ist noch nicht das 
undefinierte Verhalten. Das undefinierte Verhalten tritt auf, sobald ich 
diesen Zeiger dereferenziere, also so etwas:
1
char *p = malloc(50000);
2
if(!p)
3
  *p = 'a'; // Undefiniertes Verhalten, wenn diese Zeile erreicht wird

Undefiniertes Verhalten heißt dann, dass die C-Implementierung machen 
darf, was sie will. Und Implementierungen nutzen diese Freiheit: Auf 
einem kleinen µC, wo sich so etwas nicht effizient abfangen lässt, wird 
halt versucht etwas an die physische Adresse 0 zuschreiben, was oft 
nichts bewirkt, oder in eine dort befindliches I/O-Register schreibt. 
Auf einem PC wird das Programm per Segfault beendet.

Natürlich ist klar, dass du diesen Nullzeiger nicht dereferenzieren 
sollst. Aber wenn du es doch tust ist es eben einer diese ca 200 Fälle 
von undefiniertem Verhalten.

von Philipp Klaus K. (pkk)


Lesenswert?

Rolf M. schrieb:

> Übrigens verbietet C solche Prüfungen nicht. Ein Compiler darf die
> durchaus auch einbauen, und es gibt Compiler, die so etwas auch können.
> Es wird nur von C nicht gefordert.

Tatsächlich ist die Möglichkeit, Fehler zu erkennen auch eine Motivation 
für undefiniertes Verhalten: In C ist der Zugriff auf uninitalisierte 
lokale Variablen undefiniertes Verhalten. Eine naheliegende Alternative 
wäre, diese implizit mit 0 zu initialisieren. Das würde Performanz 
kosten, aber es gibt noch ein weiteres Argument dagegen:

In vielen Fällen wäre eine Initalisierung mit 0 nicht das, was der 
Programmierer wollte, man hätte also auch bei definiertem Verhalten 
einen Bug. Aber mit undefiniertem Verhalten kann die Implementierung 
einen Fehler melden (zur Compilezeit, oder z.B. mit valgrind auch zur 
Laufzeit), was sie nicht dürfte, wenn das Verhalten in diesem Fall 
definiert wäre.

von Stefan F. (Gast)


Lesenswert?

Rolf M. schrieb:
> Was bleibt, ist nur, dass das Programm definiert abstürzt, statt ggf.
> irgendwas zu tun.

Web Server sollen dabei nicht abstürzen, sondern einen Error 500 zurück 
liefern. Die anderen User, die von dem Fehler nicht betroffen sind, 
wollen schließlich weiter arbeiten. Und der eine betroffene User will 
vielleicht auch mit anderen Datensätzen weiter arbeiten.

Deswegen macht dort eine Exception, die man fangen muss durchaus Sinn.

Rolf M. schrieb:
> Übrigens verbietet C solche Prüfungen nicht. Ein Compiler darf die
> durchaus auch einbauen, und es gibt Compiler, die so etwas auch können.
> Es wird nur von C nicht gefordert.

Ja, guter Hinweis.

von Philipp Klaus K. (pkk)


Lesenswert?

Da der Thread vom ursprünglichen Thema nun zu undefiniertem Verhalten 
abschweifte, könnte etwas Hintergrund nützlich sein. Es gibt mehrere 
Motivationen für undefiniertes Verhalten in C. Die beiden wichtigsten 
sind:

1) Sachen, die eigentlich Fehler sind, aber sich im Allgemeinen zur 
Compilezeit nicht erkennen lassen (meist weil die Frage, ob sie 
auftreten, äquivalent zum Halteproblem ist). Hier soll eine für manche 
Implementierungen (of µC) teure Fehlererkennung zur Laufzeit nicht 
vorgeschrieben werden, um die Effizienz nicht zu beinträchtigen. Das 
undefinierte Verhalten erlaubt Implementierungen natürlich zu versuchen, 
manchmal Fehler zur Compilezeit oder zur Laufzeit zu melden.

2) Sachen, bei denen es unübersichtlich viele sinnvolle Möglichkeiten 
gibt, sie umzusetzen. Hier soll die Freiheit der Implementierungen nicht 
eingeschänkt werden. Meist geht es hier um die Interaktion des 
C-Programms mit seiner Umgebung, z.B. Bibliotheksfunktionen, deren 
Funktionssignatur standardisiert ist, die aber etwas systemspezifisches 
machen.

P.S.:
Zu 1) Wenn diese leicht zu erkennen wären, würde man sie statt dessen zu 
Constraint Violations (Fehler zur Compilezeit) machen.
Zu 2) Wenn es nur eine überschaubare Anzahl sinnvoller Möglichkeiten 
gäbe würde man hier stattdessen implementierungsabhängiges Verhalten 
verwenden (und in den Standard eine Liste dieser Möglichkeiten 
aufnehmen, während die Implementierung dokumentieren müsste, welche 
davon sie umsetzt).

: Bearbeitet durch User
von Nop (Gast)


Lesenswert?

Philipp Klaus K. schrieb:

> Tatsächlich ist die Möglichkeit, Fehler zu erkennen auch eine Motivation
> für undefiniertes Verhalten:

Nein. Die Motivation ist, daß lokale Variablen nicht automatisch 
initialisiert werden, weil das Laufzeit-Performance kosten würde, sobald 
der automatische Initialisierungswert (z.B. 0) nicht das ist, was 
gebraucht wird.

> In C ist der Zugriff auf uninitalisierte
> lokale Variablen undefiniertes Verhalten.

Ob man dann einen Fehler erkennt oder nicht, hängt davon ab, was im 
Speicher gerade steht. Zuverlässig ist das nicht. Wäre die Erkennung 
eines Fehlers die Motivation, dann würde wie in Rust der Compiler gleich 
das Programm abweisen, und das wäre im Sprachstandard auch so definiert.

von MaWin (Gast)


Lesenswert?

Nop schrieb:
> Die Motivation ist, daß lokale Variablen nicht automatisch
> initialisiert werden, weil das Laufzeit-Performance kosten würde,

Ein Relikt aus grauer Vorzeit.
Dass es so gut wie keinen Laufzeitzuwachs gibt, ist heute klar.
Das beweisen entsprechende Compileroptionen, die automatics immer 
initialisieren und somit diese UB entfernen.
Und das beweisen auch moderne Sprachen wie Rust.

Heute sollte man eher den Ansatz verfolgen in Sprachen per default alles 
safe zu designen und dann für rare Ausnahmefälle Ausnahmen schaffen 
(vgl. unsafe-Rust).

von Rolf M. (rmagnus)


Lesenswert?

Philipp Klaus K. schrieb:
> 1) Sachen, die eigentlich Fehler sind, aber sich im Allgemeinen zur
> Compilezeit nicht erkennen lassen (meist weil die Frage, ob sie
> auftreten, äquivalent zum Halteproblem ist). Hier soll eine für manche
> Implementierungen (of µC) teure Fehlererkennung zur Laufzeit nicht
> vorgeschrieben werden, um die Effizienz nicht zu beinträchtigen. Das
> undefinierte Verhalten erlaubt Implementierungen natürlich zu versuchen,
> manchmal Fehler zur Compilezeit oder zur Laufzeit zu melden.
>
> 2) Sachen, bei denen es unübersichtlich viele sinnvolle Möglichkeiten
> gibt, sie umzusetzen. Hier soll die Freiheit der Implementierungen nicht
> eingeschänkt werden.

Das ist dann aber eher unspecified oder implementation-defined. 
Undefined heißt, dass irgendwas passieren darf und ab dieser Stelle im 
Programm keinerlei Regeln mehr gelten. In diesen Fällen will man aber 
eher schon ein zwar nicht vom Standard festgezurrtes, aber doch 
deterministisches und in irgendeiner Form sinnvolles Verhalten.

> Meist geht es hier um die Interaktion des C-Programms mit seiner Umgebung,
> z.B. Bibliotheksfunktionen, deren Funktionssignatur standardisiert ist, die
> aber etwas systemspezifisches machen.

Sie sollen sich systemspezifisch verhalten, aber nicht undefiniert.

> Zu 2) Wenn es nur eine überschaubare Anzahl sinnvoller Möglichkeiten
> gäbe würde man hier stattdessen implementierungsabhängiges Verhalten
> verwenden (und in den Standard eine Liste dieser Möglichkeiten
> aufnehmen, während die Implementierung dokumentieren müsste, welche
> davon sie umsetzt).

implementation-defined heißt nicht zwangsläufig, dass eine endliche 
Liste aller Möglichkeiten aufgezählt wurde. Es heißt nur, dass der 
Compiler ein Verhalten wählen und dokumentieren muss.

von Stefan F. (Gast)


Lesenswert?

MaWin schrieb:
> Heute sollte man eher den Ansatz verfolgen in Sprachen per default alles
> safe zu designen und dann für rare Ausnahmefälle Ausnahmen schaffen

So ist es ja auch. C stammt aus einem anderen Jahrhundert.

von Rolf M. (rmagnus)


Lesenswert?

MaWin schrieb:
> Nop schrieb:
>> Die Motivation ist, daß lokale Variablen nicht automatisch
>> initialisiert werden, weil das Laufzeit-Performance kosten würde,
>
> Ein Relikt aus grauer Vorzeit.
> Dass es so gut wie keinen Laufzeitzuwachs gibt, ist heute klar.
> Das beweisen entsprechende Compileroptionen, die automatics immer
> initialisieren und somit diese UB entfernen.

Du meinst … durch definiertes, aber immer noch ggf. fehlerhaftes 
Verhalten zu ersetzen. Mir ist es da lieber, wenn ich durch eine Meldung 
darauf aufmerksam gemacht werde, wenn eine Variable genutzt wird, die 
noch gar keinen Wert bekommen hat, als wenn sie einfach mit einem zwar 
definierten, aber ggf. nicht gewünschten Wert vorbelegt wird. gcc warnt 
mich in den meisten Fällen bei so etwas.

> Heute sollte man eher den Ansatz verfolgen in Sprachen per default alles
> safe zu designen und dann für rare Ausnahmefälle Ausnahmen schaffen
> (vgl. unsafe-Rust).

safe ist für mich, wenn der Compiler keine Annahmen darüber trifft, was 
ich vielleicht wollen könnte.

von Nop (Gast)


Lesenswert?

MaWin schrieb:

> Ein Relikt aus grauer Vorzeit.
> Dass es so gut wie keinen Laufzeitzuwachs gibt, ist heute klar.

Das kommt auf das Programm an.

> Und das beweisen auch moderne Sprachen wie Rust.

Nein. Rust initialisiert lokale Variablen nicht automatisch, sondern 
weist den uninitialisierten Zugriff stattdessen mit einem Compile-Fehler 
ab. Das kostet ebenfalls keine Laufzeit, erspart einem die längliche 
Fehlersuche, und man findet solche Fehler obendrein zuverlässig und 
nicht nur, wenn im Speicher zufällig Werte stehen, die zu erkennbar 
fehlerhaftem Programmablauf führen.

von MaWin (Gast)


Lesenswert?

Rolf M. schrieb:
> als wenn sie einfach mit einem zwar
> definierten, aber ggf. nicht gewünschten Wert vorbelegt wird.

Richtig.
Deshalb bricht der Compiler von Rust ja auch ab, wenn kein expliziter 
default-Wert gefordert wird.

> safe ist für mich, wenn der Compiler keine Annahmen darüber trifft, was
> ich vielleicht wollen könnte.

Meine volle Zustimmung.
Deshalb ist C mit UB Mist.
UB ist die Annahme, dass man ebenjenes UB-Konstrukt nicht verwendet.

von Nop (Gast)


Lesenswert?

Rolf M. schrieb:

> Undefined heißt, dass irgendwas passieren darf und ab dieser Stelle im
> Programm keinerlei Regeln mehr gelten.

Nicht erst ab dieser Stelle, sondern das komplette Programm als Ganzes. 
Das macht die Fehlersuche ja mitunter so "lustig".

von MaWin (Gast)


Lesenswert?

Nop schrieb:
> Das kommt auf das Programm an.

Genau.
Und deshalb sollte man solche Programme, wo es darauf ankommt, zum 
Sonderfall machen.

>> Und das beweisen auch moderne Sprachen wie Rust.
>
> Nein. Rust initialisiert lokale Variablen nicht automatisch

Ja. Aber Rust zwingt den Programmierer zur Initialisierung, auch wenn 
das mal nicht nötig sein sollte.  z. B. bei Arrays, die im weiteren 
Programmverlauf dann wieder überschrieben werden, bevor sie gelesen 
werden.

von Nop (Gast)


Lesenswert?

MaWin schrieb:
>  z. B. bei Arrays, die im weiteren
> Programmverlauf dann wieder überschrieben werden, bevor sie gelesen
> werden.

Da braucht es keine Initialisierung, weil das "zweite" Beschreiben eine 
Initialisierung ist. Das gilt aber natürlich nur dann, wenn nicht nur 
teilweise beschrieben wird.

von MaWin (Gast)


Lesenswert?

Nop schrieb:
> Das gilt aber natürlich nur dann, wenn nicht nur
> teilweise beschrieben wird.

Ja eben. Das war mein Beispiel.

von Nop (Gast)


Lesenswert?

MaWin schrieb:

> Ja eben. Das war mein Beispiel.

Wenn die Überschreiblänge sich erst zur Laufzeit ergibt, aber das Lesen 
auch auf dem Rest passieren könnte, würde man auch in C ein memset 
reinsetzen. Der Vorteil von Rust ist dabei nicht automatische 
Initialisierung, sondern daß der Compiler statt einer je nach Compiler 
optional zuschaltbaren Warnung gleich einen Fehler wirft, was in der Tat 
das sinnvollere Verhalten ist.

von MaWin (Gast)


Lesenswert?

Nop schrieb:
> aber das Lesen auch auf dem Rest passieren könnte

Das habe ich nicht geschrieben.

von Nop (Gast)


Lesenswert?

MaWin schrieb:
> Nop schrieb:
>> aber das Lesen auch auf dem Rest passieren könnte
>
> Das habe ich nicht geschrieben.

Sonst ist es aber auch kein undefiniertes Verhalten - und auch in Rust 
darfst Du uninitialisierte Variablen gleich im Dutzend haben. Du darfst 
nur nicht lesend darauf zugreifen.

von Einer K. (Gast)


Lesenswert?

Hier mal eine Anekdote zu implementation defined und Pointern.

Zudem zeigt es, dass ein Zeiger auf char eben nicht das gleiche ist wie 
ein char Array.
Die jeweiligen Zufgriffsmöglichkeiten sind äquivalent, aber nicht die 
Definitionen.


Gegeben AVR-Gcc gnu++17
1
char *test1  = "ein x"; // bedenklich
2
char test2[] = "ein x"; // alles gut

Später dann Manipulationen:
1
*(test1+4) = 'u'; // bedenklich
2
*(test2+4) = 'u'; // alles gut
3
4
test1[3] = '-'; // bedenklich
5
test2[3] = '-'; // alles gut

Alles funktioniert, wie es soll!

Schaut man aber in die Spezifikation, dann ist
> char *test1  = "ein x";
Implementation Defined.
Das heißt, dass spätere Manipulationen des Strings nicht so 
funktionieren müssen, wie man das erwartet.
Klarer test1[3] = '-' kann auch auf anderen Systemen funktionieren, muss 
aber nicht, könnte z.B. auch eine Speicherschutzverletzung werfen....


Aktiviert man alle Warnungen, sagt einem der Gcc
1
E:\Programme\arduino\portable\sketchbook\sketch_apr05a\sketch_apr05a.ino:11:15: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
2
   11 | char *test1 = "ein x";
3
      |
Das sollte einen schon stutzig machen!

Richtig ist es so:
1
const char *test1  = "ein x";
Ein Zeiger auf einen konstanten String

Oder gar so:
1
const char *const test1  = "ein x";
Ein konstanter Zeiger auf einen konstanten String

Es ist also durchaus möglich auf das "implemtation defined" angemessen 
zu reagieren.

Nötig ist dafür:
Etwas Wissen um die Sprache.
Etwas Disziplin und Sorgfalt.

von Stefan F. (Gast)


Lesenswert?

Du hast gerade C mit C++ verwechselt.

von Einer K. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Du hast gerade C mit C++ verwechselt.
Nein, das habe ich nicht.

Sogar knallhart extra dabei geschrieben.
Arduino Fanboy D. schrieb:
> Gegeben AVR-Gcc gnu++17

Zudem verhält sich der Gcc  C und der C++ Kompiler an der Stelle 
identisch.
(mal abgesehen von der Warnung)


Aber das passt ja nicht in deine Vorstellungswelt.

---------

Eigentlich ist es sogar noch schlimmer:
1
#include <Streaming.h> // die Lib findest du selber ;-)
2
3
void setup() 
4
{
5
  Serial.begin(9600);
6
  
7
  char *t1 = "Beispiel";
8
  char *t2 = "Beispiel";
9
  
10
  t2[0] = '*';
11
  
12
  Serial << F("t1: ") << t1 << endl;
13
  Serial << F("t2: ") << t2 << endl;
14
}
15
16
void loop() 
17
{
18
19
}

Zeigt folgende Ausgabe:
1
t1: *eispiel
2
t2: *eispiel
t1 und t2 zeigen auf den gleichen Speicherbereich.

Auch hier, C und C++ identisches Verhalten.

von Stefan F. (Gast)


Lesenswert?

Ich wusste nicht dass wir hier Pointer von C++ diskutieren. Dachte du 
seist versehentlich dorthin abgedriftet.

Beitrag #6645150 wurde von einem Moderator gelöscht.
von Einer K. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich wusste nicht dass wir hier Pointer von C++ diskutieren.
Ja, mit dem Denken, daran haperts manchmal....

von Philipp Klaus K. (pkk)


Lesenswert?

Rolf M. schrieb:
>>
>> 2) Sachen, bei denen es unübersichtlich viele sinnvolle Möglichkeiten
>> gibt, sie umzusetzen. Hier soll die Freiheit der Implementierungen nicht
>> eingeschänkt werden.
>
> Das ist dann aber eher unspecified oder implementation-defined.
> Undefined heißt, dass irgendwas passieren darf und ab dieser Stelle im
> Programm keinerlei Regeln mehr gelten. In diesen Fällen will man aber
> eher schon ein zwar nicht vom Standard festgezurrtes, aber doch
> deterministisches und in irgendeiner Form sinnvolles Verhalten.
>

Nicht notwendigerweise. Z.B. hat N2464 undefiniertes Verhalten für 
realloc mit size 0 eingeführt, weil man sah dass Implementierungen hier 
so sehr divergieren, dass implementierungsabhängiges Verhalten hier 
nicht mehr sinnvoll wäre. N2464 wurde von WG14 einstimmig angenommen (16 
Ja 0 Nein 0 Enthaltung).

>> Meist geht es hier um die Interaktion des C-Programms mit seiner Umgebung,
>> z.B. Bibliotheksfunktionen, deren Funktionssignatur standardisiert ist, die
>> aber etwas systemspezifisches machen.
>
> Sie sollen sich systemspezifisch verhalten, aber nicht undefiniert.

Undefiniert im C-Standard, um die Definition anderen Standards, z.b. 
POSIX zu überlassen. Auf dem konkreten System, im Programm dann also 
kein undefiniertes Verhalten, aber eben einer der ca 200 Fälle 
undefinierten Verhaltens im C-Standard.

von mh (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Schaut man aber in die Spezifikation, dann ist
>> char *test1  = "ein x";
> Implementation Defined.
Ich vermute, du meinst den Standard mit "Spezifikation"? Wo genau sagt 
er, dass hier etwas implementation defined ist?

> Das heißt, dass spätere Manipulationen des Strings nicht so
> funktionieren müssen, wie man das erwartet.
> Klarer test1[3] = '-' kann auch auf anderen Systemen funktionieren, muss
> aber nicht, könnte z.B. auch eine Speicherschutzverletzung werfen....
Du kommst zu richtigen Ergebnis ... der Weg ist aber falsch.

von A. S. (Gast)


Lesenswert?

Nop schrieb:
> Rust initialisiert lokale Variablen nicht automatisch, sondern weist
> den uninitialisierten Zugriff stattdessen mit einem Compile-Fehler ab.

Ein Compiler kann das nicht (sicher) erkennen.  Sonst würden Warnungen 
ja auch reichen.

von MaWin (Gast)


Lesenswert?

A. S. schrieb:
> Ein Compiler kann das nicht (sicher) erkennen.

Ja doch, natürlich.
Man muss die Sprache nur vernünftig definieren.

von Einer K. (Gast)


Lesenswert?

mh schrieb:
> Ich vermute, du meinst den Standard mit "Spezifikation"?
Ok, falsche Wort verwendet....

Ich meinte: Referenz!


Meine Referenz sagt:
> whether string literals are distinct is implementation-defined

Oder auch in neuerer Fassung:
> distinctness is unspecified,
> and same string literal can yield different object

Zudem auch noch:
> Attempting to modify a string literal results in
> undefined behavior: they may be stored in read-only storage
> (such as .rodata) or combined with other string literals

von mh (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
[...]

Keins deine Zitate aus dieser Referenz sagt, dass die Zeile ID ist.

von Philipp Klaus K. (pkk)


Lesenswert?

Nop schrieb:
> Philipp Klaus K. schrieb:
>
>> Tatsächlich ist die Möglichkeit, Fehler zu erkennen auch eine Motivation
>> für undefiniertes Verhalten:
>
> Nein. Die Motivation ist, daß lokale Variablen nicht automatisch
> initialisiert werden, weil das Laufzeit-Performance kosten würde, sobald
> der automatische Initialisierungswert (z.B. 0) nicht das ist, was
> gebraucht wird.

Doch. Erst auf der letzten WG14-Sitzung wurde wieder einmal die Frage 
diskutiert, was der nächste C-Standard (hier C23) zum Lesen nicht 
initalisierter Variablen sagen soll. Die Diskussion findet sich im 
vorläufigen Protokoll N2690 in Abschnitt 5.10.

von Einer K. (Gast)


Lesenswert?

mh schrieb:
> Arduino Fanboy D. schrieb:
> [...]
>
> Keins deine Zitate aus dieser Referenz sagt, dass die Zeile ID ist.
Die Zitate zeigen, dass es dem Compiler überlassen bleibt wie er mit dem 
String literal umgeht, wie und wo er es im Speicher anlegt.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Bei der ganzen Diskussion um das undefined Behavior sollte man sich auch
vor Augen halten, dass die Liste der UBs im Standarddokument eine
Besonderheit von C und C++ ist.

In den Sprachdefinitionen der meisten anderen Programmiersprachen ist
diese Liste entweder gar nicht vorhanden oder sehr unvollständig. Dort
ist einfach alles undefined, was nicht explizit defined ist. Das ist
auch völlig in Ordnung, hat halt nur den Nachteil, dass sich die UBs
nicht so schön nachzählen lassen wie in C ;-)

Des Weiteren gibt es für die meisten Programmiersprachen gar keine
ISO-Norm. Stattdessen gibt es eine mehr oder weniger vollständige
Sprachdefinition der Entwickler der Sprache und zusätzlich oft noch
einen Referenzcompiler, der zu Rate gezogen werden kann, wenn etwas in
der Sprachdefinition unklar ist. So macht der Referenzcompiler aus
manchem undefined Behavior ein "de facto defined Behavior".

C ist erst standardisiert worden, nachdem es schon eine Vielzahl von
Compilern gab, die die nicht allzu präzise Sprachdefinition von K&R mit
viel Ermessensspielraum umgesetzt haben. Vor diesem Hintergrund
erscheint es es durchaus sinnvoll, dass einige ohnehin fragwürdige
Konstrukte, die in den existierenden Compilern auf untereinander
inkompatible Art und Weise implementiert waren, nicht zugunsten eines
bestimmten Compilers oder einer bestimmten Prosessorarchitektur
festgelegt, sondern stattdessen explizit als undefined Behavior verboten
wurden.

von A. S. (Gast)


Lesenswert?

MaWin schrieb:
> Ja doch, natürlich.
> Man muss die Sprache nur vernünftig definieren.

Du meinst, man muss notfalls doppelt halt initialisieren, einmal fürs 
Programm und vorher für den Compiler? Oder wie machst Du das?

von MaWin (Gast)


Lesenswert?

A. S. schrieb:
> Du meinst, man muss notfalls doppelt halt initialisieren

Richtig. In der Praxis kommt das selten genug vor, dass es keine Rolle 
für die Performance spielt, oder man Ausnahmen regeln kann, für die 
wenigen Stellen, an denen es dann doch stören würde.

von Yalu X. (yalu) (Moderator)


Lesenswert?

MaWin schrieb:
> Man muss die Sprache nur vernünftig definieren.

Wenn man an C ohne Rücksicht auf die Abwärtskompatibilität beliebig
herumdefinieren könnte, wäre es IMHO am sinnvollsten, Variablen nicht
automatisch, sondern zwingend direkt bei ihrer Definition durch den
Programmierer zu initialisieren. Dann ist es auch für den dümmsten
Compiler ganz leicht zu erkennen, wenn eine Initialisierung fehlt.

Doppelte Initialisierungen können dadurch vermeiden werden, dass
Variablen am Ort ihrer ersten Verwendung definiert werden, was sowieso
guter Stil ist.

Die Fälle, wo eine doppelte Initialisierung unvermeidbar ist, dürften so
selten sein, dass sie performanzmäßig kaum ins Gewicht fallen. Durch die
Einführung weiterer Sprachkonstrukte könnte auch diese Fälle erschlagen.

von Philipp Klaus K. (pkk)


Lesenswert?

Yalu X. schrieb:

>
> Die Fälle, wo eine doppelte Initialisierung unvermeidbar ist, dürften so
> selten sein, dass sie performanzmäßig kaum ins Gewicht fallen. Durch die
> Einführung weiterer Sprachkonstrukte könnte auch diese Fälle erschlagen.

Bei einem einfachen Compiler wie SDCC sieht das anders aus:
1
void f(void)
2
{
3
  char buffer[2048] = {0}; // Von dir vorgeschlagene erforderliche Initalisierung
4
  init_buffer(buffer);
5
  
6
}

Da bräuchte es schon einiges an Link-Time-Optimization, damit der 
Compiler hier die Initialisierung des Buffers herausoptimieren kann, und 
bei der Größe des Buffers kann es sich durchaus in der Performanz 
deutlich bemerkbar machen.

von mh (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> mh schrieb:
>> Arduino Fanboy D. schrieb:
>> [...]
>>
>> Keins deine Zitate aus dieser Referenz sagt, dass die Zeile ID ist.
> Die Zitate zeigen, dass es dem Compiler überlassen bleibt wie er mit dem
> String literal umgeht, wie und wo er es im Speicher anlegt.
Das ist aber nicht das, was du ursprünglich geschrieben hast.

Yalu X. schrieb:
> Die Fälle, wo eine doppelte Initialisierung unvermeidbar ist, dürften so
> selten sein, dass sie performanzmäßig kaum ins Gewicht fallen.
Das hört sich super an ... aber gibt es dazu irgendwelche handfesten 
Daten, um das so pauschal sagen zu können? Es ist ja nicht nur das "wie 
oft" sondern es ist auch das "wann" und "wieviel" relevant.

von A. S. (Gast)


Lesenswert?

Philipp Klaus K. schrieb:
> Da bräuchte es schon einiges an Link-Time-Optimization, damit der
> Compiler hier die Initialisierung des Buffers herausoptimieren kann, und
> bei der Größe des Buffers kann es sich durchaus in der Performanz
> deutlich bemerkbar machen.

Und jetzt werden die Verfechter "richtiger" Programmiersprachen wieder 
Workarounds für ihre Anwendungsfälle zeigen und warum man "das alles 
sowieso ganz anders macht".

Das wirklich gute (und zuverlässige) an C ist, dass es eben nicht besser 
wird. Jeder weiß, was besser wäre, doch viele Köche (hier Anforderungen) 
verderben den Brei. Für andere Aufgaben (Web, OOP, ...) gibt es ja 
Alternativen.

von Rolf M. (rmagnus)


Lesenswert?

Arduino Fanboy D. schrieb:
> Schaut man aber in die Spezifikation, dann ist
>> char *test1  = "ein x";
> Implementation Defined.

Das string literal "ein x" ist vom Typ Array[6] aus const char, daher 
ruft das Schreiben dorthin undefiniertes Verhalten hervor. C++ hat hier 
nur aus Gründen der Kompatibilität zu alten Programmen diesen 
Spezialfall zugelassen - normalerweise kann man ein const nicht auf 
diese Weise ohne explizite Konvertierung entfernen.
Bei deinem Array passiert nichts, weil es nicht const ist und nur mit 
dem Inhalt des Literals initialisiert wird. Das Array darf man daher 
überschreiben, so lange man nicht über das Ende hinaus schreibt.

Philipp Klaus K. schrieb:
>>> Meist geht es hier um die Interaktion des C-Programms mit seiner Umgebung,
>>> z.B. Bibliotheksfunktionen, deren Funktionssignatur standardisiert ist, die
>>> aber etwas systemspezifisches machen.
>>
>> Sie sollen sich systemspezifisch verhalten, aber nicht undefiniert.
>
> Undefiniert im C-Standard, um die Definition anderen Standards, z.b.
> POSIX zu überlassen.

Hast du mal ein konkretes Beispiel dafür, wo das so ist?

Philipp Klaus K. schrieb:
> Bei einem einfachen Compiler wie SDCC sieht das anders aus:
> void f(void)
> {
>   char buffer[2048] = {0}; // Von dir vorgeschlagene erforderliche
> Initalisierung

Hier wird aber auch nur das erste Element explizit initialisiert. Da 
greift die Regel, dass, wenn mindestens ein Element explizit 
initialisiert ist, alle anderen implizit mit 0 initialisiert werden. 
Damit das alles explizit ist, müsste man schon 2048 mal die 0 
hinschreiben. Und wenn sich die Array-Größe ändert, jedes mal anpassen, 
was vor allem nervig wird, wenn die Größe sinnvollerweise irgendwo in 
einem Makro definiert ist.

: Bearbeitet durch User
von mh (Gast)


Lesenswert?

Rolf M. schrieb:
> Philipp Klaus K. schrieb:
>> Bei einem einfachen Compiler wie SDCC sieht das anders aus:
>> void f(void)
>> {
>>   char buffer[2048] = {0}; // Von dir vorgeschlagene erforderliche
>> Initalisierung
>
> Hier wird aber auch nur das erste Element explizit initialisiert. Da
> greift die Regel, dass, wenn mindestens ein Element explizit
> initialisiert ist, alle anderen implizit mit 0 initialisiert werden.
> Damit das alles explizit ist, müsste man schon 2048 mal die 0
> hinschreiben. Und wenn sich die Array-Größe ändert, jedes mal anpassen,
> was vor allem nervig wird, wenn die Größe sinnvollerweise irgendwo in
> einem Makro definiert ist.

Das hat wenig mit dem zu tun, was Philipp in seinem Beitrag geschrieben 
hat.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Philipp Klaus K. schrieb:
> Bei einem einfachen Compiler wie SDCC sieht das anders aus:
>
> void f(void)
> {
>   char buffer[2048] = {0}; // Von dir vorgeschlagene erforderliche 
Initalisierung
>   init_buffer(buffer);
>   …
> }

Das wäre einer der von mir erwähnten Ausnahmefälle. Das Ungeschickte bei
C ist, dass man als Initialisierungswerte nur Ergebnisse von Ausdrücken
verwenden kann und Arrays keine Rückgabewerte von Funktionen sein
können.

Um ein Array mittels eines Funktionsaufrufs mit Werten zu belegen, wird
(wie in deinem Beispiel) das Array üblicherweise als Argument an die
Funktion übergeben. Man bräuchte also (wie ich oben bereits andeutete)
ein weiteres Sprachkonstrukt, um Variablen auch per Funktionsaufruf mit
Call-by_Reference-Übergabe des Arrays initialisieren zu können.

Eine griffige Syntax fällt mir dazu auf die Schnelle nicht ein. Das
folgende Beispiel mit dem neuen Schlüsselwort init_by ist ein erster,
holpriger Versuch, der ausschließlich dazu dient, das Prinzip zu
verdeutlichen:

1
char buffer[1024] init_by init_buffer(buffer);

PS: Um kein neues Schlüsselwort einführen zu müssen, könnte man init_by
auch durch etwas bereits Existierendes wie bspw. "do" oder "->"
ersetzen, das innerhalb einer Deklaration noch keine Bedeutung hat:

1
char buffer[1024] do init_buffer(buffer);

: Bearbeitet durch Moderator
von Rolf M. (rmagnus)


Lesenswert?

mh schrieb:
> Das hat wenig mit dem zu tun, was Philipp in seinem Beitrag geschrieben
> hat.

Gut erkannt.

von Philipp Klaus K. (pkk)


Lesenswert?

Rolf M. schrieb:

>>>
>>> Sie sollen sich systemspezifisch verhalten, aber nicht undefiniert.
>>
>> Undefiniert im C-Standard, um die Definition anderen Standards, z.b.
>> POSIX zu überlassen.

Das undefinierte Verhalten beim Ändern des von getenv zurückgegebenen 
Strings wird von POSIX genutzt, um das Verhalten zu definieren, wenn es 
ich um einen vorher per putenv hinzugefügten handelt.

Aber in den meisten Fällen, in denen man anderen Standards wie POSIX 
Freiheit geben will, wird das unspezifiziertes statt über undefiniertes 
Verhalten gemacht.

von Philipp Klaus K. (pkk)


Lesenswert?

Johannes schrieb:
> Viel entscheidender ist, dass Arrayzugriffe in C keine "Arrayzugriffe"
> sind, sondern simple Pointerarithmetik. Es gibt keine Prüfung auf
> Indexverletzungen und damit hast du einfach ein Einfallstor für Fehler.

Beim Zugriff auf das Arrayelement außerhalb der Grenzen gibt es 
undefiniertes Verhalten. Somit hat die C-Implementierung die Freiheit, 
dieses undefinierte Verhalten für eine Überprüfung zu nutzen.
Wer diese Überprüfung will, kann das bei GCC und LLVM  per 
-fsanitize=array-bounds machen.
Auch für andere Fälle undefinierten Verhaltens, die sich erst zur 
Laufzeit erkennen lassen, bieten Implementierungen oft entsprechende 
Möglichkeiten.

von Cyblord -. (cyblord)


Lesenswert?

Philipp Klaus K. schrieb:

> Beim Zugriff auf das Arrayelement außerhalb der Grenzen gibt es
> undefiniertes Verhalten. Somit hat die C-Implementierung die Freiheit,
> dieses undefinierte Verhalten für eine Überprüfung zu nutzen.
> Wer diese Überprüfung will, kann das bei GCC und LLVM  per
> -fsanitize=array-bounds machen.
> Auch für andere Fälle undefinierten Verhaltens, die sich erst zur
> Laufzeit erkennen lassen, bieten Implementierungen oft entsprechende
> Möglichkeiten.

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.

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.