Forum: Compiler & IDEs 'return' with no value, in function returning int


von Rück Kehrer (Gast)


Lesenswert?

Ja, ich weiß, der Compiler hat immer Recht, aber in diesem Fall... sehe 
ich es einfach nicht. Beim ersten Versuch (ohne default: mit allen case) 
dachte ich noch, der switch deckt alle Werte des shm_type_enum ab (gcc 
merkt auch, wenn nicht), also wird das Ende der Funktion nie erreicht. 
Das stimmt so nicht, weil in SHM_DATA_TYPES[] ein Wert vorkommt der im 
enum nicht vorkommt. Genau für solche Fälle möchte ich auch eine Warnung 
sehen.

Aber mit default: sind doch wirklich alle Werte abgedeckt und trotzdem 
gibt es anscheinend einen Pfad zum Ende der Funktion.
1
// convert.c -- convert internal <-> external resolution
2
#include "display.h"
3
#include "shm.h"
4
#include "shm-data-types.h"
5
#include "syslib.h"
6
#include "temperature.h"
7
extern volatile shm_struct  shm;
8
9
int
10
cv_int_ext (volatile int *src)
11
{
12
   uint32_t  index;
13
14
   index = src - &shm.nc;
15
   if (index >= sizeof SHM_DATA_TYPES) {
16
      exit (4);  // dprintf ("cv_int_ext: illegal src %d\n", index);
17
   }
18
   switch (SHM_DATA_TYPES[index]) {
19
   case ST_Input:
20
   case ST_Temp_in:
21
   case ST_Volt_in:
22
      exit (6);  /* FIXME */
23
24
   case ST_Output:
25
      exit (5);  // dprintf ("cv_ext_int: cannot convert from output\n");
26
27
   case ST_Temp_C:
28
      return (*src - TEMP_0C + C_MUL/2) / C_MUL;
29
30
   case ST_Temp_K:
31
      return (*src + C_MUL/2) / C_MUL;
32
33
   case ST_Minutes:
34
      return (*src + 30) / 60;
35
36
   case ST_Volt:
37
      return (*src + 500) / 1000;
38
39
// case ST_Bits:
40
// case ST_Int:
41
// case ST_Seconds:
42
   default:
43
      return *src;
44
   }
45
}
46
47
void
48
cv_ext_int (volatile int *dst, int ext)
49
{
50
   uint32_t  index;
51
/* gekürzt */
52
}
1
// shm-data-types.h
2
#pragma once
3
#include "shm.h"
4
// DO NOT EDIT -- generated from ../include/shm.h by ../tools/shm-to-types
5
6
typedef enum shm_type_enum {
7
   ST_Bits     = 'B',
8
   ST_Int      = 'I',
9
   ST_Input    = 'i',
10
   ST_Output   = 'o',
11
   ST_Temp_in  = 't',
12
   ST_Temp_C   = 'C',
13
   ST_Temp_K   = 'K',
14
   ST_Minutes  = 'M',
15
   ST_Seconds  = 'S',
16
   ST_Volt_in  = 'v',
17
   ST_Volt     = 'V',
18
} shm_type_enum;
19
20
static const shm_type_enum SHM_DATA_TYPES[] = {
21
   '-', 't', 't', 't', 't', 't', 't', 't', 't', 't', 't', 't', 't', 'i',
22
   'I', 'I', 'I', 'I', 'I', 'M', 'I', 'I', 'I', 'M', 'S', 'V', 'V', 'S',
23
   'I', 'I', 'C', 'I', 'I', 'K', 'K', 'K', 'V', 'V', 'M', 'C', 'B', 'V',
24
   '-', '-', '-', '-', '-', '-', '-', '-', '-', 0
25
};
1
// syslib.h
2
#pragma once
3
#include <stdarg.h>
4
#include <stdint.h>
5
6
void  exit (int status) __attribute__ ((noreturn));
7
/* gekürzt */

von Yalu X. (yalu) (Moderator)


Lesenswert?

Ich sehe hier nirgends einen "'return' with no value". Vermutlich liegt
der Fehler in einer Datei, die du nicht gepostet hat. Oder du hast
Änderungen am Code vorgenommen, aber das Abspeichern vergessen.

von Olly T. (twinpeaks)


Lesenswert?

Liegt's vielleicht an den Cases mit exit(), kapiert der Compiler das 
'noreturn' nicht?

von Rätselprogrammierer (Gast)


Lesenswert?

Yalu X. schrieb:
> Ich sehe hier nirgends einen "'return' with no value".

