Forum: Mikrocontroller und Digitale Elektronik Beispiel Quellcode sd-karte


von Holger W. (mb_holger)


Lesenswert?

Hallo ich bin am verzweifeln. Wer kann mir helfen?
Ich habe versucht den Beispiel Quellcode aus dem Buch "AVR Hardware und 
Programmierung in C"  sd-karte.c mit dem AtmelStudio kompilieren. Zum 
linken und brennen kommt es nicht. AtmelStudio bricht mit vielen 
undefined reference to ....Fehlermeldungen ab.zb.

Error  28  ld returned 1 exit status  collect2.exe  0  0 GccApplication8

Error  5  undefined reference to `fat_loadFatData'  C:\Users\mb_win 
7\Documents\Atmel 
Studio\6.2\GccApplication8\GccApplication8\Debug/.././GccApplication8.c 
120  1  GccApplication8

Error  26  undefined reference to `uputc'  C:\Users\mb_win 
7\Documents\Atmel 
Studio\6.2\GccApplication8\GccApplication8\Debug/.././GccApplication8.c 
146  1  GccApplication8

Error  2  undefined reference to `uputs'  C:\Users\mb_win 
7\Documents\Atmel 
Studio\6.2\GccApplication8\GccApplication8\Debug/.././GccApplication8.c 
110  1  GccApplication8

Error  19  undefined reference to `ffclose'  C:\Users\mb_win 
7\Documents\Atmel 
Studio\6.2\GccApplication8\GccApplication8\Debug/.././GccApplication8.c 
137  1  GccApplication8

...... ......
und noch einige mehr undefined reference to Fehlermeldungen andere 
Fehlermeldungen außer der Error 28 ld returned 1 exit status  und  viele 
undefined reference to und erscheinen nicht.

wer kann mir helfen? Liegt es daran das der Compiler einen Zugriff auf 
der SD Karte sucht und nicht darauf zugreifen kann?
vielen Dank
Holger

code
1
/**
2
 *  Greift auf eine SD Karte per SPI zu
3
 *
4
 *   Doku, siehe http://www.mikrocontroller.net/articles/AVR_FAT32
5
 *  Neuste Version: http://www.mikrocontroller.net/svnbrowser/avr-fat32/
6
 *  Autor: Daniel R.
7
 *
8
 *  Modifikationen: Florian Schäffer, www.blafusel.de, 23.6.2014
9
 *
10
 */
11
12
# define F_CPU 4000000UL
13
#include <avr/io.h>
14
#include <util/delay.h>    // definiert _delay_ms() 
15
16
17
#include <avr/interrupt.h>
18
#include <stdio.h>
19
#include <mmc_config.h>  // Hier werden alle noetigen Konfigurationen vorgenommen, umbedingt anschauen !
20
#include <file.h>
21
#include <fat.h>
22
#include <mmc.h>    // Hardware abhaengig
23
#include <uart.h>    // Hardware abhaengig, es kann auch eine eigene eingebunden werden !
24
25
26
// prototypen von funktionen in dieser datei
27
static void timer0_init(void);
28
int main(void);
29
30
// timer0 einstellungen, werte mit http://www.avrcalc.com/download.html berechnet!
31
// aus diesen 3 werten ergibt sich die tick zeit, hier 10ms. 
32
// 4 = prescaler 256, 3 = prescaler 64, 5 = prescaler 1024, 2 = prescaler 8. wenn prescaler 0 = prescaler dann stoppt der timer
33
#if(F_CPU == 4000000)      // error 0.16%
34
  #define TOP_OCR 0x9B
35
  #define START_TCNT 0x64
36
  #define PRESCALER 0x04
37
#endif
38
39
#if(F_CPU == 8000000)      // error 0,16%
40
  #define TOP_OCR 0x4D
41
  #define START_TCNT 0xB2
42
  #define PRESCALER 0x05
43
#endif
44
45
#if(F_CPU == 10000000)      // error 0.351%
46
  #define TOP_OCR 0x61
47
  #define START_TCNT 0x9E
48
  #define PRESCALER 0x05
49
#endif
50
51
#if(F_CPU == 12000000)      // error 0.16%
52
  #define TOP_OCR 0x74
53
  #define START_TCNT 0x8B
54
  #define PRESCALER 0x05
55
#endif
56
57
#if(F_CPU == 16000000)      // error 0,16%
58
  #define TOP_OCR 0x9B
