Telefonino.net network
 
| HOMEPAGE | INDICE FORUM | REGOLAMENTO | ::. NEI PREFERITI .:: | RSS Forum | RSS News | NEWS web | NEWS software |
| PUBBLICITA' | | ARTICOLI | WIN XP | VISTA | WIN 7 | REGISTRI | SOFTWARE | MANUALI | RECENSIONI | LINUX | HUMOR | HARDWARE | DOWNLOAD | | CERCA nel FORUM » |

Torna indietro   WinTricks Forum > Software > Programmazione

Notices

Rispondi
 
Strumenti discussione
Vecchio 24-04-2007, 12.00.55   #1
Flavio58
Junior Member
 
L'avatar di Flavio58
 
Registrato: 12-04-2007
Messaggi: 96
Flavio58 promette bene
I puntatori del C

Quando si vuole gestire l'ottica dei puntatori si deve avere sempre a mente che in effetti i dati sono memorizzati in certe locazioni di memoria e che a seconda dei tipi questi tengono un certo numero di bytes.
Un puntatore è come una variabile normale ma solo che il valore che contiene è un indirizzo di un altra locazione di memoria dove viene mantenuto un valore di un ceryo tipo.
In genere quando si cedono cose del tipo :

char *c;
int *c;
struct abc *c;

uno si chiede : ma se un puntatore è uno spazio sufficente a contenere un indirizzo cosa me ne frega di scrivere int *, char * ecc. visto che alla fine gli indirizzi sono sempre lunghi uguale ?
Perchè il tipo dice al sistema che il dato a quell'indirizzo è di un certo tipo e quindi occupa N bytes.
La tipologia influsice sull'aritmetica dei punatori.

In pratica se io avessi :

int *n = (int *) 0x00000C000;

e se poi incrementassi l'indirizzo cosi :

++n;

Di quanti bytes verrebbe incrementato n ?
Semplicemente di :

n = n + (1 * sizeof(int));

ovvero, nel caso di int = 4 bytes, di 4 bytes appunto !
L'aritmetica dei punatori è potente.
Prendete ad esempio il problema di copiare 10 bytes di un array in un altro array.
Norlamente tutti farebbero :

int a[10] = { 1,2,3,4,5,6,7,8,9,0 };
int b[10];

int x;

for(x=0;x!=10;i++)
b[x] = a[x];


Con i punatori potrei fare un codice, che se andate a vederlo in assembler tradotto dal compilatore, molto piu' compatto :

int a[10] = { 1,2,3,4,5,6,7,8,9,0 };
int b[10];
struct x { int a[10]; }; // Solo definizione -- NON DICHIRAZIONE

(*((struct x * )(&b[0]))) = (*((struct x * )(&a[0])));

o

(*((struct x * )(b))) = (*((struct x * )(a)));

Uno comunque potrebbe chiedersi perchè dover usare costrutti come quello di prima e non il semplice ciclo.
Ottimizzazione velocità ....
Se uno scrive gestionale certi tipi di ottimizzazioni può anche evitarle...se invece fai sistemi di compuetr vision allora tutto quello che ottimizza diventa necessario.....
GUarda qui ad esempio :

Codice:
int a[5] = { 1,2,3,4,5 };
int b[5];


void copia(void)
{
struct p { int f[5]; };
(*((struct p *)(b))) = (*((struct p *)(a)));
}
tradotto dal compilatore con l'opzione Fa

Codice:
    TITLE    test1.c
    .386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT    SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT    ENDS
_DATA    SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA    ENDS
CONST    SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST    ENDS
_BSS    SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS    ENDS
_TLS    SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS    ENDS
FLAT    GROUP _DATA, CONST, _BSS
    ASSUME    CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC    _a
_DATA    SEGMENT
COMM    _b:DWORD:05H
_a    DD    01H
    DD    02H
    DD    03H
    DD    04H
    DD    05H
