Header/Structs/Arrays

mag1000

Grünschnabel
Hallo zusammen,

da ich Neuling bin erstmal, vielen Dank für die ganzen Tipps, die ich hier schon gefunden habe. Großartiges Forum.
Leider aber konnte ich mein aktuelles Problem nicht finden.

Also die Programmiersprache ist C und ich möchte in mehreren c-Dateien Zugriff auf eine 3D-Matrix haben.Also habe ich eine header datei erstellt (header.h)
Es handelt sich dabei um ein Gitter, das für jeden Matrix-Eintrag 3 Werte (x,y,z-Wert) hat.
Da habe ich mir gedacht, dass es schön übersichtlich ist, wenn ich das zu einer struct mesh zusammenfasse.
Innerhalb der struct mesh definiere ich nun mittels Pointer die Matrix, die variabel in der Größe ist.
Mittels malloc wird die Größe später definiert.
Nun ist das Problem, dass ich beim kompilieren folgende Meldung von eclipse erhalte:

"../src/header.h:41:11: error: variably modified ‘x’ at file scope"
(für y und z dasselbe).
Verschiebe ich die struct-Definition in die main-Funktion ist der Fehler weg, aber dann ist die struct leider nicht in allen c-Dateien verfügbar.

Kann mir jemand bei dem Problem helfen?

Hier der Code von header.h
in den c-Dateien steht logischerweise dann immer "#include "header.h"

Code:
#ifndef HEADER_H
#define HEADER_H

#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

//Variables
int int_interations;
int int_interationsStart;
int int_interationsEnd;

int int_myCPUID;
int int_MaxNumberCPUs;

int int_iMax;
int int_jMax;
int int_kMax;

//Variables of ConfigImport
struct strct_configuration
{
	int int_totalIterations;
	int int_iterationsSample;
	int int_CPUsInIDirection;
	int int_CPUsInJDirection;
	int int_CPUsInKDirection;
	double dbl_tau;
	double dbl_machNumber;
	double dbl_reynoldsNumber;
	double dbl_prandtlNumber;
	double dbl_kappaNumber;
	double dbl_gasConstantNumber;
};

//Variables of MeshImport
struct strct_mesh
{
	double (*x)[int_iMax][int_jMax];
	double (*y)[int_iMax][int_jMax];
	double (*z)[int_iMax][int_jMax];
};
#endif /*HEADER_H */
 
Hi.

Du darfst in Headerdateien keine Variablen definieren. Wenn du das doch tust bekommst du Linkerfehler, da jedes Modul diese Variablen enthält.

Deklariere alle Variablen in der Headerdatei als "extern" und definiere sie in einer einzelnen C-Datei.

Welchen Compiler verwendest du? Schreibst du C99 Code? Es ist nur in C99 erlaubt Arrays mit variabler Größe zu definieren. Ansonsten müssen Arraydimensionen "konstante Ausdrücke" sein.

Gruß
 
Ich nutze den gcc compiler, das hier spuckt der mir aus, wenn ich nach der version frage:
Code:
gcc (SUSE Linux) 4.5.0 20100604 [gcc-4_5-branch revision 160292]
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

wie sieht denn die syntax für einen variablen mehrdimensionalen array aus?
Code:
Aktuell verwende ich für einen 3D-pointer folgende syntax:
double (*x)[i][j];
x=malloc(k*sizeof(double));

gibt es bessere alternativen?


wie genau funktioniert das mit dem extern? ich versteh das nicht.
bisher wurde hier eine c-datei verwendet, wo alles drin stand.
ich möchte jetzt für verschiedene themen eigene c-dateien erstellen, und in diesen c-dateien dann die funktionen definieren. also übersicht schaffen.
wo definiert man bei einem modularisierten projekt am sinnvollsten die variablen, und vor allem wie =)?
sry, was modularisierte projekte angeht, hab ich keine erfahrung!
bin einer dieser ingenieur-coder.

gruß,
manuel
 
Ich nutze den gcc compiler, das hier spuckt der mir aus, wenn ich nach der version frage:

gcc (SUSE Linux) 4.5.0 20100604 [gcc-4_5-branch revision 160292]
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

wie sieht denn die syntax für einen variablen mehrdimensionalen array aus?
Wie üblich. Der Compiler muss nur angewiesen werden den Code zu akzeptieren (beim GCC mit der "-std=c99" Option). Aber selbst in C99 ist es nicht erlaubt (Zeiger auf) Arrays variabler Länge auf Dateiebene (also global) zu deklarieren.
Aktuell verwende ich für einen 3D-pointer folgende syntax:
Code:
double (*x)[i][j];
Das ist in C89 und C90 nur statthaft, wenn i und j "konstante Ausdrücke" sind. Also Präprozessor-Variablen oder Literale.

Man darf in C89/C90 keine Zeiger auf Arrays variabler Größe deklarieren.
gibt es bessere alternativen?
Da du für solch ein Array immer auch die Dimension wissen mußt, wäre es am günstigsten diese Information gleich zusammenzufassen:
C:
struct array_2d {
  int x, y;
  double* _mem;
};
Später, falls du C99 nutzt, kannst du dann auf _mem als ein 2 dim. Array zugreifen.
C:
struct array_2d a = { 5, 6, calloc(5 * 6, sizeof(double)) };

...
typedef double (*xarray_2d)[a.y];
xarray_2d a2 = (xarray_2d)a._mem;

func(a2[1][2]);
wie genau funktioniert das mit dem extern? ich versteh das nicht.
bisher wurde hier eine c-datei verwendet, wo alles drin stand.
C:
// in xyz.h

extern int x;
C:
// in xyz.c
#include "xyz.h"

int x;
C:
// in abc.c
#include "xyz.h"
...
printf("%i", x);
wo definiert man bei einem modularisierten projekt am sinnvollsten die variablen, und vor allem wie =)?
Naja, zusammengehörige Variablen, Funktionen, Typen gehören in ein Paar von Header- und C-Datei.

Bitte achte auf die Netiquette, insbesondere Punkt 15! Und verwende für Code die Code-Tags. Danke.

Gruß
 
Zuletzt bearbeitet:
Hi,
meinst du mit Punkt 15, dass ich Groß- und Kleinschreibung verwenden soll?

Also erstmals vielen Dank für deine ausführliche und großartige Hilfe. Du hast mir sehr geholfen.
Vor allem habe ich nun dank deiner Hinweise, wie man modularisiert, einmal meinen Code optimiert.