59
  #define START_TCNT 0x64
60
  #define PRESCALER 0x05
61
#endif
62
63
#if(F_CPU == 20000000)      // error 0.16%
64
  #define TOP_OCR 0x4D
65
  #define START_TCNT 0xB2
66
  #define PRESCALER 0x04
67
#endif
68
69
// timer0 variable
70
volatile uint8_t   TimingDelay;  // fuer mmc.c
71
72
73
ISR (TIMER0_COMP_vect)
74
{
75
  TimingDelay = (TimingDelay==0) ? 0 : TimingDelay-1;
76
}
77
78
79
static void timer0_init()
80
{
81
  // timer0 config  
82
  // initialisierung, auf jeden fall vor mmc_init(), 
83
  // denn da wird der timer benoetigt!
84
85
  TimingDelay = 0;    // initialisierung der zaehl variable  
86
87
  TCCR0 = 1<<WGM01;     // timer0 im ctc mode
88
  TIMSK = 1<<OCIE0;    // compare interrupt an
89
90
  TCNT0 = START_TCNT;    // ab wo hochgezaehlt wird,
91
  OCR0 = TOP_OCR;      // maximum bis wo gezaehlt wird bevor compare match  
92
93
  TCCR0 = PRESCALER;    // wenn prescaler gesetzt wird, lauft timer los
94
  sei();          // interrupts anschalten, wegen compare match
95
}
96
97
98
99
// *****************************************************************************************************************
100
int main(void)
101
{
102
  uint8_t file_name [] = "test.txt";
103
  char str [20];
104
  uint32_t seek;
105
106
  timer0_init();    // Timer initialisieren bevor FAT Library genutzt wird
107
  uinit();      // uart config 
108
109
  uputs((uint8_t*)"Start");
110
111
  // sd/mmc config  
112
  if( FALSE == mmc_init() )
113
  {
114
    uputs((uint8_t*)" -> Fehler Init. Ende\n");
115
    return -1;
116
  } 
117
118
  // fat config 
119
  if( FALSE == fat_loadFatData() )
120
  {
121
    uputs((uint8_t*)" -> Fehler loadFatData. Ende\n");
122
    return -1;
123
  }
124
125
  uputs((uint8_t*)" OK\n");
126
127
  // ********************** Datei schreiben **********************
128
  if( MMC_FILE_OPENED == ffopen(file_name,'r') )    // Oeffne existierende Datei zum anhaengen von Daten. Wenn geklappt
129
    ffseek(file.length);              // Gehe ans Ende der Datei
130
  else                         
131
    ffopen(file_name,'c');              // Lege Datei neu an
132
133
  ffwrites ((uint8_t*)"Hello world.");      
134
  sprintf (str, " File Size: %ld Bytes\r\n", file.length);  // DOS Zeilenumbruch
135
  ffwrites ((uint8_t*)str);
136
  ffclose();
137
138
  // ********************** Datei lesen **********************
139
140
  if( MMC_FILE_OPENED == ffopen(file_name,'r') )    // Datei zum lesen oeffnen
141
  {      
142
    seek = file.length;                // Dateigroesse
143
    do                        // Lese Byte ein
144
    {
145
      uputc( ffread() );            
146
    } while(--seek);                // bis alle Bytes der Datei eingelesen wurden
147
    ffclose();
148
  }
149
  
150
  return 0;
151
}

von Holger W. (mb_holger)


Lesenswert?

Zur Ergänzung der Controller ist der Atmega 16
Holger

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Hast du die passenden Bibliotheken? Und die Pfade richtig gesetzt?

von holger (Gast)


Lesenswert?

Du musst ALLE *.c Dateien aus dem Beispiel im AVR Studio
zum Projekt hinzufügen, nicht nur eine.

von Holger W. (mb_holger)


Lesenswert?

Danke, Danke das Brennen auf den Atmega hat funktioniert.

 mal sehen ob auf der SD Karte auch was zu lesen ist.


Noch eine dumme Frage warum müssen alle
*.c Dateien aus dem Beispiel im AVR Studio
zum Projekt hinzu? Ich dachte mit den Header Dateien *.h ist alles 
erledigt und alle nötigen Funktionen zum schreiben und lesen auf der 
Karte sind dadurch im Projekt?


Holger

von holger (Gast)


Lesenswert?

>Noch eine dumme Frage warum müssen alle
>*.c Dateien aus dem Beispiel im AVR Studio
>zum Projekt hinzu? Ich dachte mit den Header Dateien *.h ist alles
>erledigt und alle nötigen Funktionen zum schreiben und lesen auf der
>Karte sind dadurch im Projekt?

Header Dateien enthalten keine Funktionen. Sie sagen dem
Compiler nur wie Funktionen aufgerufen werden. Die
eigentliche Funktion steckt in der *.c Datei.
Wenn diese *.c nicht mit compiliert wird meckert
dann der Linker weil er die Funktion nicht finden kann
und meldet: undefined reference. Jedesmal wenn du also
undefined reference liest weisst du das du eine notwendige
*.c Datei nicht zum Projekt hinzugefügt hast. Oder eine
Library beim Linkeraufruf fehlt, aber das ist ein anderes Thema.

von Holger W. (mb_holger)


Lesenswert?

Hallo Holger,
hab ich nicht gleich erkannt du bist ja mein Namensvetter.

Super!! auf der SD Karte wurde die Datei Test.txt mit dem Inhalt
Hello world. File Size: 0 Bytes
Hello world. File Size: 33 Bytes
Hello world. File Size: 67 Bytes
geschrieben und konnte mit Windows gelesen werden.

nochmals Danke alleine wäre ich verzweifelt.

also muss ich dann bei jedem eigenen C Programm  wenn ich die Funktionen 
aus dem oben gezeigten Code zB.  ffwrites ((uint8_t*)"Hello world."); 
verwenden will immer alle Header Dateien *.h und alle *.c Datei aus dem 
Beispiel mit einfügen.

Das mit der SD Karte ist schwieriger als ich dachte.
Zum Verständnis gibt es auch Header Dateien *.h mit Funktionen? und kann 
ich die einzelnen *.c Datei Code in eine einzelne *.c Datei 
zusammenführen oder besser nicht.

Holger

von Holger W. (mb_holger)


Lesenswert?

Hallo
noch eine Frage wer kann mir sagen, was das uint8_t* mit Stern in 
ffwrites ((uint8_t*)"Hello world.")bedeutet und wie der Compiler im 
Projekt die Reihenfolge im Programmablauf der verschiedenen .c Datei 
Code erkennen kann, wenn im Projekt des AVR Studio mehrere c code 
eingebunden sind?
Holger

von Cyblord -. (cyblord)


Lesenswert?

Holger W. schrieb:
> Hallo
> noch eine Frage wer kann mir sagen, was das uint8_t* mit Stern in
> ffwrites ((uint8_t*)"Hello world.")bedeutet und wie der Compiler im
> Projekt die Reihenfolge im Programmablauf der verschiedenen .c Datei
> Code erkennen kann, wenn im Projekt des AVR Studio mehrere c code
> eingebunden sind?

Ein C-Buch...

Sorry wenn ich lese dass jemand ne SD-Karte nutzt, aber gleichzeitig 
keine Ahnung von den fundamentalen Grundlagen seiner Programmiersprache 
hat, da bekomm ich die Krätze.

: Bearbeitet durch User
von Kai M. (kai_mauer)


Lesenswert?

Cyblord -. schrieb:
> Ein C-Buch...
>
> Sorry wenn ich lese dass jemand ne SD-Karte nutzt, aber gleichzeitig
> keine Ahnung von den fundamentalen Grundlagen seiner Programmiersprache
> hat, da bekomm ich die Krätze.

Siehst Du: Mir geht's genau so, wenn ich Dein immer gleiches, saublödes
"von der Seite Annölen" in mindestens 10 Threads/Tag lesen soll.
Das hält man doch eigentlich im Kopf nicht aus...

von Cyblord -. (cyblord)


Lesenswert?

Kai M. schrieb:
> Cyblord -. schrieb:
>> Ein C-Buch...
>>
>> Sorry wenn ich lese dass jemand ne SD-Karte nutzt, aber gleichzeitig
>> keine Ahnung von den fundamentalen Grundlagen seiner Programmiersprache
>> hat, da bekomm ich die Krätze.
>
> Siehst Du: Mir geht's genau so

Hilft lieber dem TE anstatt hier Offtopic zu nölen. Bei persönlichen 
Problemen gibt's pn.

Du bist also nicht der Ansicht der TE sollte sich ein C-Buch gönnen? 
Warum nicht? Denkst du so ist alles ok? Wenn du ihm nun von Pointern 
erzählst und noch bisschen was über Funktionen. Dann läuft das? Los lass 
mal was zum Thema hören. Nur einmal.

: Bearbeitet durch User
von Kai M. (kai_mauer)


Lesenswert?

Cyblord -. schrieb:
> Hilft lieber dem TE anstatt hier Offtopic zu nölen.
Ich kann ihm nicht helfen, weil ich "C" für eine Dreckssprache halte.
Du willst ihm nicht helfen, obwohl Du es könntest.

Weil ich nicht helfen kann, halte ich die Pfoten still. Weil Du Dich 
abreagieren willst, tust Du das nicht, sondern textest den 
Fragesteller mit sinnlosem Mist zu.

Fazit: Weder Deine noch meine Antwort halfen ihm -nur: Mein Text wäre 
gar nicht geschrieben worden, wenn Du nicht Deinen Unsinn gepostet 
hättest.

> Bei persönlichen Problemen gibt's pn.

Darauf lege ich nicht den geringsten Wert.

von .. (Gast)


Lesenswert?

Cyblord -. schrieb:
> ..da bekomm ich die Krätze.

Dann geht zum Doktor oder lies es nicht.

@Holger Weiß

Beitrag "c code: Priorität & Lebensdauer Variable im Funktionsaufruf"
Beitrag "c code Unterschied uint8 buffer [8] und char buffer[8]"

Buch Tip:
Grundkurs C
von Jürgen Wolf
Verlag Galileo Computing
ISBN 978-3-8362-1546-66
EUR 9.90

von Holger W. (mb_holger)


Lesenswert?

Danke Ja ich bin Änfänger.


zur ersten Frage ffwrites ((uint8_t*)"Hello world.")
Macht also (uint8_t*)"Hello world." ein  ein Array vom Typ char als 
Argument für die Funktion ffwrites? Oder was hat der Stern hier für eine 
Aufgabe.

zu meiner zweiten Frage: Zu der Reihenfolge im Programmablauf könnte 
jemand einen Satz verlieren. Sind die anderen c Code nur Bibliotheken in 
denen nur die Funktionen definiert sind, die aufgerufen werden?


Ich habe zwei Bücher "C als erste Programmiersprache" und "C 
Programmieren von Anfang an" In diesen Bücheren habe ich nichts dazu 
gefunden, desshalb meine Fragen.

Das Buch "Grundkurs C von Jürgen Wolf" habe ich soeben bestellt.

Ich brauche hier keine ausführliche Beschreibung, nur einen Denkanstoß.
was mit dem Stern ist.

Danke Holger

von Falk B. (falk)


Lesenswert?

@ Holger Weiß (mb_holger)

>Macht also (uint8_t*)"Hello world." ein  ein Array vom Typ char als
>Argument für die Funktion ffwrites? Oder was hat der Stern hier für eine
>Aufgabe.

"Hello world." ist ein konstanter String, also ein Array aus chars.
Der Funktion ffwrites wird der ZEIGER auf dieses Array übergeben. Dieser 
Zeiger ist vom Typ char* (Zeiger auf char)
(uint8_t*) ist ein Cast. D.h. der Zeiger auf char (char*) wird zum 
Zeiger auf uint8_t (uint8_t*) umdeklariert. Technisch sind char und 
uint8_t nahezu identisch, es ist ein einfaches Bytes. Aber C ist etwas 
pingelig und nimmt es hier genau. Ohnde den Cast würde dein Compiler 
eine Warnung erzeugen, weil ein falscher Zeigertyp an die Funktion 
übergeben wird. Mit Cast kommt keine Warnung.

von Holger W. (mb_holger)


Lesenswert?

ich muß noch mal nerven zu ffwrites ((uint8_t*)"Hello world."). Sowei 
habe ich alles verstanden. Der Funktion wird der Zeiger auf dem String 
übergeben.

Ist der Klammeroperator um (uint8_t*) wegen der Priorität in dem 
Ausdruck(uint8_t*)"Hello world.", aber bei zum Beispiel
ffwrites ((uint8_t*)str) ergibt es keinen Sinn wegen der Priorität. Also 
warum ist (uint8_t*) in Klammern?

Danke Holger

von easylife (Gast)


Lesenswert?

-> casting

von Holger W. (mb_holger)


Lesenswert?

(uint8_t*)"Hello world." hab ich verstanden.

"Hello world." ist ein Array aus chars. Wie kann eine unit8_t den 
Speicherbereich des  Array aus chars darstellen ? müßte der Zeiger auf 
ein
Array nicht wenigstens auch ein Array sein?
Holger

von Karl H. (kbuchegg)


Lesenswert?

Holger W. schrieb:
> (uint8_t*)"Hello world." hab ich verstanden.
>
> "Hello world." ist ein Array aus chars. Wie kann eine unit8_t den
> Speicherbereich des  Array aus chars darstellen ? müßte der Zeiger auf
> ein
> Array nicht wenigstens auch ein Array sein?

Zeiger ist Zeiger.

Ein Zeiger ist einfach nur die Adresse im Speicher an der sich etwas 
befindet.
Im Speicher stehen Bytes. Irgendwelche Bytes. Im Speicher gibt es keine 
Markierung, was da an dieser Stelle steht. Da stehen einfach nur Bytes.

Was an einer Stelle im Speicher zu finden ist, das definiert sich durch 
die Verwendung.

Wenn ich schreibe
1
  int i = 48;

(Annahme: 16 Bit int)
dann werden dafür im Speicher 2 Bytes reserviert und in diese beiden 
Bytes werden die entsprechenden Bits so geschrieben, dass sich daraus 
die int-Zahl 48 ergibt, WENN man diese beiden Bytes als int 
interpretiert.
Ich muss sie aber nicht als int interpretieren. Das ich das tue, liegt 
einzig und alleine daran, dass ich die Variable als int definiert habe, 
so dass der Compiler davon ausgeht, dass wenn ich schreibe
1
  k = 2 * i;
ich haben will, dass er von der Speicheradresse an der i zu liegen 
kommt, ich 2 Bytes holen möchte, die als int interpretiert werden.

Das ist eine der Grundannahmen. Definiere ich irgendetwas von einem 
Datentyp, dann möchte ich dieses auch genau in diesem Sinne verwendet 
haben.

Das muss aber nicht so sein. Ich kann den Compiler auch überstimmen. Ich 
kann sagen: Hey, ist mir doch scheiss egal, ob da die beiden Bytes im 
Speicher eigentlich einen int formen, ich will jetzt, dass wir mal 
kurzzeitig so tun, als ob da nur ein einzelnes Byte liegen würde - und 
genau diesen einzelnen Bytewert will ich haben. Nimm also die Adresse 
von diesem ominösen i, wo auch immer das im Speicher liegt, und dann tun 
wir mal so, also ob an dieser Stelle zb ein uint8_t im Speicher liegen 
würde (also 1 Byte) - und genau dieses Byte will ich haben.
1
    *(uint8_t*)&i

Ich kann auch sagen: (Selbes Spielchen) Vergiss, dass dort im Speicher 
ein int liegt. Ich will haben, dass du die Adresse an der i im Speicher 
liegt so auffasst, als ob dort ein double im Speicher liegen würde. Hol 
dir also die Anzahl an Bytes von dort aus dem Speicher, die für einen 
double benötigt werden und tu so als ob das tatsächlich ein double wäre
1
    *(double*)&i

oder ich kann ihm jeden anderen Datentyp (auch Strukturen oder Unions 
oder Arrays oder Arrays von Strukturen) aufs Auge drücken. Und wenn ein 
AVR keine Harvard Architektur hätte, dann könnte ich dem Compiler auch 
dazu zwingen so zu tun, als ob an dieser Stelle im Speicher die 
Maschinenbefehle einer Funktion zu finden sind, die aufgerufen werden 
soll.

Und damit sind wir bei Casts und bei der Frage warum zum Teufel du noch 
immer kein C Buch hast. Schön langsam sollte es doch auch dir dämmern, 
dass es eine Unmenge an Kleinigkeiten gibt, die man wissen muss und ohne 
deren Kentniss man nicht vernünftig ein Programm schreiben kann.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Holger W. schrieb:

> Wie kann eine unit8_t den
> Speicherbereich des  Array aus chars darstellen ?

Wer sagt denn das?

Da steht
1
    ... (uint8_t*) ....

und nicht
1
    ... (uint8_t) ...

> müßte der Zeiger auf
> ein
> Array nicht wenigstens auch ein Array sein?

Ein Zeiger ist einfach nur eine Speicheradresse, die angibt an welcher 
Stelle im Speicher etwas zu finden ist. Was dieses 'etwas' darstellt, 
wird durch den beim Zeiger angegebenen Datentyp definiert. Hier
1
   .... (uint8_t*) ....

wird halt ausgesagt: an dieser Stelle im Speicher liegt ein uint8_t. Und 
da sich der Computer nicht wehren kann, wenn du den so erhaltenen Zeiger 
einfach um 1 erhöhst, ist damit auch implizit enthalten: und an den 
folgenden Speicherstellen liegen ebenfalls uint8_t, wenn man den 
Zeigerwert entsprechend inkrementiert/erhöht. Datentypen ändern sich ja 
nicht, wenn man die Werte inkrementiert. Erhöhe ich den Zeigerwert um 1, 
dann hat der Zahlenwert der Adresse jetzt einen anderen Wert. Aber er 
zeigt nach wie vor auf einen uint8_t, wenn er das vorher tat. Und das er 
das tat, dafür hat ja der Datentyp (wenn auch mit einem Cast erzwungen) 
schon gesorgt.

: Bearbeitet durch User
von Holger W. (mb_holger)


Lesenswert?

vielen Dank für eure Geduld,
ein Buch für Einsteiger habe ich damit komme ich nicht weiter. Ich habe 
euren Rat befolgt und noch 2  Bücher bestellt.
Zu den Zeigern habe ich noch eine Unklarheit. Ein Zeiger beinhaltet eine 
Adresse
im Speicher je nach Architektur zb. bei 32 bit beinhaltet  eine Adresse 
2 Byte?  Viele Variablen oder Konstanten haben einen Adressbereich also 
mehrere Byte. Wird durch den Datentyp im Zeiger der Adressbereich 
bestimmt und ist der Zeiger immer die Adresse des ersten Bytes des 
Bereiches der Variablen. Ist also ein Zeiger immer nur eine Adresse und 
der Datentyp bestimmt die Anzahl der folgenden und somit den 
Adressbereich?

Kann es durch einen Cast zu Überschneidungen oder Konflikten kommen zb. 
bei globalen oder static  ?

Holger

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Holger W. schrieb:
> ein Buch für Einsteiger habe ich damit komme ich nicht weiter.

Hm, merkwürdig. In dem Buch für Anfänger steht nix zu Zeiger und 
Datentypen?

> Zu den Zeigern habe ich noch eine Unklarheit.
> .. dies und das ..

Ja. Eine Variable (egal in welcher Programmiersprache) besteht aus 
mehreren "Teilen":

einem Varaiablen-Namen:  DonauDampfSchiffahrtsKapitänPatentNummer
einem Daten-Typ       : integer
einem definierten Größe an Speicherplatz, welche so eine Variable 
benötigt: (z.B. 2 bytes)
einem "lagerort" im Speicher (wen eine solche Variable existiert (z.B. 
0xabcd

einen Wert, den solch eine Variable annehmen kann, z.B. 4711, oder 
-0815, oder <null> (= uninitialisiert, kein definierter Wert)

dann gibts dann vielleicht noch ein weiteres Objekt, nämlich einem 
Zeiger, der auf Objekte vom Typ xx(z.B. Integer) zeigt
(der Zeiger selbst hat natürlich auch wieder eine gewisse Größe, z.B. 2 
bytes)

naja, und schließlich ist der Wert (Inhalt) des Zeigers gleich der 
Speicheradresse auf das Objekt, auf das er zeigt.

in C ist der Stern '*' zu lesen als "Zeiger auf", und der '&' läßt sich 
lesen als "Adresse von"

: Bearbeitet durch User
von Holger W. (mb_holger)


Lesenswert?

Wegstaben V. schrieb:
> (der Zeiger selbst hat natürlich auch wieder eine gewisse Größe, z.B. 2
> bytes

ja, das ist mir alles klar. ich hatte nur die spezielle Frage zur Größe 
des Zeigers bzw dessen Adressbereich.



Ein Zeiger beinhaltet eine Adresse.
im Speicher je nach Architektur zb. bei 32 bit beinhaltet  eine Adresse
2 Byte.  Viele Variablen oder Konstanten haben einen Adressbereich also
mehrere Byte. Wird durch den Datentyp im Zeiger der Adressbereich
bestimmt und ist der Zeiger immer die 1.Adresse  des
Bereiches der Variablen. Ist also ein Zeiger immer nur eine Adresse und
der Datentyp bestimmt die Anzahl der folgenden und somit den
Adressbereich?

Kann es durch einen Cast zu Überschneidungen oder Konflikten kommen zb.
bei globalen oder static ?

von Holger W. (mb_holger)


Lesenswert?

Beispiel:
Ein long int aus den Bytes an den Adressen 100, 101, 102 und 103 hat die 
Adresse 100.
Ein direkt benachbartes long int hat die Adresse 104 (Bytes 104, 105, 
106, 107).

Wird durch den Datentyp im Zeiger der Adressbereich
bestimmt und ist der Zeiger immer die 1.Adresse  des
Bereiches der Variablen. Ist also ein Zeiger immer nur eine Adresse und
der Datentyp bestimmt die Anzahl der folgenden und somit den
Adressbereich?

Ein Zeiger zeigt auf eine Adresse(32bit System 4 Byte) oder nur auf ein 
Byte?

Kann es durch einen Cast zu Überschneidungen oder Konflikten kommen zb.
bei globalen oder static ?

Danke Holger

von Karl H. (kbuchegg)


Lesenswert?

Holger W. schrieb:
> Wegstaben V. schrieb:
>> (der Zeiger selbst hat natürlich auch wieder eine gewisse Größe, z.B. 2
>> bytes
>
> ja, das ist mir alles klar. ich hatte nur die spezielle Frage zur Größe
> des Zeigers

Die Größe des Zeigers selbst ist durch die Architektur definiert und 
wieviel Speicher in dieser Architektur überhaupt adressierbar ist. Ist 
die Architektur so, dass die Hardware nicht mehr als 64kByte mximal 
hergibt, dann werden die Adressen wohl so bemessen sein, dass damit alle 
überhaupt vorkommenden Adressen damit abgebildet werden können. Bei 64kB 
sind das 2 Bytes. Kann eine Hardware mehr adressieren, dann werden auch 
Adressen (und damit Zeiger Variablen, die ja Adressen Speichern können 
müssen) auch entsprechend größer sein.
Du bemisst ja den Platz auf einem Briefkuvert auch danach, welches die 
längste vorkommende Adresse sein wird.

(Um die Sache nicht zu verkomplizieren, lass ich jetzt erst mal 
segmentierte Architekturen aussen vor)

> bzw dessen Adressbereich.

Wie gross das Objekt ist, auf das mittels eines Zeigers verwiesen wird, 
das ist deswegen bekannt, weil man ja nicht einfach nur definiert, dass 
man eine Zeiger Variable hat
1
   zeiger MeinZeiger;
sondern weil man ja definiert
1
   int * MeinZeiger;
dass dieser Zeiger auf einen int zeigt, oder das
1
   double * MeinZeiger;
dieser Zeiger auf einen double zeigt, oder dass
1
  struct irgendeineStruktur * MeinZeiger;
dieser Zeiger auf ein Objekt vom Typ 'struct irrgendeineStruktur' zeigt.

In allen Fällen ist damit bekannt, wie gross der 'Adressbereich' dessen 
ist, worauf der Zeiger zeigt.

> Ein Zeiger beinhaltet eine Adresse.
> im Speicher je nach Architektur zb. bei 32 bit beinhaltet  eine Adresse
> 2 Byte.

Kann sein, kann auch nicht sein. Mit 32 Bit hat das erst mal nichts zu 
tun, sondern damit, wie gross der vom Prozessor bearbeitbare Adressraum 
überhaupt ist.

WEnn du wissen willst, wie gross bei dir konkret ein Zeiger ist, warum 
fragst du dann nicht einfach deinen Compiler? Der weiss das.
1
int main()
2
{
3
  printf( "%lu\n", (unsigned long)sizeof(void*) );
4
}

> Bereiches der Variablen. Ist also ein Zeiger immer nur eine Adresse und
> der Datentyp bestimmt die Anzahl der folgenden und somit den
> Adressbereich?

genauso ist es.
Bytes im Speicher haben kein Mascherl.

> Kann es durch einen Cast zu Überschneidungen oder Konflikten kommen zb.
> bei globalen oder static ?

Natürlich.
Mit einem Cast kannst du alles anstellen, weil du effektiv jegliche 
Datentypprüfung des Compilers damit abschaltest. Mit einem Cast 
übernimmst du selbst die Verantwortung, das alles in Ordnung ist.

: Bearbeitet durch User
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.