_DATA    ENDS
PUBLIC    _copia
_TEXT    SEGMENT
_copia    PROC NEAR
; File test1.c
; Line 6
    push    ebp
    mov    ebp, esp
    push    esi
    push    edi
; Line 8
    mov    ecx, 5
    mov    esi, OFFSET FLAT:_a
    mov    edi, OFFSET FLAT:_b
    rep movsd
; Line 9
    pop    edi
    pop    esi
    pop    ebp
    ret    0
_copia    ENDP
_TEXT    ENDS
END
Codice:
int a[5] = { 1,2,3,4,5 };
int b[5];
int i;

void copia(void)
{
 for(i=0;i!=5;i++)
           b[i] = a[i];
 }
Codice:
    TITLE    test2.c
    .386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT    SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT    ENDS
_DATA    SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA    ENDS
CONST    SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST    ENDS
_BSS    SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS    ENDS
_TLS    SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS    ENDS
FLAT    GROUP _DATA, CONST, _BSS
    ASSUME    CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC    _a
_DATA    SEGMENT
COMM    _b:DWORD:05H
COMM    _i:DWORD
_a    DD    01H
    DD    02H
    DD    03H
    DD    04H
    DD    05H
_DATA    ENDS
PUBLIC    _copia
_TEXT    SEGMENT
_copia    PROC NEAR
; File test2.c
; Line 6
    push    ebp
    mov    ebp, esp
; Line 7
    mov    DWORD PTR _i, 0
    jmp    SHORT $L35
$L36:
    mov    eax, DWORD PTR _i
    add    eax, 1
    mov    DWORD PTR _i, eax
$L35:
    cmp    DWORD PTR _i, 5
    je    SHORT $L37
; Line 8
    mov    ecx, DWORD PTR _i
    mov    edx, DWORD PTR _i
    mov    eax, DWORD PTR _a[edx*4]
    mov    DWORD PTR _b[ecx*4], eax
    jmp    SHORT $L36
$L37:
; Line 9
    pop    ebp
    ret    0
_copia    ENDP
_TEXT    ENDS
END
___________________________________

Flavio Bernardotti
Portale programmazione avanzate e sicurezza biometrica
http://www.bernardotti.it
Flavio58 non è collegato   Rispondi citando
Vecchio 24-04-2007, 12.36.26   #2
LoryOne
Gold Member
WT Expert
 
Registrato: 09-01-2002
Loc.: None of your business
Messaggi: 5.502
LoryOne è un gioiello raroLoryOne è un gioiello raroLoryOne è un gioiello raro
Bene, questo post dovrebbe essere messo in coda ai precedenti, quando abbiamo trattato in maniera molto più soft i puntatori.
Flavio incita ad apprendere anche Assembly, giustamente.

Vorrei far notare il primo codice Assembly , quello della copia del blocco della struttura in un' unica riga di codice in C.
memcpy o CopyMemory effettuano esattamente la stessa cosa.

Ottimizzazione delle risorse e velocità d'esecuzione dovrebbero sempre essere rispettate, qualunque sia il contesto in cui l' applicazione deve "girare". E' chiaro che dal lato Assembly, l'architettura del processore e dei vari registri messi a disposizione del programmatore possono influire sull'incremento prestazionale, così come allocare dati in locazioni di memoria pari oppure dispar,i in base alla tipologia ed alla quantità dei bytes da indirizzare

Ottimo post. (Y)
LoryOne non è collegato   Rispondi citando
Vecchio 24-04-2007, 14.43.58   #3
Flavio58
Junior Member
 
L'avatar di Flavio58
 
