Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Frage zu Func.-Ptr und ANSI

0 views
Skip to first unread message

Götz Borkowski

unread,
Apr 20, 1998, 3:00:00 AM4/20/98
to

Hallo,

Im Zusammenhang mit einer Quellcodeanalyse ergab sich folgende Frage zur
Handhabung (Deref.) von Zeigern auf Funktionen:

Im untenstehenden Programm wird /lfunction ()/ dreimal per
Pointer-Dereferenzierung aufgerufen ( # 1 - 3 ); in verschiedener Schreibweise.

Meines Wissens ist nur Schreibweise #2 ANSI-zulässig.

/PURE C, GNU C und Microtec C/ (letzteres in der Industrie verwendet) verdauen
alle Aufrufe klaglos: Es wird die Funktion gerufen; keine bizarren Effekte.


*Frage:*
Sind Schreibweisen #1 und #3 evtl. /doch/ ANSI und damit /portabel?/

Wer weiß Definitives?????

Gruß Götz


Hier ist das (unglaublich komplexe) Softwarepaket:


typedef long (*funcp) ( int zahl );

long lfunction ( int zahl );


int main ( void )
{
funcp fptr;
long lzahl;


fptr = lfunction;

lzahl = (fptr) ( (int) 1234 ); /* #1 */
lzahl = (* fptr) ( (int) 48 ); /* #2 */
lzahl = fptr ( (int) 33 ); /* #3 */

return 0;

}


long lfunction ( int zahl )
{
return ((long) zahl) * 2L;
}

Jochen Schoof

unread,
Apr 24, 1998, 3:00:00 AM4/24/98
to

On Mon, 20 Apr 1998 22:53:00 +0200, =?ISO-8859-1?Q?G=F6tz_Borkowski?= wrote:
:
: Im untenstehenden Programm wird /lfunction ()/ dreimal per

: Pointer-Dereferenzierung aufgerufen ( # 1 - 3 ); in verschiedener Schreibweise.
:
: Meines Wissens ist nur Schreibweise #2 ANSI-zulässig.
:
: /PURE C, GNU C und Microtec C/ (letzteres in der Industrie verwendet) verdauen
: alle Aufrufe klaglos: Es wird die Funktion gerufen; keine bizarren Effekte.
:
: *Frage:*
: Sind Schreibweisen #1 und #3 evtl. /doch/ ANSI und damit /portabel?/
:
: lzahl = (fptr) ( (int) 1234 ); /* #1 */

: lzahl = (* fptr) ( (int) 48 ); /* #2 */
: lzahl = fptr ( (int) 33 ); /* #3 */

Sie sind. Zunaechst einmal sind #1 und #3 identisch, da die Klammern
in diesem Fall die Semantik nicht veraendern. Zur Erhoehung der Les-
barkeit erlaubt ANSI explizit, dass statt

(*fkt_ptr)(params,...);

einfach

fkt_ptr(params,...);

geschrieben wird. Am praegnantesten wird das in der "Rationale" zum
Standard (http://wwwwbs.cs.tu-berlin.de/~jutta/c/rat/title.html) in
Abschnitt 3.3.2.2 beschrieben:

Pointers to functions may be used either as (*pf)() or as pf().

Im weiteren wird sogar noch erlaeutert, dass auch beliebig viele De-
referenzierungen zulaessig sind, also z.B. (***pf)().

Im ISO-Standard selbst ist Abschnitt 6.3.2.2 einschlaegig, aber fuer
sich allein nicht so eindeitig (man muss noch zig andere Stellen be-
ruecksichtigen).

Gruss

- Jochen

PS: Die expliziten Casts auf int bei allen drei Aufrufen sind
ueberfluessig, da die Definition des Funktionszeiger-Typs
als Prototyp dient und die erforderlichen Casts implizit
garantiert.


--
Jochen Schoof (http://www-info2.informatik.uni-wuerzburg.de/staff/joscho)
___________________________________________________________________________
\_Address __/ Informatik II, Uni Wuerzburg, Am Hubland, D-97074 Wuerzburg
\_Email ___/ mailto:sch...@informatik.uni-wuerzburg.de

Marcus Ohlhaut

unread,
Apr 24, 1998, 3:00:00 AM4/24/98
to

>Sind Schreibweisen #1 und #3 evtl. /doch/ ANSI und damit /portabel?/

Ja. (fptr) ist äquivalent zu fptr genauso wie (x) zu x und
(((((3))))) zu 3.

*fptr ist äquivalent zu fptr, wenn fptr ein Funktionspointer ist.

Hope it helps,
- Marcus [PGP]

Sönke Müller-Lund

unread,
Apr 24, 1998, 3:00:00 AM4/24/98
to

Moin Götz,

> Meines Wissens ist nur Schreibweise #2 ANSI-zulässig.

es ist die einzige Schreibweise, die bei mir Kopfschmerzen erzeugt. Mir
ist nur #3 bekannt von der ich sicher bin, daß sie strikt ANSI ist.

> lzahl = (fptr) ( (int) 1234 ); /* #1 */
> lzahl = (* fptr) ( (int) 48 ); /* #2 */
> lzahl = fptr ( (int) 33 ); /* #3 */

Und wenn Du die absolut überflüssigen Casts weglassen würdest, wäre dieses
Segment auch lesbar.

Ciao
Sönke

Nur Deppen rappen!

Götz Borkowski

unread,
Apr 25, 1998, 3:00:00 AM4/25/98
to

Hallo,

SML>
SML>Und wenn Du die absolut überflüssigen Casts weglassen würdest, wäre
SML>dieses Segment auch lesbar.

--> Kicher...
Sag DAS mal den Jungs/Mädels, die die Programmierrichtlinien in großen
Konzernen verfassen.
Mir ist sowas auch ziemlich lästig, aber mit der Zeit gewöhnt man sich das dann
doch an... und machts dann im Privatleben auch.

Gruß Götz

Sönke Müller-Lund

unread,
Apr 27, 1998, 3:00:00 AM4/27/98
to

Moin Götz,

>> Und wenn Du die absolut überflüssigen Casts weglassen würdest, wäre

>> dieses Segment auch lesbar.

> --> Kicher...
> Sag DAS mal den Jungs/Mädels, die die Programmierrichtlinien in großen
> Konzernen verfassen.

sind das dieselben Leute, die Warnschilder schreiben, daß man einen
Fahrstuhl nicht benutzen sollte, wenn dieser brennt?

Joergen Von Bargen

unread,
Apr 27, 1998, 3:00:00 AM4/27/98
to

Moin!

SML>Und wenn Du die absolut überflüssigen Casts weglassen würdest, wäre
SML>dieses Segment auch lesbar.

GB>Sag DAS mal den Jungs/Mädels, die die Programmierrichtlinien in großen
GB>Konzernen verfassen.

Wenn Leute Programmierrichtlinien verfassen, die casts vorschreiben, wo keine
notwendig sind, dann gehören die meiner Meinung nach gefeuert.

Gruß JJvB

PS: Ich habe selbst mal welche für unsere Firma verfasst, aber so'n Schrott
kam da nicht rein.

Gerhard Bahr

unread,
Apr 28, 1998, 3:00:00 AM4/28/98
to

Hallo Götz,

SML>Und wenn Du die absolut überflüssigen Casts weglassen würdest, wäre
SML>dieses Segment auch lesbar.

GB>Sag DAS mal den Jungs/Mädels, die die Programmierrichtlinien in großen
GB>Konzernen verfassen.

Das mit den casts ist gar keine so einfache Sache. Wenn ich grundsätzlich
überall caste, dann sind Datentypen anscheinend egal. Ich versuche von
vorneherein die angemessenen Datentypen zu verwenden, so daß ein int auch immer

einem int zugewiesen wird. Wo das nicht geht (z.B. bestimmte Libraries, die ich

nun mal nicht ändern kann) da ist ein cast ein Muß).

Das (int)33 finde ich aber genauso überflüssig wie ein (long)33L, weil 33 ja
bereits ein int ist. Grundsätzlich alles zu casten finde ich sinnlos. Ein cast
heißt für mich hier hat sich der Programmierer etwas dabei gedacht, daß er z.B.

ein unsigned short auf ein unsigned char casted: er weiß, das er hier einige
bits unter den Tisch fallen läßt.

BTW, welche Programmierrichtlinien - wenn ihr denn danach arbeitet - findet ihr

hilfreich und welche nerven? Ich finde es z.B. ausgesprochen hilfreich, wenn
Makros immer GROSS geschrieben werden. Man weiss sofort, daß MAKRO(a++)
eventuell etwas unerwartetes liefern kann, weil es möglich ist, daß der
Ausdruck a++ mehrfach ausgewertet wird.

Bei großen Projekten ist es sinnvoll alle public Prozeduren eines Moduls
(eventuell mehrere source files) mit den gleichen Anfangsbuchstaben zu
beginnen.
Z.B. XX_init(), YY_init(), YY_send_byte(), YY_xoff(), ...

Sinnvolle Richtlinien machen sich in der Regel bezahlt. Man muß doch hin und
wieder mal Software auf ein anderes Zielsystem portieren - auch wenn das Jahre
vorher nicht geplant war. Oder zwei ähnliche Moduln müssen auf einmal in einem
System laufen. Wie gut, wenn man dann auch bei gleichlautenden Funktionsnamen
diese zwei Präfix-Buchstaben hatte!

Shubhashayam
*** Gerhard

Uwe Heidemann

unread,
Apr 28, 1998, 3:00:00 AM4/28/98
to

Hallo Sönke,

SML>sind das dieselben Leute, die Warnschilder schreiben, daß man einen
SML>Fahrstuhl nicht benutzen sollte, wenn dieser brennt?

Was ist denn daran verwerflich? Es ist unheimlich gefährlich, einen Fahrstuhl
im Brandfall zu benutzen!

Ciao

Uwe H..

Götz Borkowski

unread,
Apr 28, 1998, 3:00:00 AM4/28/98
to

Hi,

Ja, ich denke, so ähnlich kann man's sehen. Eigentlich ist es, meine ich, ein
Abfallprodukt bei der Produktion von Richtlinien, die im Großen und Ganzen
sonst vernünftig sind: Die berühmten Auswüchse und Sumpfblüten. Kann man in
jeder Behörde etc. reihenweise bewundern. Ist ja bekannt, daß Konzerne,
proportional zu ihrer Größe, verstärkte Ähnlichkeit mit Behörden bekommen...
;-)


Gruß Götz

Gerhard Bahr

unread,
Apr 29, 1998, 3:00:00 AM4/29/98
to

Hallo Sönke,

SML>sind das dieselben Leute, die Warnschilder schreiben, daß man einen
SML>Fahrstuhl nicht benutzen sollte, wenn dieser brennt?

...wenn ES brennt...

Shubhashayam
*** Gerhard

Sönke Müller-Lund

unread,
May 1, 1998, 3:00:00 AM5/1/98
to

Moin Heiko,

> Wie gehe ich mit fremden Headerfiles um, bei denen es Konflikte gibt? (Z.B.
> mit abweichenden Deklarationen, fehlender #ifndef / #define -Klammerung
> etc.) Sollte ich diese Headerfiles anpassen oder soll ich eigene Headerfiles
> schreiben, die die problematischen Headerfiles nachladen und 'fixen' ?

es ist natürlich immer besser, irgendwelche Pakete unberührt zu lassen.
Wie dem auch sei, in beiden Fällen solltest Du gut dokumentieren, was Du
da eigentlich machst.

> Ist es statthaft, Standardfunktionen durch eigene Makros zu ersetzen?
> Ich habe mir zum Beispiel
> #define new( type ) (type *) malloc( sizeof( type ))
> #define cnew( num,type ) (type *) calloc( num,sizeof( type ))
> #define crealloc( blk, num, type ) (type *) realloc( blk, (num) * sizeof(
> type ))
> geschrieben, benutze diese durchgängig und finde es viel praktischer als die
> Standard-Aufrufe.

