Zum Inhalt springen
View in the app

A better way to browse. Learn more.

Fachinformatiker.de

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

2d Array of Array [FFTW] in C

Empfohlene Antworten

Veröffentlicht

Hallo,

ich arbeite gerade mit der FFTW Bibliothek und bin dabei auf folgendes Problem gestossen:

Ich habe ein zweidimensionales Array vom Typ fftw_complex

fftw_complex fft[256][129]
wobei laut Hilfe fftw_complex wie folgt definiert ist:
typedef double fftw_complex[2];
Nun, ich wollte jetzt einfach mal einen Wert in diesem Array löschen:
fft[Xpos][Ypos]=0;
Das klappt komischerweise, nur weiß ich nicht, welcher Teil den nun gelöscht wird, oder ob gar alle Null gesetzt werden. Wenn ich versuche
fft[Xpos][Ypos][0]=fft[Xpos][Ypos]=0;

zu verwenden, dann bekomme ich den Fehler:"Indizierter Wert ist weder Feld noch Zeiger"

Daher meine Frage: Wie greife ich auf ein Array[][] of Array[2] zu?

Nun, ich wollte jetzt einfach mal einen Wert in diesem Array löschen:

fft[Xpos][Ypos]=0;
Das klappt komischerweise, nur weiß ich nicht, welcher Teil den nun gelöscht wird, oder ob gar alle Null gesetzt werden.
Es ist in der Tat sehr merkwürdig, dass das bei dir funktioniert. Folgenden Code lassen weder MSVC2008 noch der Comeau-Compiler durchgehen:
int main()
{
typedef double fftw_complex[2];
fftw_complex fft[256][129];
fft[0][0]=0;
}[/code]

Morgen kann ich das auch noch mit dem GCC testen.

Welchen Compiler benutzt du denn?

Und kannst du ein vollständiges Minimalbeispiel zeigen, das das beschriebene Verhalten reproduziert?

Ich arbeite mit dem gcc.

Hab gerade etwas herumgespielt:

Eine weitere Bibliothek ist anscheinend schuld an der Misere! Complex.h


#include <fftw3.h>

void main()

{

	fftw_complex fft[256][129];


	fft[0][0]=0;

}

Gibt einen anständigen Fehler zurück, so wie sich das gehört.

#include<complex.h>

#include <fftw3.h>

void main()

{

	fftw_complex fft[256][129];


	fft[0][0]=0;

}

dagegen zeigt dass von mir beschriebene Verhalten.

Danke für den Denkanstoss, scheint als wäre das des Rätsels Lösung!

Allerdings bringt mich das irgendwie nicht weiter :(

Die complex.h brauche ich unbedingt, und kann sie nicht einfach weglassen. *grübel*

Bitte nimm es mir nicht übel, aber wenn ich dieses und andere Postings von Dir lese, dann habe ich das Gefühl, dass Dir Grundlagen fehlen.

Wenn Du den C99-Header "complex.h" zuerst einbindest, führt das 2. Beispiel zu keinem Fehler, da in diesem Fall "fftw_complex" anders definiert wird, also der C99 Typ für komplexe Zahlen zum Einsatz kommt und nicht die typedef Variante. Steht auch in der Dokumentation der Bibliothek.

Du könntest Deinen Komplexe-Zahlen-Typ auch anders als per typedef definieren. Beispielsweise so:

struct KomplexeZahl

{

double realteil;

double imaginaerteil;

};

Alternativ könnte man auch folgendes definieren:

struct KomplexeZahl

{

double teil[2];

};

Die erste Variante ist übersichtlich, da sofort klar ist, wann auf den Real- oder Imaginärteil zugegriffen wird. Bei der zweiten Variante ist bei der Verwendung das Speicherlayout unmissverständlicher, wenn Du zusätzlich die Reihenfolge als "zuerst Realteil, dann Imaginärteil" definierst. (Bei den passenden Compilereinstellungen können aber beide Varianten zu dem gleichen Speicherlayout führen.) Du musst sicherstellen, dass das Speicherlayout mit der zu verwendenen Bibliothek kompatibel bleibt.

Nun kannst Du nach Belieben multidimensionale Arrays anlegen und bei Zugriffen immer unterscheiden, welcher Anteil verändert werden soll.

Wenn Du C++ verwendest, kannst Du auch das complex template verwenden. Wenn Du C99 benutzt, was scheinbar der Fall ist, dann kannst Du dessen Komplexe-Zahlen-Unterstützung verwenden.

mag sein, dass ich grad auf der Leitung steh, aber ist "fftw_complex fft[iFoo][iFoo]" nicht schon von vornerein n dreidimensionales array?

Und wenn dem so wäre, kann man dann da überhaupt per fft[posX][posY] da drauf kommen?

~sry, wenn der Post sinnlos is, interessiert mich nur mal, bin auch so "semianfänger"~

@Bubble: Dein Gefühl trügt dich keineswegs, C ist für mich schwammiges Gebiet, hab vor knapp einem halben Jahr angefangen, da sind noch so einige Lücken drin.

Umso mehr danke ich für die Ausführungen. :)

