Newsgroup: it.comp.lang.c
Titolo: come freezare un pentium e vivere felici

char x [5] = { 0xf0, 0x0f, 0xc7, 0xc8 };
main ()
{
void (*f)() = x;
f();
}
questo codice fa crashare i processori pentium intel (usando un bug presente
nei suddetti). Vorrei che mi spiegaste il costrutto usato in main()... cosa
significa quel void (*f)() = x? e dove viene dichiarata la funzione f() che
usa poi?
PS. Non voglio saperlo per provocare chissa quali disastri, ma ne ho bisogno
dato che sto imparando il c/c++     ;Ź)
ciao e grazie, Sergio

 usa poi?
Come avrai capito da quanto sopra, lo statment f() chiama la funzione
puntata dalla variabile f; il corpo di tale funzione e' costituito quindi
dalle istruzioni codificate dai byte 0xf0 0x0f 0xc7 0xc8. Se prendi un
buon manuale di assembler, scopri anche cosa vuol dire...
Notare che la tecnica qui presentata per inserire codice macchina nei
sorgenti C non viene quasi mai usata, perche' richiede l'inserimento del
codice macchina, obbligando a fare "a mano" il passaggio da codici
mnemonici delle istruzioni ASM a codifiche binarie.
			Ciao,
				Luca

usa poi?
"void (*f)() = x;" dichiara la variabile locale f come puntatore ad una
funzione che prende argomenti di numero e tipo non precisato (in C;
in C++, sarebbe una funzione che non prende argomenti) e non torna
alcun risultato; e la definisce, inizializzandola con l'indirizzo iniziale
dell'array di byte "x".  Un compilatore C standard non dovrebbe pero`
accettare questa linea, in quanto il tipo di "x" e` "char*", che non e`
compatibile con il tipo "void (*)()", che e` quello di f; ci vorrebbe un
cast -- senza di esso, il codice non dovrebbe compilare.
In generale, poi, non e` detto che dei dati possano essere usati come
codice eseguibile; un sistema operativo puo` benissimo scegliere di
tenere dati e codice in pagine diverse, col bit "permesso di eseguire"
settato solo per le pagine di codice, e non per quelle di dati.  Il C
standard non garantisce quindi nessuna intercambiabilita` fra i
puntatori a dati (compreso il generico "void*") e i puntatori a funzioni
(codice eseguibile).
Alex

 Alex
Per concludere, un compilatore che accetti codice del genere non rispetta lo
standard ANSI. Detto altrimenti, non e' C, non deve essere quindi usato se si
vuole programmare in C. Il metodo meno non-standard per inserire commandi
assembler e' usare la keyword #asm. Questa e' una estensione accettata
dall'ANSI, anche se non e' richiesta.
Ciao Paolo
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/
       Search, Read, Discuss, or Start Your Own    

 compilare questo codice.
Non mi è chiara la differenza!?
Comunque, quello che mi preme sottolineare è che, proprio perchè
parliamo di C e non di C++, AFAIK il cast *non* è obbligatorio, ed un
compilatore C conforme dovrebbe limitarsi a generare un warning... o no?
Saluti, julio di egidio
ju...@webzone.it

standard ANSI. Detto altrimenti, non e' C, non deve essere quindi usato se si
Un compilatore che accetti questo codice con uno o piu` warning
rispetta lo standard ISO (l'unico standard esistente al mondo per
il linguaggio C); e` inoltre molto comune che, a seconda di "switch"
e "opzioni" passati al compilatore, i warning possano essere emessi
o meno (questo non viola lo standard, purche` esistano "switch" che
provocano i warning; ad esempio, il diffusissimo compilatore gcc e`
Standard ISO solo se chiamato con gli "switch"
    -ansi -pedantic
[evidentemente anche loro chiamano "ANSI" quel che ANSI non e`
piu` da tanto, tanto tempo...]).
Alex

compilatore C conforme dovrebbe limitarsi a generare un warning... o no?
Un compilatore C standard, a fronte della situazione che stiamo
discutendo, in pratica:
    char *x;
    void (*f)() = x;
deve generare per il programma almeno una diagnostica, e puo`
o meno produrre un programma eseguibile (se lo produce, il suo
comportamento e` undefined).  Non vi e`, che io sappia, alcuna
differenza in questo fra gli standard ISO per i linguaggi C e C++
(e` una delle aree in qui quest'ultimo "include per riferimento"
il primo).
Alex

 memoria e dovrebbe essere segnalata dal compilatore.
Non credo; in questo caso l'ultimo elemento dell'array non e'
inizializzato esplicitamente e conterra' zero.  E' una situazione
esplicitamente prevista dallo standard.  Ovviamente se il numero di
inizializzazioni e' maggiore delle dimensioni dell'array il
compilatore e' tenuto ad emettere un errore.
-- 
Maurizio Loreti                      
http://wwwcdf.pd.infn.it/~loreti/mlo.html
Un. of Padova, Dept. of Physics - Padova, Italy          
lor...@padova.infn.it

 Alex
Comunque una piccola statistica mostra che : i compilatori cc -Aa e gcc -ansi
-pedantic su HP-UX generano warnings, mentre cc su DEC Alpha genera errori.



Vedere i posting scmbiati da me e Alex Martelli per una discussione
approfondita.
Per una distinzione chiara tra "deve"e "dovrebbe" si possono distinguere tre
casi. Un compilatore, in presenza di una assegnazione tra puntatori differenti
(con l'eccezione di void *) ha tre scelte:
1) Non lamentarsi e operare l'assegnazione
2) Mandare un warning e operare l'assegnazione
3) Generare un errore e fermare la compilazione.
Per un compilatore conforme allo standard 1) e' proibito. Infatti K&R2 (il
Kernigham e Ritchie 2nd edizione) dice (nella versione inlgese in fondo a p.
103): "It is not legal .... except for void*, to assign a pointer of one type
to a pointer of another type without a cast." Quindi sicuramente almeno 2) e'
richiesto. (Deve generare almeno un warning) E' in discussione se sia
richiesto 3) o sia solo possibile (Puo' generare un errore. ma e'
necessario?).
L'unica differenza tra C e C++ da questo punto di vista e' che l'assegnazione
di un void* a un altro puntatore a un oggetto e' legittimo in C ma non in C++
(in C++ malloc richiede un casting, in C non e' necessario). E' pero'
possibile che un compilatore C++ sia, in generale, piu' stretto e meno
permissivo di uno C. Per esempio sul mio sistema HP-UX (Unix) le assegnazioni
"miste" generano warnings con cc -Aa ("ANSI"-ISO ) per il C, ma generano
errori con aCC ("ANSI") C++. Ciao Paolo


possibile che un compilatore C++ sia, in generale, piu' stretto e meno
Puo` darsi, si`, anche per questioni di "temperie culturale".
Comunque, siamo chiaramente fra i "dovrebbe", non fra i "deve"...
Alex