Forum: Compiler & IDEs Initialisierung von Doppel Array verhindert Programmausführung


von devil13 (Gast)


Lesenswert?

Hallo zusammen :)

irgendwie habe ich gerade ein Verständnissproblem.


Schreibe ich außerhalb der main Funktion das hier, wir mein Programm 
nicht mehr ausgeführt (der Compiler meckert nicht):

unsigned char virtual_LCD[SCREEN_HIGHT][SCREEN_WIDTH];


Was meiner Meinung nach dem hier entsprechen müsste ...
... schreibe das hier außerhalb der main Funktion
unsigned char **virtual_LCD;


und das hier in die main Funktion, funktioniert das Programm
virtual_LCD = malloc(SCREEN_HIGHT * sizeof(unsigned char*));
for (unsigned char idx = 0; idx < SCREEN_WIDTH; idx++)
  virtual_LCD[idx] = malloc(SCREEN_WIDTH * sizeof(unsigned char));


Nun meine Frage:
was ist an diser Formulierung falsch?
unsigned char virtual_LCD[SCREEN_HIGHT][SCREEN_WIDTH];

SCREEN_HIGHT, SCREEN_WIDTH sind Konstanten


Vielen Dank!

von Jonas B. (jibi)


Lesenswert?

>der Compiler meckert nicht

soll heißen er gibt keinen Fehler oder keine Warnmeldung aus?

Gruß Jonas

von devil13 (Gast)


Lesenswert?

er sagt erfolgreich kompiliert

von Yalu X. (yalu) (Moderator)


Lesenswert?

devil13 schrieb:
> und das hier in die main Funktion, funktioniert das Programm

Aber sicher nicht perfekt, denn hier sollte SCREEN_WIDTH durch
SCREEN_HIGHT ersetzt werden:
1
for (unsigned char idx = 0; idx < SCREEN_WIDTH; idx++)

> was ist an diser Formulierung falsch?
> unsigned char virtual_LCD[SCREEN_HIGHT][SCREEN_WIDTH];

Nichts.

Damit hast du das Array statisch definiert, und es liegt zusammenhängend
im Speicher. Im anderen Fall wird die Datenstruktur dynamisch angelegt,
und die einzelnen Zeilenarrays können verstreut im Speicher liegen.

Wenn das Programm nicht läuft oder abstürzt, liegt es vielleicht daran,
dass du das Array falsch nutzt. Oder du hast wo ganz anders einen
Fehler.

von devil13 (Gast)


Lesenswert?

Yalu X. schrieb:
>> was ist an diser Formulierung falsch?
>> unsigned char virtual_LCD[SCREEN_HIGHT][SCREEN_WIDTH];
>
> Nichts.

denn versteh ich aber nicht, warum es nicht geht ... ich verwende das 
Array bisher nicht mal ... außer diese Zeile

unsigned char virtual_LCD[SCREEN_HIGHT][SCREEN_WIDTH];

taucht virtual_LCD nicht auf ...

lasse ich es weg, geht es, steht es mit drin, geht es nicht ...

Nebenbei bemerkt, ich möchte dieses Array in ein Modul packen.

es soll nicht in der Header Datei stehen, aber ich der dazugehörigen *.c 
Datei ... kann das damit was zu tun haben oder muss ich dabei etwas 
beachten?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

devil13 schrieb:
> SCREEN_HIGHT, SCREEN_WIDTH sind Konstanten

Dann gibt's allerdings keinen sinnvollen Grund, das Array und
die Subarrays dynamisch anzulegen.  Funktionieren sollte es
natürlich trotzdem, auch wenn beide Ansätze nicht identisch sind
von der Benutzung.

devil13 schrieb:
> es soll nicht in der Header Datei stehen, aber ich der dazugehörigen *.c
> Datei ...

Speicherplatz alloziert man ohnehin nie in Headerdateien.  Dort
muss also stehen:

extern unsigned char virtual_LCD[SCREEN_HIGHT][SCREEN_WIDTH];

und in einer der C-Dateien dann einfach

unsigned char virtual_LCD[SCREEN_HIGHT][SCREEN_WIDTH];

(auf globalem Niveau).

von devil13 (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Speicherplatz alloziert man ohnehin nie in Headerdateien.  Dort
> muss also stehen:
>
> extern unsigned char virtual_LCD[SCREEN_HIGHT][SCREEN_WIDTH];
>
> und in einer der C-Dateien dann einfach
>
> unsigned char virtual_LCD[SCREEN_HIGHT][SCREEN_WIDTH];

Nunja, da ich dieses Array nur in der *.c Datei des Moduls verwende und 
es nach außen nich sichtbar sein soll. Glaube aber sowas wie private und 
public gibt es in C noch nicht ... naja ... zur Not, kann auch alles 
überall sichtbar sein ... die Variante mit extern in der *.h Datei führt 
auch dazu, dass das Programm nicht mehr ausgeführt wird ...

von Yalu X. (yalu) (Moderator)


Lesenswert?

devil13 schrieb:
> denn versteh ich aber nicht, warum es nicht geht ... ich verwende das
> Array bisher nicht mal ... außer diese Zeile

Der Programmfehler liegt nicht immer dort, wo man die letzte Änderung
vor Auftreten des Fehlverhaltens gemacht hat.

Vielleicht hast du woanders einen Array-Überlauf o.ä., so dass beim
Beschreiben des Arrays andere Variablen überschrieben werden. Fügst du
nun das virtual_LCD-Array hinzu, wird die Speicherposition anderer
Variablen verschoben, so dass durch den Überlauffehler jetzt vielleicht
andere Variablen überschrieben werden, die für den Programmablauf
besonders kritisch sind.

von Matthias (Gast)


Lesenswert?

>Nunja, da ich dieses Array nur in der *.c Datei des Moduls verwende und
>es nach außen nich sichtbar sein soll. Glaube aber sowas wie private und
>public gibt es in C noch nicht ... naja ... zur Not, kann auch alles

Sowas gibt es schon, halt ein bissle anders:

"static unsigned char virtual_LCD[SCREEN_HIGHT][SCREEN_WIDTH];"

als globale Variable ist nur innerhalb der C-Datei, in der es definiert 
wurde, sichtbar.


Was für ein System bzw. Controller verwendest Du?

Und wieviel anderes Zeugs wird in dem Projekt noch verwendet?

von devil13 (Gast)


Lesenswert?

Yalu X. schrieb:
> Vielleicht hast du woanders einen Array-Überlauf o.ä., so dass beim
> Beschreiben des Arrays andere Variablen überschrieben werden. Fügst du
> nun das virtual_LCD-Array hinzu, wird die Speicherposition anderer
> Variablen verschoben, so dass durch den Überlauffehler jetzt vielleicht
> andere Variablen überschrieben werden, die für den Programmablauf
> besonders kritisch sind.

Habe das Problem mal an nem Beispiel reproduzieren können. Das Verhalten 
ist bei mir genau das Beschriebene.

das geht
1
#include <avr/io.h>
2
3
//unsigned char virtual_LCD[122][32];
4
5
int main(void)
6
{
7
  DDRB = (1<<PB0);  
8
  PORTB ^= (1<<PB0);
9
10
}

dass nicht
1
#include <avr/io.h>
2
3
unsigned char virtual_LCD[122][32];
4
5
int main(void)
6
{
7
  DDRB = (1<<PB0);  
8
  PORTB ^= (1<<PB0);
9
10
}

(verwende übrigends nen Atmega8)

von Yalu X. (yalu) (Moderator)


Lesenswert?

Wieviel RAM hat der ATmega8, und wieviel Bytes belegt dein Array? :)

von devil13 (Gast)


Lesenswert?

Matthias schrieb:
> Sowas gibt es schon, halt ein bissle anders:
>
> "static unsigned char virtual_LCD[SCREEN_HIGHT][SCREEN_WIDTH];"
>
> als globale Variable ist nur innerhalb der C-Datei, in der es definiert
> wurde, sichtbar.

bedeutet dann static nicht auch unveränderlich? Oder gilt das nur für 
die Array Größe, nicht aber für deren Inhalt?

von Patrick (Gast)


Lesenswert?

devil13 schrieb:
> (verwende übrigends nen Atmega8)

Scherzkeks.
Schon mal ausgerechnet, wie viele Bytes Dein Array im RAM belegt?
Und schon mal ins Datenblatt geschaut, wieviel RAM der ATmega8 hat?
Na?...

von devil13 (Gast)


Lesenswert?

Patrick schrieb:
> Scherzkeks.
> Schon mal ausgerechnet, wie viele Bytes Dein Array im RAM belegt?
> Und schon mal ins Datenblatt geschaut, wieviel RAM der ATmega8 hat?
> Na?...

Hm ... muss gestehen, darüber habe ich mir garkeine Gedanken gemacht ... 
erklärt aber das Problem ...

Danke für die Hilfe erstmal :)


Wie würdet ihr denn am Besten an mein Vorhaben rangehen?
Ich beschäftige mich gerade mit Grafik Displays. Habe auch alles so 
hinbekommen, dass alles funktioniert. Jedoch muss ich z.B. um eine Linie 
zu zeichnen immer ganz viele Punkte im LCD zeichnen lassen ... da dieser 
aber immer 8 Bit Spalten besitzt, muss ich die 7 Bit die bleiben sollen 
immer erst einlesen, das zu ändernde Bit ändern und dann wieder 
zurückschreiben. Ich finde das sehr mühsam und umständlich.
Daher wollte ich mir im Atmega8 merken, was gerade auf dem LCD zu sehen 
ist und dann nur noch zu schreiben ... bzw. ein kompletten Display im 
Atmega vorzubereiten und ihn dann an das LCD senden. Das würde viel 
schneller gehen.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Wieviele Pixel hat das Display, 32×122 oder 256×122? Ist letzteres der
Fall, gibt es keine Möglichkeit, den Displayinhalt lokal zu speichern,
und dir bleibt nur der umständlichere Weg. Aber auch dann kannst du die
Sache etwas optimieren, indem du erst einmal alle zu ändernden Pixel,
die zum selben Byte gehören, sammelst und dann erst den Displayzugriff
machst.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

devil13 schrieb:

> unsigned char virtual_LCD[SCREEN_HIGHT][SCREEN_WIDTH];
>
> Was meiner Meinung nach dem hier entsprechen müsste ...
>
> unsigned char **virtual_LCD;

Nö.

Das eine ist ein 2-dimensionales Array von 8-Bit Skalaren, das andere 
ist ein Array von Zeigern.

Auf beide wird unterschiedlich und nicht-kompatibel zugegriffen

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

devil13 schrieb:
> muss ich die 7 Bit die bleiben sollen
> immer erst einlesen, das zu ändernde Bit ändern und dann wieder
> zurückschreiben

Rate mal was der uC macht wenn das im internem RAM liegt? ;-)

Sei doch froh, dass das Grafikdisplay genug RAM mitbringt wo du den 
Inhalt drin liegen hast.

Damit es komfortabler wird kann man sich ja Funktionen schreiben welche 
den mühevollen Teil erledigen.

von devil13 (Gast)


Lesenswert?

Yalu X. schrieb:
> Wieviele Pixel hat das Display, 32×122 oder 256×122?

32×122 Pixel

Läubi .. schrieb:
> Sei doch froh, dass das Grafikdisplay genug RAM mitbringt wo du den
> Inhalt drin liegen hast.
>
> Damit es komfortabler wird kann man sich ja Funktionen schreiben welche
> den mühevollen Teil erledigen.

dann werde ich mich wohl damit zufrieden geben ... allerdings dauert das 
Zeichnen schon echt ganz schön lange ... naja ...

Yalu X. schrieb:
> Aber auch dann kannst du die
> Sache etwas optimieren, indem du erst einmal alle zu ändernden Pixel,
> die zum selben Byte gehören, sammelst und dann erst den Displayzugriff
> machst.

Das war ja auch mein Plan ... nur im schlechten Fall, kann sich ja alles 
ändern und dafür brauche ich eben besagtes Arra, was zu groß ist um es 
im Ram abzulegen, und der SRAM/EEPROM ist mir dafür zu schade ... weiß 
nicht, wieviel zusätzliche Geschwindigkeit man gewinnt, wenn man einen 
externen Ram nutzt ... dachte nur, weil das LCD mit 2 kHz arbeitet und 
der Atmega mit 16 MHz wäre es besser, wenn der Atmel mehr arbeit macht 
... vllt. wäre nen "größerer" Atmega oder nen anderes Display oder so ne 
einfachere Lösung ...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

devil13 schrieb:
> bedeutet dann static nicht auch unveränderlich? Oder gilt das nur für
> die Array Größe, nicht aber für deren Inhalt?

Du solltest die Programmiersprache deiner Wahl schon erstmal lernen,
bevor du versuchst, sie zu verwenden.  "static" ist, wenn man es auf
globalem Niveau in einer Datei anwendet (also außerhalb aller
Funktionen) genau das "private", das du gesucht hast.  "Statisch" (im
Sinne von permanent vergebenem Speicherplatz) ist auf diesem Niveau
nämlich ohnehin alles, nur ohne "static" sind Funktionen und Variablen
global.

Kann man als Designfehler der Sprache C ansehen.  Eigentlich hätte
ohne Kennzeichnung alles privat sein sollen, und nur durch "export"
oder sowas global.  Daher ist es auch guter Stil, dass man vor alles,
das nicht exportiert wird, prinzipiell "static" schreibt.

Mit "const" sollte man das alles außerdem nicht verwechseln.

von devil13 (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Du solltest die Programmiersprache deiner Wahl schon erstmal lernen,
> bevor du versuchst, sie zu verwenden.

Ganz schön harte Worte ... aber ich muss zugeben nicht unberechtigt ...

... aber ich möchte dran erinnern, dass zwischen etwas nicht können und 
etwas können immernoch etwas lernen liegt!

Dennoch ein Dickes Dankeschön, an alle, die mir so nett geholfen haben, 
mein kleines Problem zu lösen :)

von André A. (nummer5) Benutzerseite


Lesenswert?

>> Wieviele Pixel hat das Display, 32×122 oder 256×122?
>32×122 Pixel

Dann brauchst du für jeden Pixel nur ein Bit also nur 122*4 Byte. Die 
einzelnen Pixel anzusprechen ist dann zwar etwas komplizierter, aber ich 
vermute mal, dass dein Grafikdisplay die Daten genauso abspeichert, du 
die Berechnungen also schon hast.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

devil13 schrieb:
> ... aber ich möchte dran erinnern, dass zwischen etwas nicht können und
> etwas können immernoch etwas lernen liegt!

Ja, das ist dann gerade deine Aufgabe. ;-)

von Yalu X. (yalu) (Moderator)


Lesenswert?

André Althaus schrieb:
>>> Wieviele Pixel hat das Display, 32×122 oder 256×122?
>>32×122 Pixel
>
> Dann brauchst du für jeden Pixel nur ein Bit also nur 122*4 Byte.

Eben. Genau deswegen habe ich nachgefragt.

Die Zugriffsfunktionen für das Array sind nicht besonders schwierig,
wenn nicht gerade jemand aus dem C-Buch die Seiten mit den Bitoperatoren
herausgerissen hat:
1
#include <stdint.h>
2
3
#define SCREEN_WIDTH   32
4
#define SCREEN_HEIGHT 122
5
6
uint8_t virtual_LCD[SCREEN_HEIGHT][SCREEN_WIDTH/8];
7
8
void setpixel(uint8_t x, uint8_t y) {
9
  virtual_LCD[y][x/8] |= 1 << x % 8;
10
}
11
12
uint8_t getpixel(uint8_t x, uint8_t y) {
13
  return virtual_LCD[y][x/8] >> x % 8 & 1;
14
}

von devil13 (Gast)


Angehängte Dateien:

Lesenswert?

Yalu X. schrieb:
> André Althaus schrieb:
>>>> Wieviele Pixel hat das Display, 32×122 oder 256×122?
>>>32×122 Pixel
>>
>> Dann brauchst du für jeden Pixel nur ein Bit also nur 122*4 Byte.
>
> Eben. Genau deswegen habe ich nachgefragt.

Boa ... was für nen dummi Fehler^^



Hier schonmal meine bisherigen Bemühungen für das Pollin LCD-12232.
Funktioniert soweit ganz schick ... aber ist eben auch die (finde ich) 
unschöne/umständliche/langsame Variante ... naja ... vllt. probiert sich 
ja jemand an diesem LCD und kann das als kleine Hilfe verwenden ...


Ich versuche mich gerade noch an die hier disskutierte Variante und 
sollte ich diese irgendwann fertig stellen, poste ich sie hier :)

LG

von devil13 (Gast)


Lesenswert?

Ach ja:

Anregungen, Verbesserungen, Kritik erwünscht!

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.