Autor Beitrag
GuaAck
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 378
Erhaltene Danke: 32

Windows 8.1
Delphi 10.4 Comm. Edition
BeitragVerfasst: Mi 06.05.15 22:19 
Liebe C-Experten,

wenn ich wüsste, nach welchem Stichwort ich suchen soll, dann würde ich nicht fragen, schon der Betreff viel mir schwer. Ich bin Pascaler und muss nur gelegentlich und behelfsweise ein paar Zeilen C-Code machen.

Also:
Ich deklarierere eine Funktion und will diese dann aufrufen:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
void Reduzieren()
{
...
}

void Machewas()
{
... 
Reduzieren;
...
}


Mein Compiler ist zufrieden, aber die Funktion "Reduzieren" wird nicht durchlaufen. Ich muss schreiben "Reduzieren()", dann geht es. Ist das eine Macke meines C-Compilers oder falls nicht, was ist der Sinn, dass er es erlaubt? Hat mich jedenfalls Stunden gekostet, den Fehler zu finden.

Kein Problem mehr, aber ich würde es gerne verstehen.

Gruß Guaack
Stundenplan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 128
Erhaltene Danke: 32

Win 7
Delphi 7 Pers., C# (VS 2010 Express)
BeitragVerfasst: Mi 06.05.15 22:52 
Ein Methodenname allein ist in C-Sprachen meist nur der Bezeichner für diese Methode, aber noch kein Aufruf. Wenn du die Methode Reduzieren als Parameter übergeben wölltest, sähe das so aus: MyMethod(Reduzieren);
Oder eine Variablenzuweisung: myVar = Reduzieren; // kein Aufruf von Reduzieren!
Um den potentiellen Rückgabewert von Reduzieren zuzuweisen, müsstest du myVar = Reduzieren(); schreiben.

Ein Aufruf hingegen verlangt in C-Sprachen immer die Klammern, auch wenn die Parameterliste leer ist.
Somit ist immer eindeutig, ob du einen Methodenaufruf oder einfach nur die Methode selbst meinst.
C#
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 561
Erhaltene Danke: 65

Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
BeitragVerfasst: Mi 06.05.15 22:55 
Hey,

der Compiler macht da nix falsch. In C sind Methodennamen Pointer. Wenn du also
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
void Reduzieren()
{
...
}

void Machewas()
{
... 
Reduzieren; // ist ein Pointer
...
}

schreibst, ohne die Klammern dran zu hängen, wird eine Kopie des Pointers - der auf Reduzieren zeigt - erstellt und gleich wieder verworfen, das ist legal in C.
Das hat den Grund, dass du bei manchen Funktionen Funktionszeiger als Argument übergeben kannst. Ein Beispiel (in C++, C bin ich mir nicht sicher) wäre Multithreading. Dort wird die Funktion selbst als Argument übergeben:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
#include <thread>

using namespace std;

void TuWas(int wert)
{
    ...
}

void main()
{
    thread t(TuWas, 4); // TuWas wird in neuem thread gestartet
}


In C ist es z.B. auch legal sowas zu schreiben:
ausblenden C#-Quelltext
1:
2:
int a = 4;
a;

a wird ausgewertet und das Ergebnis gleich wieder verworfen.

// EDIT
War wohl zu langsam :mrgreen:

// EDIT 2
Hab nochmal nachgeschaut, thread wird erst ab C++ 11 unterstützt. Aber als Beispiel sollte es trotzdem taugen.

_________________
Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler

Für diesen Beitrag haben gedankt: GuaAck
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 06.05.15 23:06 
Zitat:
a wird ausgewertet und das Ergebnis gleich wieder verworfen.


Wobei das eine exclusive Eigenschaft von c/c++. Die Compiler jeder anderen c-artige Sprache (die ich kenne) haben dazu gelernt und würden merken das der Ausdruck weder eine Zuweisung noch ein Aufruf ist und das ablehnen. Eine Methode als Typ darf dort nur Teil einer Zuweisung sein (rechte Seite) oder als Parameter eines Methodenaufrufs dienen.
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 431
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: Mi 06.05.15 23:09 
> der Compiler macht da nix falsch. In C sind Methodennamen Pointer.

Das ist die Sache.

In C ist fast alles ein Ausdruck, dessen Ergebnis nicht zwangsläufig verwendet werden muß.

Wenn Du schreibst

MachWas;

liefert das die Adresse der Funktion MacheWas. Und die wird nicht verwendet - also ignoriert.

Wenn Du schreibst

MachWas ();