Was ich aber nicht ganz verstehe ist, wie du den 3-dimensionalen Array erzeugst. Mein Compiler scheint C99 zu verwenden, weil dein beschriebener Code bei mir funktionierte.
Allerdings ist dieser nun zweidimensional.
Was ich mir wünsche ist folgendes:
C:
mesh.x[i][j][k]=12.32
mesh.y[i][j][k]=17.268
mesh.z[i][j][k]=0.1458
Hierbei sind i,j,k Gitterpunkte des Netzes, wobei ich aktuell nicht weiß wieviele Gitterpunkte es pro Dimension gibt. Das müsste ich also dynamisch machen.
Wie säh das aus? Ich habe eben wieder erfolglos rumprobiert =(.

PS: Wie sieht die Implementation dieser Struktur im Header aus? Ich muss die "mesh"-Struktur nämlich in mehreren C-Dateien nutzen.

Danke im voraus!
 
Zuletzt bearbeitet:
Hi,
meinst du mit Punkt 15, dass ich Groß- und Kleinschreibung verwenden soll?
Ja.
Was ich aber nicht ganz verstehe ist, wie du den 3-dimensionalen Array erzeugst. Mein Compiler scheint C99 zu verwenden, weil dein beschriebener Code bei mir funktionierte.
GCC ist da manchmal etwas lax.
Allerdings ist dieser nun zweidimensional.
Was ich mir wünsche ist folgendes:
C:
mesh.x[i][j][k]=12.32
mesh.y[i][j][k]=17.268
mesh.z[i][j][k]=0.1458
Hierbei sind i,j,k Gitterpunkte des Netzes, wobei ich aktuell nicht weiß wieviele Gitterpunkte es pro Dimension gibt. Das müsste ich also dynamisch machen.
Wie säh das aus? Ich habe eben wieder erfolglos rumprobiert =(.
Analog zu 2D:
C:
typedef double (*array_3d)[j][k];
array_3d mesh_x = (array_3d)mesh.x;
PS: Wie sieht die Implementation dieser Struktur im Header aus? Ich muss die "mesh"-Struktur nämlich in mehreren C-Dateien nutzen.
Wie ich es bereits demonstriert habe. Du verwendest einen einfachen Zeiger in der Struktur.

Gruß
 
Sorry, aber meine Dummheit ist heute grenzenlos :),
ich schaffs nicht.
Hier mein Code:
C:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
int i,j,k;

struct my_mesh {
  double x, y, z;
  double* _mem;
};


struct my_mesh mesh = { 3, 3, 3, calloc(3*3*3, sizeof(double)) };

i=3;
j=3;
k=3;

typedef double (*array_3d)[j][k];
array_3d mesh_x = (array_3d)mesh.x;


for(i=0;i<=2;i++)
{
for(j=0;j<=2;j++)
{
for(k=0;k<=2;k++)
{
    mesh.x[i][j][k]=i+j+k;
}
}
}



for(i=0;i<=2;i++)
{
for(j=0;j<=2;j++)
{
for(k=0;k<=2;k++)
{
printf("mal gucken: %lf\n",mesh.x[i][j][k]);
}
}
}


}
 
Hi.

Also bei mir spuckt der Compiler:
Code:
d3x.c: In function ‘main’:
d3x.c:22: error: cannot convert to a pointer type
d3x.c:31: error: subscripted value is neither array nor pointer
d3x.c:44: error: subscripted value is neither array nor pointer
make: *** [d3x] Error 1
zu 1) der Zeiger innerhalb der (Beispiel-)Struktur heißt _mem, nicht x
zu 2) und 3) statt mesh.x mußt du natürlich über mesh_x zugreifen.

Gruß
 
Hi,
also bin gerade zuhause aber werde es gleich morgen ausprobieren.
Die Fehlermeldung, die du dort hast, ist diesselbe, die ich auch hatte.
Demnach müsste ich ja dann den Fehler wegkriegen.
Also hier schonmal VIELEN DANK =)******
 
Hi,
also es funktioniert.
Er macht jetzt, was er soll.
Leider verstehe ich nicht vollkommen, wie der Code funktioniert.

Ich definiere ja zunächst eine Struktur mit 3 Variablen und einem Pointer (warum hat der eigentlich einen unterstrich? Ist das Usus?)
C:
  struct my_mesh {
  double x, y, z;
  double* _mem;
};

Anschließend erzeuge ich solch eine struktur und initialisier diese direkt. Die Werte 1,2,3 werden den Variablen x,y,z der Struktur zugewiesen und der Pointer allokiert Speicher. Warum?
C:
struct my_mesh mesh = { 1, 2, 3, calloc(3*3*3, sizeof(double)) };

Was hier gemacht wird, versteh ich irgendwie gar nicht. Anscheinend wird hier der 3D Array erzeugt. Aber wie genau sieht da die Verbindung zur Struktur aus? Kann ich mir das so vorstellen, dass ich keinen double-Array erzeuge, sondern einen my_mesh-Array?
Was genau macht die untere Zeile und was bewirkt "typedef" ?
C:
typedef double (*array_3d)[j][k];
array_3d mesh_x = (array_3d)mesh._mem;

Wäre wirklich klasse, wenn du mir das noch erklären könntest.
Danke!
 
Zuletzt bearbeitet:
Zurück