Registrato: 12-04-2007
Messaggi: 96
Flavio58 promette bene
Un altro esempio per fare capire che alla fine un puntatore è di fatto un indirizzo è quello che alla fine è alla base del concetto di buffer overflow nelle tecniche di hacking.
Se noi prendiamo un programma e lo guardiamo con il debug in modalità esadecimale possiamo vedere le istruzioni binarie come se fossero degli array di numeri.
Ad esempio un programmino molto corto chiamato boot.com che non faceva altro che resettare la macchina può essere visto in modalità esadeciomale ed essere assegnato ad un array di numeri interi.

Codice:
 unsigned char array[] = {
                                /* ---- [CODICE  DI BOOT.COM] ---- */
                0xFB,0x31,0xDB, /* FB            STI               */
                0x8E,0xDB,0xBB, /* 31DB          XOR     BX,BX     */
                0x72,0x04,0xB8, /* 8EDB          MOV     DS,BX     */
                0x34,0x12,0x89, /* BB7204        MOV     BX,0472   */
                0x07,0xEA,0x00, /* B83412        MOV     AX,1234   */
                0x00,0xFF,0xFF  /* 8907          MOV     [BX],AX   */
                                /* EA0000FFFF    JMP     FFFF:0000 */
                                /* ------------------------------- */
        };
Ora se dichiarassimo un puntaore a funzione in pratica avremmo uno spazio in memoria per contenere un indirizzo, che si suppone essere di una funzione.
Il C possiede il concetto di CAST o forzatura.
In pratica un certo tipo viene forzato ad assumere le proprietà di un altro tipo.
Per cui se noi avessimo il puntatore a funzione :

void (far *funct)()

&array[0] o semplicemente array (gli array il c li vede come indirizzi) sarebbe a questo punto l'indirizzo del primo elemernto del vettore.
Ma se mediante un cast noi lo assegnassimo al puntaore a funzione con :

void (*funct)() = (void(*)()) array;

costringeremmo il C a vedere funct come un puntatore a funzione il cui indirizzo di fatto è quello del primo elemento dell'array.
Ma una funzione può essere richiamata !
E quindi ....

(*funct)();

non farebbe altro che chiamare la funziopne all'indirizzo &array[0].
Il C salterebbe a questo indirizzo convinto che sia una funzione e quindi eseguirebbe i codici all'interno che di fatto sono querlli di boot.com ....
Detto in altre parole: come fare eseguire al sistema dei numeri esadecimali (convincendolo che sono codici operativi binari) !!!
___________________________________

Flavio Bernardotti
Portale programmazione avanzate e sicurezza biometrica
http://www.bernardotti.it
Flavio58 non è collegato   Rispondi citando
Rispondi


Utenti attualmente attivi che stanno leggendo questa discussione: 1 (0 utenti e 1 ospiti)
 
Strumenti discussione

Regole di scrittura
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is ON
Gli smilies sono ON
[IMG] è ON
Il codice HTML è OFF

Vai al forum

Discussioni simili
Discussione Autore discussione Forum Risposte Ultimo messaggio
[C] Problemi con i puntatori Nanri Programmazione 11 20-09-2005 15.12.36
Problema di paging, File System e puntatori animati in Win ME Ciobby Windows 9x/Me/NT4/2000 4 11-05-2005 00.20.35
Puntatori a carattere otto_cb Programmazione 7 21-08-2004 00.18.27
(C) Chiarimento sui puntatori Far - Huge Topov Programmazione 4 06-08-2004 12.56.18
Aiuto puntatori GiulioCesare Programmazione 1 12-11-2003 09.09.39

Orario GMT +2. Ora sono le: 19.24.49.


E' vietata la riproduzione, anche solo in parte, di contenuti e grafica.
Copyright © 1999-2017 Edizioni Master S.p.A. p.iva: 02105820787 • Tutti i diritti sono riservati
L'editore NON si assume nessuna responsabilità dei contenuti pubblicati sul forum in quanto redatti direttamente dagli utenti.
Questi ultimi sono responsabili dei contenuti da loro riportati nelle discussioni del forum
Powered by vBulletin - 2010 Copyright © Jelsoft Enterprises Limited.