Also mir fällt augenblicklich nichts ein, was noch gefährlicher für ein
Projekt ist, als das, was Du dort fabrizierst.
Sieht man einmal davon ab, daß "new" C++ und kein C ist, solltest Du
zumindest genau wissen, was deine "Standard-Funktion" macht, bevor Du sie
"verbesserst".
Und ich gebe dir schwarz auf weiß, daß "new" wesentlich mehr tut, als
Speicher für ein Objekt zu reservieren.

Obiges mag bei deinen Geschichten prächtig funktionieren, aber wenn Du
dein Haederfile später in einem echten C++ Programm verwenden willst,
fällst Du mächtig auf die Nase.

Götz Borkowski

unread,
May 2, 1998, 3:00:00 AM5/2/98
to

Hallo,

Casts: siehe meine letzte mail v. 28.04. ...

Richlinien (etwa zur Schreibweise von Bezeichnern):

Hier finde ich es nicht so wichtig, WIE die Konventionen im einzelnen lauten,
aber sie sollten zweierlei Dinge sicherstellen:

1) Makros, Globale, Modulglobale, Funktionen... sollten möglichst klar
voneinander zu unterscheiden sein.

2) Die Konventionen sollten etwa innerhalb einer Firma, eines Projekts o. ä.
STRIKT von ALLEN Beteiligten eingehalten werden.

So sind in erwähntem Konzern u.a. folgende (sinnvolle!) Konventionen üblich:

- Globale Var. fangen mit Großbuchstaben an und stehen in Headerfile,
- Modulglobale: Auch Gr.-Buchstabe, stehen aber in C-Modul.
- Lokale Variablen: Fangen klein an; falls zusammengesetzte Wörter, dann
fängt ab dem 2. jedes Teilwort groß an.
- Makros: Nur Großbuchst., Unterstriche trennen Teilwörter
- Funktionen: wie Lokalvariablen falls Modul-static, wie Globale falls
exportiert. Tragen Präfix, der das Herkunftsmodul kenntlich macht, wie etwa
"errSomethingWrong (...)" aus dem Modul "errhand.c".
- Namen für Bezeichner sind IMMER englisch.
- Tabweite bei Einrückungen ist 3.
- Kommentare sind ebenfalls englisch.
- Zeiger tragen Prä- oder Suffix "...Ptr" bzw. "ptr...", sofern nicht
SOFORT aus dem Zusammenhang als Zeiger ersichtlich.


Aber wie gesagt, wichtiger ist, daß Konventionen _einheitlich_ und
_durchgängig_ gehandhabt werden...

Gruß Götz

Gerhard Bahr

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

Hallo Götz,

Götz>2) Die Konventionen sollten etwa innerhalb einer Firma, eines Projekts o.
ä.
Götz>STRIKT von ALLEN Beteiligten eingehalten werden.

In dem was Du dann ausführst, stimme ich Dir voll zu.
Wie sieht es aber mit Richtlinen für die Optik aus?

Z.B.
Götz>- Tabweite bei Einrückungen ist 3.

Wo ich arbeite kann man trotz Richtlinien mit geübtem Auge an einem Stück Code
erkennen, wer es verbrochen hat.

Beispiel:

function(arg1, arg2)
function (arg1, arg2)
function ( arg1, arg2 )

(Welche Argumente gibt es überhaupt dafür auf einen einheitlichen Stil im oben
beschriebenen Fall zu achten?)

oder (mir schaudert):
#define EQ ==
und dann
if (a EQ b)

wieder einen anderen erkenne ich am
/* that's it */
return;

wieder ein anderer schreibt auch im default-Zweig sein "break;"

oder
int i,j,k; /* loop counters */
long gnrpf;

Man beachte den Kommentar oben - jeder kann sich denken, was i, j, k ist - bei
gnrpf aber wundert sich der Leser, wofür das wohl gebraucht wird. Es macht dann

Spaß zu verfolgen, daß gnrpf mit gnlpf multipliziert und zur Potenz von grumpf
erhoben wird, als index für das Feld gnlumpf dient, in dem dann die pointer auf