Wenn Du den C99-Header "complex.h" zuerst einbindest, führt das 2. Beispiel zu keinem Fehler, da in diesem Fall "fftw_complex" anders definiert wird, also der C99 Typ für komplexe Zahlen zum Einsatz kommt und nicht die typedef Variante.

Das ist mir klar, was mich verwirrt ist, dass FFT keinerlei Probleme mit der fftw_complex struktur aus complex.h hat, obwohl diese ja offensichtlich anders aufgebaut ist...

Werd da nochmal die Beschreibung von FFTW wälzen.

@dundee:

Jap, wenn fftw_complex so definiert ist:

typedef double fftw_complex[2]

dann hast du mit fftw_complex fft[iFoo][iFoo]im Prinzip ein 3d-Feld...

Allerdings habe ich den Fehler begangen, eine andere Bibo zuerst einzubinden, so dass fftw_complex von vornherein anders definiert war. Deswegen konnte ich auch durch fft[posX][posY] zugreifen, anscheind ist DAS der richtige weg, wenn man die complex.h nutzt.

Das ist mir klar, was mich verwirrt ist, dass FFT keinerlei Probleme mit der fftw_complex struktur aus complex.h hat, obwohl diese ja offensichtlich anders aufgebaut ist...

Solange das Speicherlayout beider Varianten gleich ist, ist es im Grunde egal, da man dann auch ohne weitere Unterscheidung geeignet programmieren kann. Und falls es dennoch zur Compile-Zeit berücksichtigt werden muss/soll, kann man "#ifdef"s verwenden.

  • 2 Wochen später...

So ungern ich das abgehackte Thema wieder nach oben schiebe, bei mir hat sich wieder eine (vermutlich noobige) Frage ergeben:

Nach dem ich nun nur noch fftw verwende, habe ich versucht, einige Daten in einer Datei auszugeben:

void ausgabe(fftw_complex grauwert[256][129][2], FILE *f2) {

	int i,j;

	for (i=0;i<256;++i) {

		for (j=0;j<129;++j){

[B]			if((j+1)%256 == 0) fprintf(f2,"%f\n",grauwert[i][j][0]);

			else fprintf(f2,"%f\t",grauwert[i][j][0]);  [/B] 

			}

		}

	fclose(f2);	

}

Nun gibt der Kompiler allerdings folgende Warnung:

format >>%f<< erwartet Typ >>double<<, aber Argument 3 hat Typ >>double *<<

Heißt das grauwert[j][0] ist ein Zeiger? (Hmm, kam aus der Dokumentation für mich nicht raus, aber gut.:eek)

Wie könnte ich den mit fprintf einen Zeiger ausgeben?

Heißt das grauwert[j][0] ist ein Zeiger? (Hmm, kam aus der Dokumentation für mich nicht raus, aber gut.:eek)
grauwert[j][0] ist, wie du an deinem Code sehen kannst, ein fftw_complex. Das wiederum ist ein double[2]. Arrayparameter werden in C und C++ aber als Zeiger übergeben.

Wie könnte ich den mit fprintf einen Zeiger ausgeben?
Du willst doch gar keinen Zeiger ausgeben. Du willst doch die beiden double-Werte. Die kannst du mit grauwert[j][0][0] bzw. grauwert[j][0][1] und %f ausgeben.

:upps Ich bin doch blöd...!

Ich will ja mein 2D Array ausgeben, aber die [2] bei

void ausgabe(fftw_complex grauwert[256][129][2], FILE *f2) {

ist natürlich völlig sinnfrei und deutet auf ein 3D array hin.

Mea culpa! :old

Archiv

Dieses Thema wurde archiviert und kann nicht mehr beantwortet werden.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.