Warscheinlch braucht er ausserhhalb der switch-Klammer
ein "return (irgendwas)".

von Yalu X. (yalu) (Moderator)


Lesenswert?

Rätselprogrammierer schrieb:
> Warscheinlch braucht er ausserhhalb der switch-Klammer
> ein "return (irgendwas)".

Nein, die Fehlermeldung sagt aus, dass da zwar ein 'return' steht, aber
ohne Argument. Und genau dieses argumentlose 'return' kommt in seinem
gepostenen Code gar nicht vor.

Wollte sich der Compiler (ich nehme an, GCC) über ein komplett fehlendes
'return' beschweren, würde er dies mit

  "control reaches end of non-void function"

tun.

von Rück Kehrer (Gast)


Lesenswert?

Yalu X. schrieb:

> Wollte sich der Compiler (ich nehme an, GCC) über ein komplett fehlendes
> 'return' beschweren, würde er dies mit
>
>   "control reaches end of non-void function"
>
> tun.

In der Tat, man sollte immer das Kleingedruckte lesen. Damit muss es 
wohl am exit() liegen. Aber das heißt ja, dass der gcc aus dem 
((noreturn)) ein return; macht... Für den switch passt das (man braucht 
kein break), aber für die Funktion ist es eben ein return with no value.

Aber ich finde, ((noreturn)) bedeutet "no return" und wie soll ohne 
return etwas zurück gegeben werden? Man kann also nur aus void 
Funktionen ausbrechen? In einer normalen main() funktioniert das doch 
auch?

Der GCC ist ein selbst gebauter arm-none-eabi-7.0.1

von Dr. Sommer (Gast)


Lesenswert?