Wird die Funktion aufgerufen, weil () der Funktionsaufrufoperator ist - er bekommt das was links von ihm steht und was innerhalb der Klammern ist.
Was in den Klammern ist "wertet er aus" und übergibt diese Daten an die Funktion, deren Adresse er weiß weil der Name links von ihm steht.

Ist eben ein anderes Denkmodell als bei Pascal.
Allerdings können in neueren Delphi-Versionen Funktionen nicht nur mittels Machwas sondern auch per MachWas() aufgerufen werden wenn sie keine Parameter erwarten - wurde wohl eingeführt um ein bischen C-Like zu ermöglichen.

Exkurs:
In C ist auch folgendes möglich:

A=B=C=0;


Abgearbeitet wird es als: A=(B=(C=0)))

"=" ist der Zuweisungsoperator. Vereinfacht gesagt bekommt er die Speicheradresse von C (links von ihm) geliefert und den Wert 0 (rechts). Also schreibt er den Wert 0 an die Speicherstelle an der die Variable C ist.
Als Ergebnis liefert der Zuweisungsoperator den zuzuweisenden Wert (also 0).
Deshalb wird B auch die 0 zugewiesen, ebenso A.

Für diesen Beitrag haben gedankt: GuaAck
C#
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 561
Erhaltene Danke: 65

Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
BeitragVerfasst: Mi 06.05.15 23:31 
Zitat:
Exkurs:
In C ist auch folgendes möglich:

A=B=C=0;


Das geht auch in C#

_________________
Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 431
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: Mi 06.05.15 23:32 
Das geht auch in C#

Davon ging ich aus
GuaAck Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 378
Erhaltene Danke: 32

Windows 8.1
Delphi 10.4 Comm. Edition
BeitragVerfasst: Do 07.05.15 22:18 
Danke an alle, alle Beiträge haben mir für ein Verständnis genützt.

Die überraschend intensive Diskussion dazu hat mich überrascht - ist wohl jeder mal in die Falle getappt. Ein Kollege gab mir vorhin den Tipp, dass man bei vielen Compilern als Option "Alle Warnungen" einstellen kann, werde ich mal suchen.

Danke nochmals,
GuaAck
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 431
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: Do 07.05.15 23:47 
> Die überraschend intensive Diskussion dazu hat mich überrascht

na, so intensiv war das doch gar nicht

> dass man bei vielen Compilern als Option "Alle Warnungen" einstellen kann, werde ich mal suchen.

Meine letzen echten Erfahrungen mit C liegen 20 Jahre zurück. Soweit ich aber weiß,
hat diese Option auch damals schon gewarnt und war hilfreich.

Eins fällt mir aber noch ein wenn Du als Pascaler Dich in C-Gefilde verirren mußt:

Sei vorsichtig bei Sachen folgender Art:


if (a=5)
{
.. mach nochwas
}

Wie ich oben schon schrieb, in C ist fast alles ein Ausdruck:

"=" ist der Zuweisungsoperator.

Also: a=5 weist der Variablen a den Wert 5 zu. Das IF bekommt das Ergebnis 5. Dies ist ungleich 0 und damit immer wahr.

Gemeint ist eigentlich immer:

if (a == 5) ..

Einstellbare Warnungen des Compilers schreien hier korrekt.

Oftmals wird geraten derartige Vergleiche immer in der Form:

if (5==a)

zu schreiben. Wenn man sich nämlich vertut und nur "=" schreibt gibt es einen echten Fehler : man kann den Wert von a nicht der Konstanten 5 zuweisen.

Weiter oben schrieb Ralf Jansen daß dies exklusive Eigenschaft von C/C++ Compilern sei.
Aufgrund der Abstammung von PHP haben wir dort aber auch fast alle Probleme der Herkunft geerbt, auch wenn PHP interpretieret.
Geprüft habe ich es jetzt nicht, es kann sein, daß PHP bei "machwas;" meckert. bei "if (a=5)" tut es das jedoch nicht..

LG
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Sa 09.05.15 22:31 
Mit dem clang-Compiler bekommst du übrigens folgende Warnung:

Zitat:
8 : warning: expression result unused [-Wunused-value]

test;
^~~~


Davon abgesehen kompiliert C-Code eigentlich "zu leicht" - gewisse Fehler äußern sich dann eben doch erst zur Laufzeit. Ich habe schonmal in C++ versucht, ein 2D-Array mit Arr[2,3] zu indizieren. Hat auch compiliert. Macht aber nicht das, was es soll. :roll: