warning: initialization makes pointer from integer without a cast

11/12/2011 - 16:51 von Thomas - Pronto - Wildgruber | Report spam
Hi Group,

ich versuche gerade das Verhalten von Arrays und Zeigern im
Speicher zu verstehen und habe mir dazu folgendes (eigentlich
sinnfreies) Programm zurecht gebastelt:

snip
#include <stdio.h>

int main() {
char carray[3] = {'a', 'b', 'c'};
int iarray[3] = {1,2,3};
char *i = "abc";
int *k = iarray[1];
return 0;
}
snap

Beim kompilieren wird mir folgende Warnung ausgegeben:

snip
ptr_array_1.c: In function ‘main’:
ptr_array_1.c:7:12: warning: initialization makes pointer from
integer without a cast
snap

Welche Typumwandlung würde der Compiler bei der Initialisierung
des Zeigers *k erwarten? Der Zeiger *k wird mit der Adresse des
zweiten Elements des Integer Arrays iarray initialisiert (was auch
funktioniert[*]) und ich dachte dann, dass der Tsp Integer wohl zu
klein für eine 4 Byte Adresse ist aber eine Typumwandlung nach
'(long int)iarray[1]' brachte die gleiche Warnung.

[*]--snip--
(gdb) list
1 #include <stdio.h>
2
3 int main() {
4 char carray[3] = {'a', 'b', 'c'};
5 int iarray[3] = {1,2,3};
6 char *i = "abc";
7 int *k = iarray[1];
8 return 0;
9 }
10
(gdb) break 8
Breakpoint 1 at 0x80483c8: file ptr_array_1.c, line 8.
(gdb) disas main
Dump of assembler code for function main:
0x08048394 <+0>: push ebp
0x08048395 <+1>: mov ebp,esp
0x08048397 <+3>: sub esp,0x20
0x0804839a <+6>: mov BYTE PTR [ebp-0x3],0x61
0x0804839e <+10>: mov BYTE PTR [ebp-0x2],0x62
0x080483a2 <+14>: mov BYTE PTR [ebp-0x1],0x63
0x080483a6 <+18>: mov DWORD PTR [ebp-0x18],0x1
0x080483ad <+25>: mov DWORD PTR [ebp-0x14],0x2
0x080483b4 <+32>: mov DWORD PTR [ebp-0x10],0x3
0x080483bb <+39>: mov DWORD PTR [ebp-0x8],0x8048490
0x080483c2 <+46>: mov eax,DWORD PTR [ebp-0x14]
0x080483c5 <+49>: mov DWORD PTR [ebp-0xc],eax
0x080483c8 <+52>: mov eax,0x0
0x080483cd <+57>: leave
0x080483ce <+58>: ret
End of assembler dump.
(gdb) run
Starting program: /home/pronto/booksrc/C_1/ptr_array_1

Breakpoint 1, main () at ptr_array_1.c:8
8 return 0;
(gdb) i r $ebp
ebp 0xbffff6e8 0xbffff6e8
(gdb) x/x 0xbffff6e8 -20
0xbffff6d4: 0x00000002
snap

In der Zeile <+46> wird der Zeiger *k erwartungsgemàß mit der
Adresse des zweiten Elements dess Integer Arrays iarray
initialisiert ([ebp-0x14]), welche erwartungsgemàß die Zahl 2
enthàlt (0xbffff6d4: 0x00000002). Demnach làuft alles so, wie ich
es erwartet habe und produziert imho sinnvollen Maschinencode.

Da ich ja weiß, dass der Zeiger *k mit einer Adresse initialisiert
wird, habe ich im Code bei der Initialisierung mal den
Adressoperator & verwendet und die Compilerwarnung war zwar
verschwunden aber der Maschinencode wurde dafür etwas
umstàndlicher:

snip
(gdb) list
1 #include <stdio.h>
2
3 int main() {
4 char carray[3] = {'a', 'b', 'c'};
5 int iarray[3] = {1,2,3};
6 char *i = "abc";
7 int *k = &iarray[1];
8 return 0;
9 }
10
(gdb) break 8
Breakpoint 1 at 0x80483cb: file ptr_array_1.c, line 8.
(gdb) disas main
Dump of assembler code for function main:
0x08048394 <+0>: push ebp
0x08048395 <+1>: mov ebp,esp
0x08048397 <+3>: sub esp,0x20
0x0804839a <+6>: mov BYTE PTR [ebp-0x3],0x61
0x0804839e <+10>: mov BYTE PTR [ebp-0x2],0x62
0x080483a2 <+14>: mov BYTE PTR [ebp-0x1],0x63
0x080483a6 <+18>: mov DWORD PTR [ebp-0x18],0x1
0x080483ad <+25>: mov DWORD PTR [ebp-0x14],0x2
0x080483b4 <+32>: mov DWORD PTR [ebp-0x10],0x3
0x080483bb <+39>: mov DWORD PTR [ebp-0x8],0x80484a0
0x080483c2 <+46>: lea eax,[ebp-0x18]
0x080483c5 <+49>: add eax,0x4
0x080483c8 <+52>: mov DWORD PTR [ebp-0xc],eax
0x080483cb <+55>: mov eax,0x0
0x080483d0 <+60>: leave
0x080483d1 <+61>: ret
End of assembler dump.
(gdb) run
Starting program: /home/pronto/booksrc/C_1/ptr_array_1

Breakpoint 1, main () at ptr_array_1.c:8
8 return 0;
(gdb) i r $ebp
ebp 0xbffff6e8 0xbffff6e8
(gdb) x/x 0xbffff6e8 -24
0xbffff6d0: 0x01
(gdb) x/x 0xbffff6e8 -20
0xbffff6d4: 0x02
snap

Demnach wird zuerst die Adresse des ersten Elements des Integer
Arrays iarray in das EAX Register geladen (lea eax,[ebp-0x18])
und darauf werden dann vier Byte (Integer) addiert (add eax,0x4),
was dann wieder auf das zweite Element des Integer Arrays zeigt.

Der langen Rede kurzer Sinn: Warum muss bei der Initialisierung
eines Zeigers, der per Definition eh schon auf eine Adresse zeigt,
zusàtzlich der Adressoperator & verwendet werden?

Thx & Bye Tom
 

Lesen sie die antworten

#1 Heinrich Wolf
11/12/2011 - 17:23 | Warnen spam
"Thomas - Pronto - Wildgruber" schrieb im Newsbeitrag
news:
...
int main() {
char carray[3] = {'a', 'b', 'c'};
int iarray[3] = {1,2,3};
char *i = "abc";
int *k = iarray[1];



k ist ein (int*), ein Zeiger auf int.
iarray[1] ist ein int, kein Zeiger

return 0;
}
snap

Beim kompilieren wird mir folgende Warnung ausgegeben:

snip
ptr_array_1.c: In function ‘main’:
ptr_array_1.c:7:12: warning: initialization makes pointer from
integer without a cast
snap

Welche Typumwandlung würde der Compiler bei der Initialisierung
des Zeigers *k erwarten? Der Zeiger *k wird mit der Adresse des



int k = iarray[1];

oder

int *k = iarray + 1;

zweiten Elements des Integer Arrays iarray initialisiert (was auch
funktioniert[*]) und ich dachte dann, dass der Tsp Integer wohl zu
klein für eine 4 Byte Adresse ist aber eine Typumwandlung nach
'(long int)iarray[1]' brachte die gleiche Warnung.

[*]--snip--


...

Ähnliche fragen