Rück Kehrer schrieb:
> if (index >= sizeof SHM_DATA_TYPES) {
Das ist übrigens falsch, du meinst vermutlich:
1
if (index >= sizeof(SHM_DATA_TYPES) / sizeof(SHM_DATA_TYPES[0]))

von Dr. Sommer (Gast)


Angehängte Dateien:

Lesenswert?

Da du ja keinen kompilierbaren Code gepostet hast, habe ich meinen 
eigenen zusammengebastelt, siehe Anhang. Damit funktioniert es. Daher 
ist nicht nachvollziehbar, wo dein Problem liegt. Getestet mit x86_64 
GCC 5.4.0, arm-none-eabi-gcc 6.3.1, sowie Clang 3.8.0.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rück Kehrer schrieb:
> Der GCC ist ein selbst gebauter arm-none-eabi-7.0.1

Aber der zeigt doch genau die Zeile und die Stelle an, wo das Problem 
ist.

> Damit muss es wohl am exit() liegen. Aber das heißt ja, dass der gcc
> aus dem ((noreturn)) ein return; macht...

Nein.  noreturn funktioniert wie erwartet.  Der Fehler ist woanders, 
z.B. falsche Header o.ä.

> Aber ich finde, ((noreturn)) bedeutet "no return"

So ist es.

> Man kann also nur aus void Funktionen ausbrechen?

Nein.

von Rolf M. (rmagnus)


Lesenswert?

Rück Kehrer schrieb:
> Aber ich finde, ((noreturn)) bedeutet "no return" und wie soll ohne
> return etwas zurück gegeben werden?

Die Funktion könnte in C++ implementiert sein und eine Exception werfen. 
Aber das sollte nicht zu dieser Warnung führen.

Rück Kehrer schrieb:
> // syslib.h
> #pragma once
> #include <stdarg.h>
> #include <stdint.h>
>
> void  exit (int status) _attribute_ ((noreturn));
> /* gekürzt */

Nur so am Rande: Gibt es einen speziellen Grund, warum du exit() selbst 
deklarierst?

von Bernd K. (prof7bit)


Lesenswert?

Rolf M. schrieb:
> Nur so am Rande: Gibt es einen speziellen Grund, warum du exit() selbst
> deklarierst?

Hat er das?

von Rolf M. (rmagnus)


Lesenswert?

Bernd K. schrieb:
> Rolf M. schrieb:
>> Nur so am Rande: Gibt es einen speziellen Grund, warum du exit() selbst
>> deklarierst?
>
> Hat er das?

Ähm, ich hab doch sogar den Teil zitiert, wo er das hat.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Bernd K. schrieb:
> Rolf M. schrieb:
>> Nur so am Rande: Gibt es einen speziellen Grund, warum du exit() selbst
>> deklarierst?
>
> Hat er das?

Ja, nämlich im hausbackenen syslib.h.

Standardmäßig ist die deklariert in stdlib.h.  Und GCC kennt den 
Prototyp ohnehin (außer bei freestanding).

von Rück Kehrer (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Da du ja keinen kompilierbaren Code gepostet hast, habe ich meinen
> eigenen zusammengebastelt, siehe Anhang. Damit funktioniert es. Daher
> ist nicht nachvollziehbar, wo dein Problem liegt.

Hier auch nicht mehr :( Ursprünglich war ich auf der Suche nach einer 
Konstruktion für meine logischen Datentypen (Volt, Minuten,...) mit der 
ich auch zuverlässig Warnungen bekomme. Und dann hab' ich mich um 
diese Warnung im Kreis gedreht.

Alles um diesen switch herum ist statisch und vollständig definiert. 
Also hatte ich gehofft, dass der gcc auch den Inhalt von 
SHM_DATA_TYPES[] berücksichtigt. Zusammen mit der Prüfung auf die 
Feldgrenze wäre das doch theoretisch möglich. Na gut, jetzt steht am 
Ende der Funktion noch ein exit(), falls sich das Programm doch dahin 
verlaufen sollte.


Johann L. schrieb:
> Rück Kehrer schrieb:
>> Damit muss es wohl am exit() liegen. Aber das heißt ja, dass der gcc
>> aus dem ((noreturn)) ein return; macht...
>
> Nein.  noreturn funktioniert wie erwartet.  Der Fehler ist woanders,
> z.B. falsche Header o.ä.
Tut es und ist er. Zwischen Bildschirm und Tastatur wie meistens.


Rolf M. schrieb:
> Nur so am Rande: Gibt es einen speziellen Grund, warum du exit() selbst
> deklarierst?
Johann L. schrieb:
> Und GCC kennt den Prototyp ohnehin (außer bei freestanding).
Ich möchte die Abhängigkeit von einer newlib o.ä. vermeiden (praktisch 
die Steigerung von freestanding?). Die paar simplen Funktionen, die ich 
brauche, sind gleich eingetippt (na gut, printf hab' ich vom ChibiOS 
ausgeborgt; danke, Giovanni Di Sirio).


Dr. Sommer schrieb:
> Rück Kehrer schrieb:
>> if (index >= sizeof SHM_DATA_TYPES) {
> Das ist übrigens falsch, du meinst vermutlich:if (index >=
> sizeof(SHM_DATA_TYPES) / sizeof(SHM_DATA_TYPES[0]))

Ja, das ist ein heikles Thema. Eigentlich hast du Recht. Aber wer 
sowieso mit -Os kompiliert, schreibt auch -fshort-enums dazu. Das ist 
beim cortex-m wohl auch Standard laut aapcs. Bei einer kritischen struct 
schreibe ich auch gerne _Static_assert zwecks Größen-Prüfung dazu. 
Deshalb hab' ich wegen der Zeile kein schlechtes Gewissen; ich finde es 
so lesbarer.

Vielen Dank an alle!

von Dr. Sommer (Gast)


Lesenswert?

Rück Kehrer schrieb:
> Ja, das ist ein heikles Thema. Eigentlich hast du Recht.
Aaah, ich habe definitiv Recht!

Rück Kehrer schrieb:
> Deshalb hab' ich wegen der Zeile kein schlechtes Gewissen; ich finde es
> so lesbarer.
Weil man so verwirrt ist, ob du jetzt wirklich nur auf einen "normalen" 
Array Überlauf prüfen möchtest oder irgendwas anderes komisches? Es hat 
definitiv keinerlei Nachteil das korrekt hinzuschreiben, dann 
funktioniert es immer, und dann weiß jeder was gemeint ist. Ohne Not 
Code zu schreiben der nur unter ganz bestimmten Bedingungen 
funktioniert, und sonst ohne jegliche Vorwarnung Unsinn macht, ist eine 
ganz schlechte Angewohnheit.
Du programmierst ja in C, da musst du mit umständlichem Code leben. Wenn 
du C++ nutzen würdest, könntest du es so kompakt schreiben:
1
static constexpr std::array<shm_type_enum, 52> SHM_DATA_TYPES = { ... };
2
// ...
3
4
   if (index >= SHM_DATA_TYPES.size ()) {
5
      exit (4);  // dprintf ("cv_int_ext: illegal src %d\n", index);
6
   }

Rück Kehrer schrieb:
> Na gut, jetzt steht am
> Ende der Funktion noch ein exit(), falls sich das Programm doch dahin
> verlaufen sollte.
Obwohl die Warnung jetzt gar nicht mehr auftritt? Da wäre es doch 
sinnvoller das wegzulassen, damit die Warnung eben doch kommt, falls du 
was (falsch) änderst.

PS: Bei solchen Fällen könnte ggf auch __builtin_unreachable helfen, 
aber das ist dann besonders hässlich.

von Rolf M. (rmagnus)


Lesenswert?

Rück Kehrer schrieb:
> Rolf M. schrieb:
>> Nur so am Rande: Gibt es einen speziellen Grund, warum du exit() selbst
>> deklarierst?
> Johann L. schrieb:
>> Und GCC kennt den Prototyp ohnehin (außer bei freestanding).
> Ich möchte die Abhängigkeit von einer newlib o.ä. vermeiden (praktisch
> die Steigerung von freestanding?).

exit() ist eine Standard-C-Funktion. Die existiert in jeder konformen 
C-Implementation, die nicht freestanding ist.

von Rück Kehrer (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Es hat
> definitiv keinerlei Nachteil das korrekt hinzuschreiben, dann
> funktioniert es immer, und dann weiß jeder was gemeint ist.
Buchstabenverschwendung, Tastaturabnutzung, Stromverbrauch,... aber du 
stimmst mich nachdenklich, ich möchte ja lesbare Programme schreiben.

> Rück Kehrer schrieb:
>> Na gut, jetzt steht am
>> Ende der Funktion noch ein exit(), falls sich das Programm doch dahin
>> verlaufen sollte.
> Obwohl die Warnung jetzt gar nicht mehr auftritt? Da wäre es doch
> sinnvoller das wegzulassen, damit die Warnung eben doch kommt, falls du
> was (falsch) änderst.
Ein Mißverständnis; der switch sollte niemals ein default label haben. 
Und wenn dann kein exit() und kein return am Ende steht, gibt es die 
Warnung immer noch. Normalerweise auch total berechtigt, weil ja von 
draußen beliebige Werte kommen könnten, auch wenn der switch alle 
enum-Werte abdeckt. Dies ist ja ein extremer Sonderfall in dem alles 
komplett statisch ist.

Eine sinnvolle Warnung vom Compiler bekomme ich hier wohl nicht. Mit dem 
exit() gibt es wenigstens einen definierten Laufzeitfehler. Ein return 
wäre hier nur schädlich.

> PS: Bei solchen Fällen könnte ggf auch __builtin_unreachable helfen,
> aber das ist dann besonders hässlich.
Das muss wirklich hässlich sein, das kannte ich noch garnicht :)


Rolf M. schrieb:
> exit() ist eine Standard-C-Funktion. Die existiert in jeder konformen
> C-Implementation, die nicht freestanding ist.
willst du damit sagen, dass ich meine exit() anders nennen sollte? Die 
verhält sich praktisch wie die Standard-Funktion. Man würde doch z.B. 
ein eigenes printf() auch nicht umbenennen, auch wenn es nicht alle 
Formate kennt?

von Rolf M. (rmagnus)


Lesenswert?

Rück Kehrer schrieb:
> Rolf M. schrieb:
>> exit() ist eine Standard-C-Funktion. Die existiert in jeder konformen
>> C-Implementation, die nicht freestanding ist.
> willst du damit sagen, dass ich meine exit() anders nennen sollte? Die
> verhält sich praktisch wie die Standard-Funktion.

Ah, mir war nicht bewusst, dass du die Funktion selbst implementiert 
hast. Ich dachte, du verwendest die Standardfunktion, benutzt aber aus 
irgendeinem Grund nicht den Header, in dem sie deklariert ist.
Also ich würde sie anders nennen, und wenn's "myexit()" ist oder so. Ich 
finde es schon sinnvoll, erkennbar zu machen, wenn man nicht die 
Originalfunktion, sondern eine selbst gestrickte verwendet, auch wenn 
sie funktional gleich ist.
In C++ kann man das schön über Namespaces lösen. Gleicher Name, aber 
anderer Namespace. Gibt's in C aber nicht.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rück Kehrer schrieb:
> Aber wer sowieso mit -Os kompiliert, schreibt auch -fshort-enums dazu.

Warum sollte man?  -Os ist eine Option zur Codeoptimierung. 
-fshort-enums ändert das Binärinterface (ABI).  Ich seh jetzt nicht, 
warum Optimierung Änderung des ABI implizieren sollte.

von Rolf M. (rmagnus)


Lesenswert?

Johann L. schrieb:
> Rück Kehrer schrieb:
>> Aber wer sowieso mit -Os kompiliert, schreibt auch -fshort-enums dazu.
>
> Warum sollte man?  -Os ist eine Option zur Codeoptimierung.
> -fshort-enums ändert das Binärinterface (ABI).  Ich seh jetzt nicht,
> warum Optimierung Änderung des ABI implizieren sollte.

Man kann es natürlich so formulieren, dass es irgendwie keinen 
Zusammenhang zu haben scheint. Oder eben: -Os ist ein Parameter, um 
Speicher zu sparen, -fshort-enums auch. Und schon passt es zusammen. Ich 
glaube aber, dass es in der Praxis wenig Programme gibt, bei denen man 
mit -fshort-enums signifikant Platz sparen kann.

von MaWin (Gast)


Lesenswert?

Rolf M. schrieb:
> Ich
> glaube aber, dass es in der Praxis wenig Programme gibt, bei denen man
> mit -fshort-enums signifikant Platz sparen kann.

Mit -fshort-enums spart man vor allem Code/Laufzeit auf 
8-Bit-Architekturen, weil alles in einem statt zwei Registern gehandhabt 
werden kann.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rolf M. schrieb:
> Johann L. schrieb:
>> Rück Kehrer schrieb:
>>> Aber wer sowieso mit -Os kompiliert, schreibt auch -fshort-enums dazu.
>>
>> Warum sollte man?  -Os ist eine Option zur Codeoptimierung.
>> -fshort-enums ändert das Binärinterface (ABI).  Ich seh jetzt nicht,
>> warum Optimierung Änderung des ABI implizieren sollte.
>
> Man kann es natürlich so formulieren, dass es irgendwie keinen
> Zusammenhang zu haben scheint. Oder eben: -Os ist ein Parameter, um
> Speicher zu sparen, -fshort-enums auch.

Nein.  -fshort-enums ist ein Schalter, um ein anderes ABI einzustellen. 
Dass das gegebenenfalls zu kleinerem Code führt ist ein angenehmer 
Nebeneffekt, mehr nicht.

Prinzipiell sind Objekte / Module, die mit unterschiedlichen 
Optimierungsstufen oder -schaltern übersetzt wurden, zusammen 
funktionsfähig und interoperabel.

Auf Objekte und Bibliotheken hingegen, die für unterschiedliches ABI 
übersetzt wurden, trifft das i.d.R nicht zu.

Das alles ist bereits daran erkennbar, dass die GCC-Doku -Os et al. als 
Optimierungsoption listet

http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

während -fshort-enums unter "Options for Code Generation Conventions"

These machine-independent options control the interface conventions used 
in code generation.

http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html

von Rolf M. (rmagnus)


Lesenswert?

Johann L. schrieb:
>> Man kann es natürlich so formulieren, dass es irgendwie keinen
>> Zusammenhang zu haben scheint. Oder eben: -Os ist ein Parameter, um
>> Speicher zu sparen, -fshort-enums auch.
>
> Nein.  -fshort-enums ist ein Schalter, um ein anderes ABI einzustellen.

Und warum sollte man das wollen? Einfach so, um mal etwas Abwechslung zu 
haben?

> Dass das gegebenenfalls zu kleinerem Code führt ist ein angenehmer
> Nebeneffekt, mehr nicht.

Ich seh's genau umgekehrt. -fshort-enums ist ein Schalter für kleineren 
Code (und ggf. kleinere Daten). Dass sich dadurch das ABI ändert, ist 
ein unangenehmer Nebeneffekt.

> Auf Objekte und Bibliotheken hingegen, die für unterschiedliches ABI
> übersetzt wurden, trifft das i.d.R nicht zu.

Das hat aber erstmal mit dem primären Zweck des Schalters nichts zu tun.

von Rück Kehrer (Gast)


Lesenswert?

Rolf M. schrieb:
> Johann L. schrieb:
>>> Man kann es natürlich so formulieren, dass es irgendwie keinen
>>> Zusammenhang zu haben scheint. Oder eben: -Os ist ein Parameter, um
>>> Speicher zu sparen, -fshort-enums auch.
>>
>> Nein.  -fshort-enums ist ein Schalter, um ein anderes ABI einzustellen.
>
> Und warum sollte man das wollen? Einfach so, um mal etwas Abwechslung zu
> haben?
>
>> Dass das gegebenenfalls zu kleinerem Code führt ist ein angenehmer
>> Nebeneffekt, mehr nicht.
>
> Ich seh's genau umgekehrt. -fshort-enums ist ein Schalter für kleineren
> Code (und ggf. kleinere Daten). Dass sich dadurch das ABI ändert, ist
> ein unangenehmer Nebeneffekt.

Ich sehe es noch umgekehrter;) Ich schreibe jetzt zum "typedef enum" ein 
"__attribute__((packed))" dazu und lasse den Schalter weg. Der gcc 
produziert dann mit -fno-short-enums genauso kleine Binaries (±8 Byte 
bei 60k) und das ABI wird nicht angetastet. Allerdings ist -fshort-enums 
bei den cortex-m sowieso der Default, ich finde nur nicht, wo das 
genau festgelegt ist.

"Using the GNU Compiler Collection (For gcc version 7.0.1)" sagt nur:
1
Chapter 4: C Implementation-Defined Behavior
2
4.9 Structures, Unions, Enumerations, and Bit-Fields
3
  On some targets, `-fshort-enums' is the default;
4
  this is determined by the ABI.

Im "ARM Procedure Call Standard for the ARM® Architecture" lässt ARM das 
auch offen, schreibt aber:
1
7.1.3 Enumerated Types
2
Discussion
3
  The definition of enumerated types in the C and C++ language standards
4
  does not define a binary interface and leaves open the following
5
  questions.
6
  * Does the container for an enumerated type have a fixed size
7
    (as expected in most OS environments) or is the size no larger than
8
    needed to hold the values of the enumeration (as expected by most
9
    embedded users)?

von Dr. Sommer (Gast)


Lesenswert?

Rück Kehrer schrieb:
> Ich sehe es noch umgekehrter;) Ich schreibe jetzt zum "typedef enum" ein
> "__attribute__((packed))" dazu und lasse den Schalter weg.
Oder du nutzt C++, wo du die Größe direkt portabel ohne 
Compiler-spezifische Erweiterungen oder Flags angeben kannst:
1
enum shm_type_enum : uint8_t {
2
   ST_Bits     = 'B',
3
   ST_Int      = 'I',
4
   ST_Input    = 'i',
5
   ST_Output   = 'o',
6
   ST_Temp_in  = 't',
7
   ST_Temp_C   = 'C',
8
   ST_Temp_K   = 'K',
9
   ST_Minutes  = 'M',
10
   ST_Seconds  = 'S',
11
   ST_Volt_in  = 'v',
12
   ST_Volt     = 'V',
13
};

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Dr. Sommer schrieb:
> Oder du nutzt C++,

Motto: Um ein Problem in Sprache X zu lösen, verwende ich immer Sprache 
Y.

von Dr. Sommer (Gast)


Lesenswert?

Johann L. schrieb:
> Dr. Sommer schrieb:
>> Oder du nutzt C++,
>
> Motto: Um ein Problem in Sprache X zu lösen, verwende ich immer Sprache
> Y.
Motto: Warum jedes Problem mit einem Schraubendreher angehen, wenn es 
schon seit Jahrzehnten Bohrmaschinen gibt? Wir haben hier offensichtlich 
Probleme, die durch C++ gelöst werden.

von Rolf M. (rmagnus)


Lesenswert?

Johann L. schrieb:
> Dr. Sommer schrieb:
>> Oder du nutzt C++,
>
> Motto: Um ein Problem in Sprache X zu lösen, verwende ich immer Sprache
> Y.

ersetze Y durch X++, eine Sprache, in der du so gut wie alles genau so 
schreiben kannst, nur dass sie unter anderem das gewünschte Feature 
schon mitbringt.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Dr. Sommer schrieb:
> Motto: Warum jedes Problem mit einem Schraubendreher angehen, wenn es
> schon seit Jahrzehnten Bohrmaschinen gibt?

Die von dir vorgeschlagene Bohrmaschine ist aber gerade mal
0,6 Jahrzehnte alt ;-)

von Dr. Sommer (Gast)


Lesenswert?

Yalu X. schrieb:
> Dr. Sommer schrieb:
> Motto: Warum jedes Problem mit einem Schraubendreher angehen, wenn es
> schon seit Jahrzehnten Bohrmaschinen gibt?
>
> Die von dir vorgeschlagene Bohrmaschine ist aber gerade mal
> 0,6 Jahrzehnte alt ;-)

Immerhin! Na, der Spruch bezog sich mehr auf C++ im Allgemeinen. Auch 
das alte C++ enthält nützliche Dinge...

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.