die strings mit dem ...

Meine Erfahrung mit Codierrichtlinen ist die, daß sie für die Art der Anwendung

und die Arbeitsumgebung maßgeschneidert werden müssen. Wer
Echtzeitbetriebssystem produziert hat ganz andere Anforderungen als
Arbeitsgruppen, Compiler auf PC basteln.


Shubhashayam
*** Gerhard

Heiko Achilles

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

Hi Sönke,
danke für die Tips.
SML>Und ich gebe dir schwarz auf weiß, daß "new" wesentlich mehr tut,
SML>als Speicher für ein Objekt zu reservieren.
Äh... was denn? Und welches new() jetzt, meins oder das C++?

SML>Obiges mag bei deinen Geschichten prächtig funktionieren, aber wenn
SML>Du dein Haederfile später in einem echten C++ Programm verwenden
SML>willst, fällst Du mächtig auf die Nase.
Und wenn ich Großbuchstaben verwende? Ist das Problem hauptsächlich der
Konflikt mit der C++-Funktion new(), von deren Existenz ich nichts wußte? Oder
ist das einfach schlechter Stil? (Mir ging einfach das in meinen Augen doch
recht stupide Wiederholen von (type) malloc( sizeof ( type ) ) auf den Geist.)

ciao
Heiko

Marcus Ohlhaut

unread,
May 8, 1998, 3:00:00 AM5/8/98
to

> function(arg1, arg2)
Meine Variante. Durchgängig.

> function ( arg1, arg2 )

Eindeutig zu viel Whitespace, läßt das ganze sehr unübersichtlich
werden, insbesondere, wenn hier noch geschachtelt wird:
f ( g ( h, i ), j, k ( l ( m ) ) );

> #define EQ ==
Schick den Kollegen in die Fortran-Abteilung (oder wars Cobol?)

>wieder ein anderer schreibt auch im default-Zweig sein "break;"

Das muß ja nicht verkehrt sein:

switch (state) {
default:
// do something
break;
case 1:
// do something else
break;
}

Wobei man natürlich mit "Special cases first, default last"
argumentierten kann.

>- bei gnrpf aber wundert sich der Leser, wofür das wohl gebraucht wird.

:-)

- Marcus [PGP]

Gerhard Bahr

unread,
May 9, 1998, 3:00:00 AM5/9/98
to

Hallo Marcus,

MO>>wieder ein anderer schreibt auch im default-Zweig sein "break;"

MO>Das muß ja nicht verkehrt sein:
MO>switch (state) {
MO>default:
MO> // do something
MO> break;

Wir benutzen X-Tools (einen Struktogramm-Editor, da kommt default automatisch
immer zum Schluß - man merkt ich kann schon gar kein C mehr :-)

Shubhashayam
*** Gerhard

Heiko Kretschmer

unread,
May 10, 1998, 3:00:00 AM5/10/98
to

<^>< Gerhard!

GB> oder
GB> int i,j,k; /* loop counters */
GB> long gnrpf;
GB>
GB> Man beachte den Kommentar oben - jeder kann sich denken, was i, j, k ist -
bei
GB> gnrpf aber wundert sich der Leser, wofür das wohl gebraucht wird. Es macht
dann
GB> Spaß zu verfolgen, daß gnrpf mit gnlpf multipliziert und zur Potenz von
grumpf
GB> erhoben wird, als index für das Feld gnlumpf dient, in dem dann die pointer
auf
GB> die strings mit dem ...
ROTFL!!

Tschö, Heiko (mit Mac Philipp)

Gerhard Bahr

unread,
May 12, 1998, 3:00:00 AM5/12/98
to

Hallo Heiko,

HK>ROTFL!!
Das ist bitterer Ernst!
;-)

Shubhashayam
*** Gerhard

0 new messages