Felder und Funktionen

Hi!
Hab hier mehrere kleine Probleme. Vielleicht weisz ja jemand Rat…

  1. Gibt es einen Operator, mit dem ich 2 Felder (gleicher Laenge) punktweise addieren kann?
  2. Wie deklariere ich Funktionen, die Felder zurueckgeben sollen?
  3. Welchen Befehl musz ich verwenden, um eine Funktion dazu zu bewegen, ein Feld zurueckzugeben?
    return(x); // x ist ein float-Feld
    funktioniert nicht so richtig…

Danke im Voraus! MfG,

Berni

Hallo Berni!

Hi!
Hab hier mehrere kleine Probleme. Vielleicht weisz ja jemand
Rat…

  1. Gibt es einen Operator, mit dem ich 2 Felder (gleicher
    Laenge) punktweise addieren kann?

In C++ geht das mit valarrays:

#include

using namespace std;

main()
{
valarray a1(5), a2(5), a3(5); // Array mit 5 Elementen;

for ( int i=0; i

using namespace std;

vector g()
{
vector v(5);

// besetzen …
// […]

return v;
}

main()
{
vector v(5);

v = g();

}

Sollen es aber ‚echte‘ Arrays sein, kommt man AFAIK nicht darum herum, ein Array als (konstanten) Zeiger auf das erste Element zu betrachen, und diesen dann auch in der Funktion zurückzugeben …

int *h()
{
static int i[5] = { 1, 2, 3, 4, 5 };

return &i[0]; //

[…]

  1. Wie deklariere ich Funktionen, die Felder zurueckgeben
    sollen?
  2. Welchen Befehl musz ich verwenden, um eine Funktion dazu zu
    bewegen, ein Feld zurueckzugeben?
    return(x); // x ist ein float-Feld
    funktioniert nicht so richtig…

[…]

Sollen es aber ‚echte‘ Arrays sein, kommt man AFAIK nicht
darum herum, ein Array als (konstanten) Zeiger auf das erste
Element zu betrachen, und diesen dann auch in der Funktion
zurückzugeben …

int *h()
{
static int i[5] = { 1, 2, 3, 4, 5 };

return &i[0]; //

Willst du dein Programm in der Programmiersprache C oder C++ schreiben?
Falls in C++, dann kannst du eine eigene Klasse entwickeln, die Felder berechnet. Du musst nur die geeigneten Methoden finden.

In C kannst du keine Operatoren verwenden. Da musst du dann entsprechend Funktionen entwickeln.

So oder so muszt du mit Zeiger (Pointer) arbeiten. Da kommst du nicht drumm herum.

Ich wette du hast bisher mit Matlab gearbeitet?
Von dort kenne ich solche Vektormultiplikationen mit und ohne Punkt.

cu
Oliver

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hi!

Hi!

[…]
Von der Verwendung der statischen Variablen rate ich
dringend ab. […]

ACK

Gruß,
Jo

Hallo Johannes,

hier noch nachträglich die Erklärung, warum Dein Compiler
an dieser Stelle nicht mehr will.

Zugegeben, die Sache ist zeimlich haarig, und bestimmt fangen
auch verschiedene Compiler an verschiedenen Stellen zu meckern
an (z.B. hat sich mein VC++ bei der Verwendung 'int a[5];'an
der Stelle ‚a = h();‘ die Arbeit eingestellt, was doch
eigentlich des guten zu viel ist? Was sagen die Experten?).

Hier würde jeder Compiler aussteigen, da das hier ein
syntaktischer Fehler ist. Mit ‚int a[5];‘ legst Du einen
_statischen_ Speicherbereich an. Anschließend versuchst
Du jedoch diesem _statischen_ Speicherbereich mit
‚a = h();‘ _dynamisch_ einen anderen Speicherbereich
zuzuweisen. Das ist ein Widerspruch an sich.

Es sollte also folgenderweise heißen:

int* a = new int[5];
do_something(a);
delete [] a;
a = g();
do_something_else(a);
delete [] a;

Gruß,
Lydia

Hi Jo :smile:

Du schreibst folgenden Code:

int \*h()
{
 static int i[5] = { 1, 2, 3, 4, 5 };
 return &i[0]; // 
Damit ist h eine Funktion, die einen Zeiger auf int zurückgibt. Mit anderen Worten, der Rückgabewert ist eine Speicheradresse, deren Inhalt als int-Wert interpretiert werden soll.



> Zugegeben, die Sache ist zeimlich haarig, und bestimmt fangen  
> auch verschiedene Compiler an verschiedenen Stellen zu meckern  
> an (z.B. hat sich mein VC++ bei der Verwendung 'int a[5];'an  
> der Stelle 'a = h();' die Arbeit eingestellt, was doch  
> eigentlich des guten zu viel ist? Was sagen die Experten?).


Doch, das ist völlig verständlich. Mit "int a[5]" definierst du ein Feld. Das kleine "a" wird vom Compiler direkt durch die Startadresse des Feldes ersetzt. Du versuchst nun, dieser Konstanten den Rückgabewert von h() zuzuweisen. Das kann nicht klappen. Das geht nur bei einem Zeiger. Ein solcher ist nämlich eine Variable, die eine Speicheradresse enthält. Merkst du den Unterschied? In C/C++ sind Feldnamen und Zeiger eben **nicht** dasselbe!!! Auch wenn dies in vielen Büchern fälschlicherweise so dargestellt wird!!!

cu Stefan.

Hallo Stefan,

> return &i[0]; //


Bei meinem VC++ funktioniert auch return i;



> Doch, das ist völlig verständlich. Mit "int a[5]" definierst  
> du ein Feld. Das kleine "a" wird vom Compiler direkt durch die  
> Startadresse des Feldes ersetzt. Du versuchst nun, dieser  
> Konstanten den Rückgabewert von h() zuzuweisen. Das kann nicht  
> klappen.


Stimmt.



> Merkst du den Unterschied? In C/C++ sind Feldnamen und Zeiger  
> eben **nicht** dasselbe!!! Auch wenn dies in vielen Büchern  
> fälschlicherweise so dargestellt wird!!!


Eigendlich doch. Der Feldname wird synonym zur Addresse des Anfangselementes benutzt (wurde schon bei K&R so definiert). Bei Feldern, die zB. in main() wie "int a[5]" definiert werden, handelt es sich um statische Felder. Der Feldname repräsentiert dabei eine **Zeigerkonstante**. Also immer noch einen Zeiger, der nich verändert werden darf. Sonst wäre ja schließlich keine Zeigerarithmetik möglich, wie der []-Operator zeigt. Es gilt: a[i] \*(a+i).

\*(a+i) wäre natürlich schlechter Programmierstil.

Bei dynamischen Feldern (Siehe Lydia-Artikel).

Gruß Frank.

Hi Frank :smile:

Bei Feldern, die zB. in main() wie „int a[5]“ definiert
werden, handelt es sich um statische Felder. Der Feldname
repräsentiert dabei eine Zeigerkonstante. Also immer
noch einen Zeiger, der nich verändert werden darf.

Ein Feldname wird während des Compilierens automatisch durch die Startadresse des Feldes ersetzt. Ein Zeiger hingegen ist eine Variable, deren Inhalt eine Adresse ist! Feldnamen und Zeiger sind also definitiv nicht dasselbe!!!

Sonst wäre ja schließlich keine Zeigerarithmetik möglich,
wie der []-Operator zeigt. Es gilt: a[i] *(a+i).

Das ist genau das, was in fast allen C/C++ Büchern das Problem ist. Dadurch wird suggeriert, dass Zeiger und Feldnamen dasselbe wären. Probier doch mal bitte in 2 Dateien eines Projektes folgende globale Definition/Deklaration:

Datei 1:
int a[10];

Datei 2:
extern int *a;

Ich garantiere dir, dass jeder Compiler dabei aussteigt. In Datei 1 ist „a“ ein Synonym für eine Speicheradresse. In Datei 2 ist „a“ eine Variable, deren Inhalt eine Speicheradresse ist. Beide werden vom Compiler völlig unterschiedlich behandelt. Damit dürfte dann auch die angebliche Gleichheit von Feldnamen und Zeigern widerlegt sein :smile:

*(a+i) wäre natürlich schlechter Programmierstil.

Wieso? Es ist doch völlig egal, wie du das schreibst:

a[5] = *(a+5) = *(5+a) = 5[a]

Ach, ich liebe C/C++. Die Sprache ist so was von logisch :smile:

cu Stefan.

Feld als Rückgabewert - geht!
Hi Bernhard :smile:

Wie du schon gelesen hast, kannst du in C++ eigentlich nur einen Zeiger auf ein Feld zurückgeben. Es gibt allerdings einen simplen Trick, mit dem du trotzdem ganze Felder zurückgeben kannst: Pack das Feld in eine Struktur!!!

struct Feld { float a[10]; }

und definiere deine Funktion so:

Feld myFunc (Feld f1, Feld f2, int n)
{ Feld f3;
 for (int i=0; i
Das funktioniert prima, ohne Aufruf von "new" oder "malloc" (das spart dir viel Zeit und eine Fehlerprüfung). Du kannst dein Programm auch noch beschleunigen, weil sich f1.a und f2.a ja nicht ändern. Übergib einfach Referenzen. Dann wird nicht der gesamte Inhalt der Felder in f1 und in f2 an die Funktion übergeben, sondern nur Adressen darauf. Dazu musst du nur den Funktionskopf ändern:


    
    Feld myFunc (Feld &f1, Feld &f2, int n)



So einfach ist C/C++ :smile:))

cu Stefan.

Hi!

So einfach ist C/C++ :smile:))

OK, danke fuer den Tip. Das werd ich auch mal probieren!

sWE,

Berni

Hi!

Ich wette du hast bisher mit Matlab gearbeitet?

erwischt. :smile:

sWE,

Berni

Hi!

Von der Verwendung der statischen Variablen rate ich
dringend ab. […]

Werds mir merken!

Dank euch allen!

Berni

Hi Stefan,

das Mißverständnis, was in fast allen C/C++ - Büchern auftritt, ist wohl, daß man nicht streng zwischen den Datentyp Zeiger und Adresse unterscheiden kann.
Ich benutze die Definition, daß ein Zeiger ein Datentyp ist (also eine Adresse, die auf einen bestimmten Typ zeigt).
Variablen, die diesen Datentyp enthalten nenne ich Zeigervariablen.

Ein Feldname wird während des Compilierens automatisch durch
die Startadresse des Feldes ersetzt.

Deshalb ist es ja auch eine Zeiger konstante und keine Zeigervariable. Man könnte z.B. durch #define z ((int*) 0xffff0000) eine solche Art Zeigerkonstante definieren.

Probier doch mal bitte in 2 Dateien eines
Projektes folgende globale Definition/Deklaration:

Datei 1:
int a[10];

Datei 2:
extern int *a;

Damit dürfte dann auch die angebliche Gleichheit
von Feldnamen und Zeigern widerlegt sein :smile:

Das zeigt nach obiger Definition, daß Konstanten und Variablen nicht dasselbe sind.

*(a+i) wäre natürlich schlechter Programmierstil.

Wieso? Es ist doch völlig egal, wie du das schreibst:

a[5] = *(a+5) = *(5+a) = 5[a]

Natürlich ist es egal. Wenn man aber in einem Entwicklungsteam arbeitet, wobei die Sourcen offengelegt werden, müssen gewisse Regeln (zB ungarische Notation u.a.) eingehalten werden, um nicht geteert und gefedert zu werden.

Ach, ich liebe C/C++. Die Sprache ist so was von logisch :smile:

dito

Gruß Frank

Moin,

Ich gehe mal von C aus.

  1. Gibt es einen Operator, mit dem ich 2 Felder (gleicher
    Laenge) punktweise addieren kann?

Nö. Meinst Du das:
for (int i = 0; i

for (int i = 0; i

Moin,

for (int i = 0; i

(for (int i = 0; i

for (int i = 0; i

oder

for (int i = 0; i 

MfG Bruno

Moin,

Das tut zwar was, aber nicht das gewünschte :wink:

Jaja, ohne Compiler programmiert sich’s schlecht. Ich hör’ jetzt auch auf.

Thorsten

Jaja, ohne Compiler programmiert sich’s schlecht.

Stimmt :smile: Eintippen und testen is leichter :smile: