PDA

View Full Version : C++ Guru della Settimana #1


fek
18-12-2003, 10:42
Prendendo spunto dall'analogo appuntamento che si svolge sul newsgroup comp.lang.c++.moderated, proviamo a proporre lo stesso "gioco" qui sul forum di HWUpgrade.

L'idea e' di presentare a tutti un quesito di C++ che esplori un problema o una curiosita' legata al linguaggio.
Tutti sono invitati a provare a rispondere al quesito e trovare la soluzione, discutendone assieme. Dopo qualche giorno vi presentero' la soluzione e potremo commentarla.

Se l'idea vi piace e prende piede, potremmo farlo diventare un appuntamento regolare e magari chiedere ai moderatori un forum apposito.

Se avete idee su quesiti da proporre, contattatemi pure in PM.

Quesito #1.

Dato il seguente pezzo di codice:



class A
{
public:

A(void)
: b(10)
, a(b + 1)
{
}

int a;
int b;
};

void main(void)
{
A obj;

printf("a = %d\nb = %d\n", obj.a, obj.b);
}



Quale sara' l'output del programma al termine dell'esecuzione di main()?
Giustificate la risposta.

cn73
18-12-2003, 12:25
Ma scusa, lo compilo, lo eseguo e te lo dico :D E poi perchè solo C??

fek
18-12-2003, 12:29
Originariamente inviato da cn73
Ma scusa, lo compilo, lo eseguo e te lo dico :D E poi perchè solo C??

Cosi' non vale pero' :)
E poi il bello e' capire il perche' dell'output che vedi e se l'output non e' quello atteso, come correggere il codice per renderlo tale.

Molz
18-12-2003, 12:31
Nn ho la minima idea d qello ke stampi,

ma andando a intuito direi

a = un numero a caso
b = 10

Nn kiedetemi xké

~Blissard~
18-12-2003, 13:20
Dunque...dunque

class A
{
public:

A(void) : b(10) , a(b + 1){}

int a;
int b;
};

void main(void)
{
A obj;

printf("a = %d\nb = %d\n", obj.a, obj.b);
}


Direi questo la classe A ha un costruttore di default che imposta il dato b = 10 e il dato a = 11, nel main l'oggetto di tipo A chiamato obj direi che assume per default questi valori dato che al costruttore non ne vengono passati di diversi; l'output dovrebbe essere:

a = 11
b = 10

giusto? :cool:

~Blissard~
18-12-2003, 13:35
Ripensandoci il valore di a non è così scontato potrebbe anche fare cose strane e non venire inizializzato realmente....

fek
18-12-2003, 13:40
Ok, piccolo suggerimento.
Il valore non e' scontato, ma il comportamento si'. Nel senso che il comportamento e' ben definito nello standard C++.

downloader
18-12-2003, 14:56
Scusate... io la butto lì...:rolleyes:

Gia è assai che il compilatore non vi sputi in faccia!:D :D :D

C'ho preso?:boh: :asd:

Kralizek
18-12-2003, 15:03
il valore di a dovrebbe essere il valore che era presente nella cella di memoria prima della definizione di a maggiorato di un'unità...

cionci
18-12-2003, 15:13
Siamo sicuri che non sia dipendente dal compilatore ?

Il mio prof di informatica 1 diceva sempre che nel programmare in C++ è sbagliato fare presupposizione sull'ordine di valutazione da parte del compilatore di espressioni a pari priorità (in questo caso b(10) e a(b + 1), oppure anche i due parametri di un operatore)...

downloader
18-12-2003, 15:36
Originariamente inviato da Molz
Nn ho la minima idea d qello ke stampi,

ma andando a intuito direi

a = un numero a caso
b = 10

Nn kiedetemi xké

:D

Non è che hai eseguito e non hai capito il risultato??? :D :D

Comunque è giusto. Anche se nn è una questione di priorità...

fek
18-12-2003, 15:55
Originariamente inviato da downloader
Scusate... io la butto lì...:rolleyes:

Gia è assai che il compilatore non vi sputi in faccia!:D :D :D

C'ho preso?:boh: :asd:

No, il compilatore con quel codice sa esattamente quello che sta facendo e produce un risultato in linea con lo standard C++.

Un altro indizio, qual e' l'ordine di valutazione delle due istruzioni di inizializazione nel costruttore?
E random? Dipende dal compilatore? E' sempre lo stesso? Perche'?

Il risultato cambia se scrivo invece questo?



class A
{
public:

A(void)
: b(10)
, a(b + 1)
{
}

int b;
int a;
};

void main(void)
{
A obj;

printf("a = %d\nb = %d\n", obj.a, obj.b);
}

Luc@s
18-12-2003, 15:55
Originariamente inviato da fek

class A
{
public:

A(void)
: b(10)
, a(b + 1)
{
}

int a;
int b;
};

void main(void)
{
A obj;

printf("a = %d\nb = %d\n", obj.a, obj.b);
}


.

a = Il valore standard del compilatore x gli int
b = 1

Perche:
Perche a nn è inizializzato.

IMHO




:)

Luc@s
18-12-2003, 16:00
Originariamente inviato da fek
Il risultato cambia se scrivo invece questo?


No, nn importa l'ordine delle variabili ma come le inizializzi nel costruttore.
Finche nn sappiamo cosa è a , b sara sempre 1 :)


IMHO

pela
18-12-2003, 17:11
l'inizializzazione viene nell'ordine in cui sono dichiarati a e b all'interno nella classe, per cui nel primo caso a viene un numero a caso perché b non è ancora stato inizializzato; se invece cambio l'ordine come nel secondo esempio avrò a=11 b=10

downloader
18-12-2003, 17:19
Originariamente inviato da pela
l'inizializzazione viene nell'ordine in cui sono dichiarati a e b all'interno nella classe, per cui nel primo caso a viene un numero a caso perché b non è ancora stato inizializzato; se invece cambio l'ordine come nel secondo esempio avrò a=11 b=10
:nono:

Luc@s
18-12-2003, 17:20
Originariamente inviato da downloader
:nono:
:confused:

downloader
18-12-2003, 17:21
Originariamente inviato da Luc@s
:confused:
intendevo che secondo me nn è così...

Luc@s
18-12-2003, 17:24
Originariamente inviato da downloader
intendevo che secondo me nn è così...

Quindi avrei ragione io???

fek
18-12-2003, 17:26
Originariamente inviato da pela
l'inizializzazione viene nell'ordine in cui sono dichiarati a e b all'interno nella classe, per cui nel primo caso a viene un numero a caso perché b non è ancora stato inizializzato; se invece cambio l'ordine come nel secondo esempio avrò a=11 b=10

Bingo! Risposta esatta :D

Nel primo caso il compilatore produce un costruttore che assomiglia a:



int a;
int b;

// [...]

{
a = b + 1;
b = 10;
}



Si puo' chiaramente notare come il valore di b e' indefinito quando viene eseguita la prima inizializzazione, quindi il valore di a e' anch'esso indefinito.

Mentre nel secondo caso il costruttore assomiglia a:


int b;
int a;

// [...]

{
b = 10;
a = b + 1;
}


Da cui e' ovvio che a e b assumono rispettivamente valore 10 e 11.

Questo comportamento e' dettato dallo standard C++ e va implementato cosi' da ogni compilatore conforme.

Detto questo, si impara che e' buona abitudine non usare gli inizializzatori quando il valore di un membro della classe dipende dal valore di uno o piu' membri della classe. Usare normale codice nel costruttore. Questo vale anche quando di mezzo ci sono chiamate a costruttori di classi padri

In tutti gli altri casi e' buona norma abituarsi a usare gli inizializzatori che aiutano a scrivere codice piu' pulito e leggible.

Se vi e' piaciuto, fra qualche giorno propongo un altro quesito.

Luc@s
18-12-2003, 17:35
Originariamente inviato da fek

Se vi e' piaciuto, fra qualche giorno propongo un altro quesito.


E stato bellissimo:D

downloader
18-12-2003, 17:35
Originariamente inviato da fek
Bingo! Risposta esatta :D

Nel primo caso il compilatore produce un costruttore che assomiglia a:



int a;
int b;

// [...]

{
a = b + 1;
b = 10;
}



Si puo' chiaramente notare come il valore di b e' indefinito quando viene eseguita la prima inizializzazione, quindi il valore di a e' anch'esso indefinito.

Mentre nel secondo caso il costruttore assomiglia a:


int b;
int a;

// [...]

{
b = 10;
a = b + 1;
}


Da cui e' ovvio che a e b assumono rispettivamente valore 10 e 11.

Questo comportamento e' dettato dallo standard C++ e va implementato cosi' da ogni compilatore conforme.

Detto questo, si impara che e' buona abitudine non usare gli inizializzatori quando il valore di un membro della classe dipende dal valore di uno o piu' membri della classe. Usare normale codice nel costruttore. Questo vale anche quando di mezzo ci sono chiamate a costruttori di classi padri

In tutti gli altri casi e' buona norma abituarsi a usare gli inizializzatori che aiutano a scrivere codice piu' pulito e leggible.

Se vi e' piaciuto, fra qualche giorno propongo un altro quesito.

Piaciuto piaciuto...
;)

Proponine degli altri!!! A discrezione dei Moderatori ovviamente

cionci
18-12-2003, 17:42
Cavolo...certo...altri altri :)

downloader
18-12-2003, 17:59
Ne posso proporre io uno al volo?

Cosa c'è di sbagliato in queste righe di codice?

void pippo(void)
{
int a[6], i = 0;

for(;i<6;i++)
i[a]=0;
}

fek
18-12-2003, 18:12
Originariamente inviato da downloader
Ne posso proporre io uno al volo?

Cosa c'è di sbagliato in queste righe di codice?

void pippo(void)
{
int a[6], i = 0;

for(;i<6;i++)
i[a]=0;
}


"i" non e' un'array e "a" non viene valutato come scalare, quindi i[a] e' sbagliata.

Noticina: preferite sempre ++i a i++, in altre parole preferite sempre il preincremento al postincremento a meno che non vi serva il valore della variabile da incrementare prima che venga incrementata (e' una caso raro).

Per tipi semplici non fa molta differenza, ma per oggetti che fanno overload degli operatori di incremento, potrebbe fare la differenza fra una semplice chiamata a funzione (preincremento) e la creazione di un oggetto temporaneo con conseguente chiamata a costruttore, operatore, distruttore.

Esempio:

Object obj;

++obj; // (1)
obj++; // (2)

(1) viene compilato in qualcosa di simile a:

obj.operator++(); // semplice chiamata a metodo

(2) viene compilato in:

Obj temp(obj); // costruttore di copia
obj.operator++();
temp.~Object(); // distruttore

Questo perche' state chiedendo al compilatore di conservare il valore di obj prima che venga incrementato e gentilmente lo copia in temp. Quell'oggetto temporaneo non puo' essere di solito eliminato dall'ottimizzatore perche' in generale il compilatore non puo' "guardare dentro" al costruttore e distruttore per sapere se sono operazioni semplici. In generale non lo sono.

Usate il preincremento, soprattutto se avete a che fare con STL :)

downloader
18-12-2003, 18:12
Non imbrogliate...:nonsifa:
Non dovete compilà!!!

cionci
18-12-2003, 18:13
Formalmente niente...

i[a] == *(i + a)

Comunque è un po' bruttino...
Io, quando posso, uso sempre il preincremento...ormai l'ho preso di abitudine...

downloader
18-12-2003, 18:14
Originariamente inviato da cionci
Formalmente niente...

i[a] == *(i + a)

Comunque è un po' bruttino...


GIUSTO.

fek... mi deludi...:( :)

downloader
18-12-2003, 18:16
Originariamente inviato da cionci
Io, quando posso, uso sempre il preincremento...ormai l'ho preso di abitudine...

Se nn l'uso all'interno di espressioni dove il pre fa differenza con il post, uso il post... questione di abitudine...
:cool:

fek
18-12-2003, 18:16
Originariamente inviato da fek
"i" non e' un'array e "a" non viene valutato come scalare, quindi i[a] e' sbagliata.

Ho scritto una scemenza. Questo e' codice valido.

"i" e' un'intero e viene automaticamente castato a puntatore, quindi puo' essere indirizzato.
"a" e' un puntatore e viene casato automaticamente a intero, quindi puo' essere usato come indice.

Dannato C e i suoi cast :D

downloader
18-12-2003, 18:18
Originariamente inviato da fek
Ho scritto una scemenza. Questo e' codice valido.

"i" e' un'intero e viene automaticamente castato a compilatore, quindi puo' essere indirizzato.
"a" e' un puntatore e viene casato automaticamente a intero, quindi puo' essere usato come indice.

Dannato C e i suoi cast :D


:eekk:

Ma cosa? Guarda che cionci ha dato la spiegazione giusta... i cast non c'entrano proprio in questo caso.

fek
18-12-2003, 18:18
Originariamente inviato da downloader
Se nn l'uso all'interno di espressioni dove il pre fa differenza con il post, uso il post... questione di abitudine...
:cool:

Pero' cosi' non aiuti il compilatore a ottimizzare. Anche' se logicamente e' equivalente, usare il pre incremento a volte ti salva un caricamento nel registro anche con semplici interi!

fek
18-12-2003, 18:21
Originariamente inviato da downloader
:eekk:

Ma cosa? Guarda che cionci ha dato la spiegazione giusta... i cast non c'entrano proprio in questo caso.

Nope, il discorso li' e' sui cast. In realta' non si chiamano proprio cast ma "degradazione".
Cionci ha detto giusto, le due versioni sono perfettamente equivalenti in C, ma il "ragionamento" che fa il parser C++ quando interpreta quel codice e' quello che ti ho detto.

Infatti se provi a sostituire delle classi e fornisci i giusti operatori di conversione, lo vedi fare le chiamate.

downloader
18-12-2003, 18:23
Originariamente inviato da fek
Pero' cosi' non aiuti il compilatore a ottimizzare. Anche' se logicamente e' equivalente, usare il pre incremento a volte ti salva un caricamento nel registro anche con semplici interi!

Di che registro parli della CPU? Ma guarda che l'ottimizzatore gia lavora a modo suo e l'ottimizzazione (dipende anche dalle impostazioni chiaramente) non dovrebbe prescindere dal pre o post incremento. Ma poi i l'uso dei registri è di default... o no?:)

cionci
18-12-2003, 18:26
Originariamente inviato da fek
"i" e' un'intero e viene automaticamente castato a puntatore, quindi puo' essere indirizzato.
"a" e' un puntatore e viene casato automaticamente a intero, quindi puo' essere usato come indice.
Se fosse così e supponendo che a fosse allocata all'indirizzo 100 decimale...con un ciclo del genere andresti a scrivere agli indirizzi:

400
401
402
....

Invece di

100
104
108
....

Infatti il calcolo dell'indirizzo sarebbe i + sizeof(*i)*a...invece il compialtore traduce automaticamente i[a] come *(i + a) che con l'aritmentica dei puntatori significa andare a scrivere all'indirizzo a+sizeof(*a)*i...

fek
18-12-2003, 18:27
Originariamente inviato da downloader
Di che registro parli della CPU? Ma guarda che l'ottimizzatore gia lavora a modo suo e l'ottimizzazione (dipende anche dalle impostazioni chiaramente) non dovrebbe prescindere dal pre o post incremento. Ma poi i l'uso dei registri è di default... o no?:)

Si', registri della CPU :)
In alcune situazioni un po' intricate, quando l'ottimizzatore non riesce a star dietro a quello che scrivi, e' costretto a semplificare e si "dimentica" che le due espressioni magari possono essere equivalenti.

Se imposti le ottimizzazione al massimo e disassembly il codice prodotto, puoi vedere che riesci a mandare facilmente in crisi l'ottimizzatore che si salva il valore da incrementare anche se poi non gli serve piu'. E aiutiamolo un po' il compilatore!

downloader
18-12-2003, 18:27
Originariamente inviato da fek
Nope, il discorso li' e' sui cast. In realta' non si chiamano proprio cast ma "degradazione".
Cionci ha detto giusto, le due versioni sono perfettamente equivalenti in C, ma il "ragionamento" che fa il parser C++ quando interpreta quel codice e' quello che ti ho detto.

Infatti se provi a sostituire delle classi e fornisci i giusti operatori di conversione, lo vedi fare le chiamate.

Scusa... ma a me non suona bene... io so solo che la cosa avviene grazie all'operatore [] dove a[b] = *(a+b). Che c'entra il cast? Non l'ho capito cosa vuoi dire poi sulle classi... :O

Cionci che ne pensi?:rolleyes: :confused:

Comunque vi saluto... a domani :)

fek
18-12-2003, 18:30
Originariamente inviato da cionci
Infatti il calcolo dell'indirizzo sarebbe i + sizeof(*i)*a...invece il compialtore traduce automaticamente i[a] come *(i + a) che con l'aritmentica dei puntatori significa andare a scrivere all'indirizzo a+sizeof(*a)*i...

Si', e' verissimo ma fai attenzione alla differenza fra C e C++. Il risultato e' uguale ma come i due parser arrivano a quel codice e' diverso.
Il C tira dritto e fa il ragionamento che fai tu.
Il C++ si domanda: "posso applicare l'operatore [] a i? Si', se lo converto (promuovo) a puntatore, posso usare a come parametro per l'operatore di default operator[](size_t i)? Si', se lo converto (degrado) ad un size_t".

Da qui in poi il comportamento di default dell'operator[] e' quello che dici tu e le due strade si riuniscono.

Comunque e' un bell'esempio perche' mostra come il C++ sia troppo zelante, retaggio della compatibilita' con il C, nel castare alle spalle del programmatore, cosa che a volte fa compilare codice come quello e magari porta a errori difficili da scoprire.

I puristi vorrebbero che i cast fossero sempre espliciti se non in pochi casi ben definiti.

cionci
18-12-2003, 18:31
Originariamente inviato da cionci
Infatti il calcolo dell'indirizzo sarebbe i + sizeof(*i)*a...invece il compialtore traduce automaticamente i[a] come *(i + a) che con l'aritmentica dei puntatori significa andare a scrivere all'indirizzo a+sizeof(*a)*i...
In effetti se si parla di C++ la cosa potrebbe diventare un po' più complicata...ora faccio qualche prova...

Luc@s
18-12-2003, 18:32
comincia a prendere una piega interessante:D

fek
18-12-2003, 18:38
Originariamente inviato da Luc@s
comincia a prendere una piega interessante:D

Si' interessante :)

Questa discussione porta ad un'altra regola pratica: non scrivere mai operatori di conversione se non strettamente necessario, ma molto necessario. E dichiarare sempre i costruttori con un solo parametro explicit.

cionci
18-12-2003, 18:42
fek mi fai un esempio in cui si ha questa conversione implicita ?

fek
18-12-2003, 18:46
Originariamente inviato da cionci
fek mi fai un esempio in cui si ha questa conversione implicita ?

Fra tipi standard o con tipi utente e operatori overloadati?

Un esempio puo' essere una classe String che ti permette la conversione automatica a char* con un operatore di conversione.

Questa non e' una cosa buona perche' puo' portare a valanghe di problemi difficili da debuggare.

Tanto e' vero che la classe std::string di STL non fornisce quest'operatore ma solo un metodo c_str(), di modo che sia il programmatore a richiedere esplicitamente una conversione a char*.

Kralizek
18-12-2003, 18:53
++obj; // (1)
obj++; // (2)



(2) viene compilato in:

Obj temp(obj); // costruttore di copia
obj.operator++();
temp.~Object(); // distruttore



forse sto dicendo una cazzata totalmente ot... ma i due operatori (preincremento e postincremento) non hanno una firma diversa??

tipo:

class& class::operator++(); //post incremento

class& class::operator++(int); //pre incremento

o mi sono inventato tutto?

fek
18-12-2003, 18:57
E' vero, hai ragione, hanno firma diversa :p

cionci
18-12-2003, 19:04
fek: con l'operatore overloadato...

cionci
18-12-2003, 19:05
Originariamente inviato da Kralizek
forse sto dicendo una cazzata totalmente ot... ma i due operatori (preincremento e postincremento) non hanno una firma diversa??

tipo:

class& class::operator++(); //post incremento

class& class::operator++(int); //pre incremento

o mi sono inventato tutto?
Vero...

fek
18-12-2003, 19:05
Vi saluto e vado a casa anch'io... Grazie per il bel thread. La settimana prossima ne preparo un altro un po' piu' ad alto livello.

fgmac
19-12-2003, 09:40
Il quesito mi e' piaciuto molto. :D
Avrei una proposta per i prossimi. Magari i moderatori non sono d'accordo, magari non piace, magari e' una caz...


Proporrei un post per il quesito in cui seguono le proposte di soluzione. Un altro post con la soluzione ufficiale con a seguire tutti i commenti e le richieste di chiarimento. In questo modo chi ha poco tempo riesce a trovare subito quello che cerca (quesit-soluzione) senza impazzire. Stamattina il post era arrivato a 3 pagine... o mamma, dove sara' la soluzione (comunque l'ho trovata)? :muro:


Che ne dite? :confused: :confused:

downloader
19-12-2003, 10:03
Mi sembra buona come idea... :rolleyes:

Ma non dobbiamo aspettare solo i moderatori...

Dove siete???:confused:

downloader
19-12-2003, 10:09
Comunque per rispondere ad alcune osservazioni, volevo chiedere:

Ma gli operatori applicati ai tipi semplici e non strutturati dal C++, per quello che ne so non vengono considerati come con classi o strutture. Questo perchè se ricordate il C++ è un'estensione del C. Ed eredita delle peculiarità del compilatore C. Credo che semplicemente i++ non voglia dire operator++() ma semplicemente i += 1.

Quindi non riesco a convenire sui discorsi relativi al cast e sui discorsi relativi a sovrapposizioni di operatori con variabili di tipo int:eek:

Mia personale opinione...;)

fgmac
19-12-2003, 11:50
Non c'e' bisongo di aspettare i moderatori.
E non c'e' bisogno di mettere i post con i quesiti in rilievo.

IMHO

Basta stabilire uno standard tipo (che oltretutto facilita la ricerca)
:cool:
[QUESITO #num] titolo normale //per la domanda
[QUESITO #num RISPOSTA] titolo normale //per la risposta

I moderatori dovrebbero solo dirci se ci sono controindicazioni.
:cool: :confused:

/\/\@®¢Ø
19-12-2003, 12:37
Originariamente inviato da downloader
Comunque per rispondere ad alcune osservazioni, volevo chiedere:

Ma gli operatori applicati ai tipi semplici e non strutturati dal C++, per quello che ne so non vengono considerati come con classi o strutture. Questo perchè se ricordate il C++ è un'estensione del C. Ed eredita delle peculiarità del compilatore C. Credo che semplicemente i++ non voglia dire operator++() ma semplicemente i += 1.

Quindi non riesco a convenire sui discorsi relativi al cast e sui discorsi relativi a sovrapposizioni di operatori con variabili di tipo int:eek:

Mia personale opinione...;)
Anche se tali operazioni non sono implementate da operatori il concetto rimane uguale. Quando il compilatore non riesce ad effettuare una operazione con un tipo, prova a vedere se riesce a farle convertendo il tipo in questione (che potrebbe essere un tipo predefinito) in un altro, in particolare usando le conversioni "standard" che coinvolgono i tipi predefiniti.

cionci
19-12-2003, 14:30
Originariamente inviato da fgmac
I moderatori dovrebbero solo dirci se ci sono controindicazioni.
:cool: :confused:
Per me va bene...

Quando i quesiti saranno molti basterà fare un thread riepilogativo da emttere in rilievo...

Ovviamente sono ben accetti anche quesiti di altri linguaggi...

Luc@s
19-12-2003, 14:38
Originariamente inviato da cionci
Per me va bene...

Quando i quesiti saranno molti basterà fare un thread riepilogativo da emttere in rilievo...

Ovviamente sono ben accetti anche quesiti di altri linguaggi...

Mi piace l'era di moderazione di cionci..............è cominciata bene:eek:
:D

Luc@s
11-01-2004, 16:23
nn si fa + nulla?

downloader
12-01-2004, 08:40
Originariamente inviato da Luc@s
nn si fa + nulla?

quoto...

verloc
12-01-2004, 17:10
Originariamente inviato da fek

Un esempio puo' essere una classe String che ti permette la conversione automatica a char* con un operatore di conversione.

...
Tanto e' vero che la classe std::string di STL non fornisce quest'operatore ma solo un metodo c_str(), di modo che sia il programmatore a richiedere esplicitamente una conversione a char*.


Si,hai ragione ma questo non è del tutto vero,
poichè tutto dipende dal fatto che lo standard stl non garantisce
che i caratteri vengano allocati contiguamente(a differenza dei vector).In realtà quasi tutte le migliori librerie lo fanno.
Il problema con c_str() è che restituisce un puntatore a stringa costante il che costituisce un problema per esempio quando devi passare ad una funzione un char *.

In realtà il trucco è che le migliori librerie(quasi tutte?) implementano il membro
.data() che restituisce un char * esattamente così come per i vector il cui equivalente membro restituisce un puntatore al primo elemento di un vettore allocato contiguamente.



Il trucco c'è (forse) e si vede nell'header della stl string :)

cionci
12-01-2004, 18:34
Provate a fare questo:

scrivete esclusivamente in C un programma che visualizza il classico messaggio "Hello world".
Caratteristiche:
- non deve includere alcuna libreria (per questo c'è un trucco, magari il primo indizio)
- deve essere portabile (su qualunque hardware)
- deve essere composto dal solo main
- non ci devono essere più di due chiamate alla stessa funzione
- non deve far uso di cicli (niente parole chiave for, while...)
- deve essere il + corto possibile

repne scasb
12-01-2004, 19:59

cionci
12-01-2004, 20:06
Azz...mi ero scordato di mettere una condizione...non si possono usare cicli... Inoltre non credo sia portabile su qualsiasi hardware (anche non x86)...

VegetaSSJ5
12-01-2004, 20:19
Originariamente inviato da repne scasb
Non sono un'esperta di C ma ci provo:


void main(void)
{
char far *v=(void _seg*)(0xB800)+(void near*)(0x0000);
char *h="Hallo world";
for(;*h;*v++=*h++,v++);
}


Non sara' molto portabile, ma funziona.
questo prog non stampa niente...

cionci
13-01-2004, 19:34
Up...non interessa a nessuno...

pela
13-01-2004, 19:44
boh non mi viene in mente nessuna soluzione :confused:

cionci
13-01-2004, 20:27
Dai dai impegnati... Magari domani posto un suggerimento ;)

downloader
14-01-2004, 12:45
Ti volevo chiedere...

il problema di non includere si può risolvere prendendo il contenuto dello stdio.h e incollarlo nel main file? Poiu chiamare printf("Hello world");

Credo di non aver capito bene cosa dobbiamo fare...

cionci
14-01-2004, 12:51
Originariamente inviato da downloader
il problema di non includere si può risolvere prendendo il contenuto dello stdio.h e incollarlo nel main file? Poiu chiamare printf("Hello world");

No...niente barbatrucchi, solo usando ciò che il C ti mette a disposizione...
Poi il programma deve essere corto...1...2...3...4 righe di codice...

cionci
14-01-2004, 21:58
Un aiutino...
Il C mette a disposizione una funzione di ouput linkata direttamente dal compilatore senza che venga inclusa alcuna libreria !!!

downloader
15-01-2004, 08:39
Avevo immaginato qualche cosa del genere... è una direttiva al precompilatore, giusto?

cionci
15-01-2004, 08:55
Nessuna direttiva ;)

downloader
15-01-2004, 09:00
quindi è proprio una funzione a tutti gli effetti... vediamo.

downloader
15-01-2004, 09:47
Ok trovato:

void main(void)
{
_cprintf("Hello World");
}

Era questa?

cionci
15-01-2004, 09:50
Non era questa che intendevo...ma se è portabile mi hai fregato ;)
Quella che intendevo io serve per stampare un solo carattere...

cionci
15-01-2004, 09:54
Wow...in VC++ non funziona... In MingW32 sì...

cionci
15-01-2004, 09:58
No...cacchio...funziona !!! :mad:

Mi hai fregato !!! Funziona anche sotto Linux ?

downloader
15-01-2004, 10:04
Tranquillo, ho capito perchè funziona...

Non ti ho fregato:cry:

Vedi funziona perchè il compilatore la linka come extern e si attacca direttamente alla libreria. Almeno credo.:rolleyes:

Ma quando lo dici che è solo per scrivere un carattere?:eek:


Comunque nn la conosco la tua funzione.

cionci
15-01-2004, 10:07
Originariamente inviato da downloader
Vedi funziona perchè il compilatore la linka come extern e si attacca direttamente alla libreria. Almeno credo.:rolleyes:
E' quello che fa anche con la mia ;)

Comunque la funzione che intedevo io è putchar !!!

Vabbè allora do la soluzione...

downloader
15-01-2004, 10:10
Originariamente inviato da cionci
Comunque la funzione che intedevo io è putchar !!!


Ma come alla fine è putchar?!?!?!
:eekk: :rotfl:

E io che ho cercato funzioni assurde...

Dacci la soluzione dai!:)

cionci
15-01-2004, 10:17
main(int c, char *s)
{(c-1)?((s[c-2])?(putchar(s[c-2]),main(++c,s)):0):main(++c,"Hello world!\n");}

downloader
15-01-2004, 10:19
fico! Ricorsione sul main carattere per carattere.

Ma credo che anche putchar sia linkata come extern... o no?

cionci
15-01-2004, 10:29
Sì ;)

downloader
15-01-2004, 10:35
Ma a sto punto potevo anche scrivere

void main(void)
{
printf("Hello World.\n");
}


:cool: ;)

cionci
15-01-2004, 10:41
Credevo che linkasse solo la putchar...invece linka anche la printf ;)

Comunque dai l'esempio di ricorsione è carino.. No ?

downloader
15-01-2004, 10:43
Sì:)

Ma hai notato che in pochi hanno partecipato?:rolleyes:

Mah!

Dove sono gli altri?

cionci
15-01-2004, 10:48
Ho notato...bo...

Luc@s
15-01-2004, 13:19
la mattina qualcuno va a scuola.
Cmq ottima soluzione e nn sapevo della printf :)

maxithron
16-01-2004, 17:38
Io proporrei anche magari di dividere la sezione in sottolivelli tipo

Aspirante Guru
Guru Intermedio
Guru Difficile
Guru

mjordan
17-01-2004, 06:31
Fek, il tizio della tua signature non è un "3D Programmer", è Peter Molyneaux... ;)

sukoy27k
10-05-2005, 16:13
main(int c, char *s)
{(c-1)?((s[c-2])?(putchar(s[c-2]),main(++c,s)):0):main(++c,"Hello world!\n");}

cazzo appena avrò modo di utilizzare la risocorsione sul main lo farò,chissà cosa ne pensa il mio prof di algoritmi :)

fek
10-05-2005, 16:34
Hai riesumato un post che e' monumento alla mia incostanza :(

cionci
10-05-2005, 17:00
Che ne dite di riesumarlo definitivamente ?

Chi vuole porre un quesito me lo scriva in PVT...io vi darò il via...

sukoy27k
10-05-2005, 19:00
Hai riesumato un post che e' monumento alla mia incostanza :(
Bhe se stessi con le mani sul motore 3d di BW2 sarei scompraso da anni ma visto che sto preparando l'esame di REti e fra uno standard e un altro mi si intorzano le balls,preferisco riesumare antiche discussioni.Cosa si fà per non studiare :cry:

VegetaSSJ5
10-05-2005, 19:23
Che ne dite di riesumarlo definitivamente ?
http://images.ciao.com/iit/images/products/normal/862/product-291862.jpg

mjordan
10-05-2005, 19:41
http://images.ciao.com/iit/images/products/normal/862/product-291862.jpg

Piu' chiaro di cosi' :D

VegetaSSJ5
10-05-2005, 20:07
Piu' chiaro di cosi' :D
più chiaro di così si muore... :eek: :asd: :rotfl:

DanieleC88
11-05-2005, 13:10
Che ne dite di riesumarlo definitivamente ?
:mano:

jappilas
23-06-2005, 23:17
Che ne dite di riesumarlo definitivamente ?
questo è un esempio tratto da un libro di Herb Sutter ;) <- edit :D
chi ha voglia di vedere se ha qualche idiosincrasia?
oh, se è troppo banale ne cerco uno + complesso :D
#include <iostream>
#include <complex>
using namespace std;
class Base
{
public:
virtual void f( int );
virtual void f( double );
virtual void g( int i = 10 );
};
void Base::f( int )
{
cout << "Base::f(int)" << endl;
}
void Base::f( double )
{
cout << "Base::f(double)" << endl;
}
void Base::g( int i )
{
cout << i << endl;
}
class Derived: public Base
{
public:
void f( complex<double> );
void g( int i = 20 );
};
void Derived::f( complex<double> )
{
cout << "Derived::f(complex)" << endl;
}
void Derived::g( int i )
{
cout << "Derived::g() " << i << endl;
}
void main()
{
Base b;
Derived d;
Base* pb = new Derived;
b.f(1.0);
d.f(1.0);
pb->f(1.0);
b.g();
d.g();
pb->g();
delete pb;
}

MSciglio
23-06-2005, 23:23
questo è un esempio tratto da Exceptional C++ di H. Sutter (capitolo 21 ) ;)
chi ha voglia di vedere se ha qualche idiosincrasia?
oh, se è troppo banale ne cerco uno + complesso :D


Non dovevi dire la fonte... ora tutti sapranno rispondere :D

jappilas
23-06-2005, 23:25
Non dovevi dire la fonte... ora tutti sapranno rispondere :D
è vero non ci avevo pensato... è che non mi va di spacciare per mio qualcosa che attualmente non ho la fantasia per inventare su due piedi :cry:
comunque mi interessa analizzare il comportamento e capire come ragiona il compilatore e le implicazioni del funzionamento standard del c++ ... ;)

MSciglio
23-06-2005, 23:29
è vero non ci avevo pensato... è che non mi va di spacciare per mio qualcosa che attualmente non ho la fantasia per inventare su due piedi :cry:
comunque mi interessa analizzare il comportamento e capire come ragiona il compilatore e le implicazioni del funzionamento standard del c++ ... ;)

E' fantastico quel libro. Ti fa capire come di c++ non si è capito ancora niente :)

mjordan
23-06-2005, 23:39
E' fantastico quel libro. Ti fa capire come di c++ non si è capito ancora niente :)

Esiste qualcosa di similare (non solo per argomenti, anche per qualità) per C e Java? Ogni linguaggio dovrebbe avere un libro simile...

MSciglio
23-06-2005, 23:40
Esiste qualcosa di similare (non solo per argomenti, anche per qualità) per C e Java? Ogni linguaggio dovrebbe avere un libro simile...

Non saprei dirti...

fek
23-06-2005, 23:49
E' fantastico quel libro. Ti fa capire come di c++ non si è capito ancora niente :)

E' la stessa cosa che pensai io quando lo lessi la prima volta :(

mjordan
23-06-2005, 23:53
E' la stessa cosa che pensai io quando lo lessi la prima volta :(

Perchè hai messo la faccina triste? La seconda volta che lo hai letto hai cambiato opinione? :D

jappilas
23-06-2005, 23:56
E' la stessa cosa che pensai io quando lo lessi la prima volta :(
io lo sto leggendo per la prima volta , ma non sono triste, anzi...
mi rendo conto che alcune cose che, sebbene fossi arrivato a darle per assunte per come insegnatemi da chi a sua volta le dava per scontate ( :sofico: ), all' epoca mi erano apparse "strane", sono effettivamente errate ...
è una cosa che ti dà una scrollata alla mente :D

DanieleC88
24-06-2005, 10:42
Perchè hai messo la faccina triste? La seconda volta che lo hai letto hai cambiato opinione? :D
Forse era solo nostalgico. :)

fek
24-06-2005, 11:13
Perchè hai messo la faccina triste? La seconda volta che lo hai letto hai cambiato opinione? :D

No peggio, ho capito che dovevo imparare il linguaggio :(

sukoy27k
24-06-2005, 15:52
questo è un esempio tratto da un libro di Herb Sutter ;) <- edit :D
chi ha voglia di vedere se ha qualche idiosincrasia?

che significa idiosincrasia?ho cercato ma non trovo nulla!!e poi....


virtual void g( int i = 10 );
void g( int i = 20 );


che senso ha dichirare in questo modo,perchè dichirare un argomento con un valore?? :confused:

perdonate l'ignoranza :D

DanieleC88
24-06-2005, 16:10
che senso ha dichirare in questo modo,perchè dichirare un argomento con un valore?? :confused:

perdonate l'ignoranza :D
Perché se poi chiami "g();" senza dare un valore all'argomento, quello avrà il valore che gli hai assegnato di default.

jappilas
24-06-2005, 16:14
che significa idiosincrasia?ho cercato ma non trovo nulla!!e poi....

in realtà ci sono delle cose interessanti, di vario tipo ed entità ;)
una già è il void main() , che non è conforme allo standard , quindi non portabile ...


virtual void g( int i = 10 );
void g( int i = 20 );

che senso ha dichirare in questo modo,perchè dichirare un argomento con un valore?? :confused:
perdonate l'ignoranza :D
defaulting del parametro argomento della funzione ;)
è vero, in questo caso è effettivamente contorto in quanto essendo nel costruttore della classe derivata, è adottato INSIEME all' overloading
cmq, è C++ lecito :)
-edit: ops, Daniele mi ha preceduto :O

71104
24-06-2005, 16:18
ma... qualcuno mi stava x caso prendendo in giro sul nome dell'autore del libro? :confused:
tanto Herbert SCHILDT mi fa sempre e solo SCHIFO!!!! :D :D :ciapet: :D
MHWAUWHAWUAUHWUAHUWAHUWAH!!!!!!

comunque (spero che non sia stato già postato :)) vorrei partecipare anche io con una domanda: secondo voi cosa fa questo programma? main(int c,char**o){char*s=c?"+L7?+;:7?+:OKIK+9?;9=;"
":+9?;:<:;+9?;;;:;+9<:;<::;+RLJ;K9+":1[o],t,a=!c,m;do
for (m=*s-'0',t=a?m/c:m%c;m>>7?c=1<<m+8,!a&&puts(&a)*
*&a:t--;printf(" \0/*"+a));while ((a^=3)||a[++s]);}

SENZA COMPILARLO PERO'!!!!!!!! :D :D :D
potete darmi la soluzione anche dicendomelo un po' in generale, tanto calcolare a mente l'output è umanamente impossibile... però non lo compilate!! :D

DanieleC88
24-06-2005, 16:27
Non ho il coraggio di decifrare tutto quel coso, ma te ne mando un'altro davvero bello. ;)
#include <stdio.h>

main(t,_,a)char *a;
{return!0<t?t<3?main(-79,-13,a+main(-87,1-_,
main(-86, 0, a+1 )+a)):1,t<_?main(t+1, _, a ):3,main ( -94, -27+t, a
)&&t == 2 ?_<13 ?main ( 2, _+1, "%s %d %d\n" ):9:16:t<0?t<-72?main(_,
t,"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+\
,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/\
+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){n\
l]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#\
n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;\
#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/")
:t<-50?_==*a ?putchar(a[31]):main(-65,_,a+1):main((*a == '/')+t,_,a\
+1 ):0<t?main ( 2, 2 , "%s"):*a=='/'||main(0,main(-61,*a, "!ek;dc \
i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);}

jappilas
24-06-2005, 16:29
ma... qualcuno mi stava x caso prendendo in giro sul nome dell'autore del libro? :confused:
tanto Herbert SCHILDT mi fa sempre e solo SCHIFO!!!! :D :D :ciapet: :D
MHWAUWHAWUAUHWUAHUWAHUWAH!!!!!!
ehm, io avevo preso un esempio da un libro di Herb Sutter... :rolleyes:
comunque (spero che non sia stato già postato :)) vorrei partecipare anche io con una domanda: secondo voi cosa fa questo programma? main(int c,char**o){char*s=c?"+L7?+;:7?+:OKIK+9?;9=;"
":+9?;:<:;+9?;;;:;+9<:;<::;+RLJ;K9+":1[o],t,a=!c,m;do
for (m=*s-'0',t=a?m/c:m%c;m>>7?c=1<<m+8,!a&&puts(&a)*
*&a:t--;printf(" \0/*"+a));while ((a^=3)||a[++s]);}

SENZA COMPILARLO PERO'!!!!!!!! :D :D :D
potete darmi la soluzione anche dicendomelo un po' in generale, tanto calcolare a mente l'output è umanamente impossibile... però non lo compilate!! :D
aiuto T_T

sukoy27k
24-06-2005, 16:30
ma... qualcuno mi stava x caso prendendo in giro sul nome dell'autore del libro? :confused:
tanto Herbert SCHILDT mi fa sempre e solo SCHIFO!!!! :D :D :ciapet: :D
MHWAUWHAWUAUHWUAHUWAHUWAH!!!!!!

comunque (spero che non sia stato già postato :)) vorrei partecipare anche io con una domanda: secondo voi cosa fa questo programma? main(int c,char**o){char*s=c?"+L7?+;:7?+:OKIK+9?;9=;"
":+9?;:<:;+9?;;;:;+9<:;<::;+RLJ;K9+":1[o],t,a=!c,m;do
for (m=*s-'0',t=a?m/c:m%c;m>>7?c=1<<m+8,!a&&puts(&a)*
*&a:t--;printf(" \0/*"+a));while ((a^=3)||a[++s]);}

SENZA COMPILARLO PERO'!!!!!!!! :D :D :D
potete darmi la soluzione anche dicendomelo un po' in generale, tanto calcolare a mente l'output è umanamente impossibile... però non lo compilate!! :D

permettimi di dire puro esrcizio di stile :confused:

71104
24-06-2005, 16:34
ehm, io avevo preso un esempio da un libro di Herb Sutter... :rolleyes: certo, e la dicitura ;) <- edit :D che significava? :rolleyes:








si scoprì che 71104 non conosceva un celeberrimo ed espertissimo autore di libri supervenduti di nome Herb Sutter :confused: :D

fek
24-06-2005, 16:37
permettimi di dire puro esrcizio di stile :confused:

Si' e soprattutto non era nello spirito del thread ;)

Lo spirito del thread non e' andare a cercare i corner case piu' curiosi del linguaggio, ma trovare quelle situazioni comuni mentre si programma che spesso si ignorano e portano a bug e/o design complicati e poco gestibili.

jappilas
24-06-2005, 16:48
certo, e la dicitura che significava? :rolleyes:
...
si scoprì che 71104 non conosceva un celeberrimo ed espertissimo autore di libri supervenduti di nome Herb Sutter :confused: :D

al posto di "<-edit" c' era il titolo completo del libro (cioè Exceptional C++ - 47 Engineering Puzzles, Programming Problems and Solutions)
l' ho tolto in quanto, come mi faceva notare msciglio, rendeva troppo facile "indovinare" le risposte (cioè buttarle lì senza una spiegazione che dimostri l' interiorizzazione del concetto e la capacità di spiegarlo agli altri, tra cui me, che per primo dico di aver bisogno di imparare) ;)

anche se, pensavo, che ci fosse o meno il titolo del libro da cui ho preso un capitolo non avrebbe cambiato nulla, visto che lo scopo del thread non era un quiz ... :)

71104
24-06-2005, 16:51
Si' e soprattutto non era nello spirito del thread ;)

Lo spirito del thread non e' andare a cercare i corner case piu' curiosi del linguaggio, ma trovare quelle situazioni comuni mentre si programma che spesso si ignorano e portano a bug e/o design complicati e poco gestibili. intendi dire come questo? :D#include <stdlib.h>
#include <stdio.h>

#define BUFLEN 0x100

int main() {
FILE *f1, *f2;
char buf[BUFLEN];
int nRead;
f2 = fopen("target", "w");
if (!f2) {
// unable to open target file
return -2;
}
f1 = fopen("not-found", "r");
if (!f1) {
// unable to open source file
return -1;
}
while (nRead = fread(buf, 1, BUFLEN, f1)) {
fwrite(buf, nRead, 1, f2);
}
fclose(f2);
fclose(f1);
return 0;
}


ho fatto un edit perché la prima versione che ho scritto non andava bene; ora l'esempio calza alla perfezione :D

cionci
24-06-2005, 17:06
Non si parlava di C++ ?

jappilas
24-06-2005, 17:16
uhm... produttore e consumatore su un file... non riesco a vedere il problema... :confused:
Non si parlava di C++ ?così credevo... :stordita:

PS: prima di dimenticarmi... nell' esempio precedente c' era un bug vero e proprio un
delete pb;
dall' apparente innocuità ma dagli effetti devastanti a causa della mancanza di un distruttore virtuale nella classe base: As it is, deleting via a pointer-to-base without a virtual destructor is evil, pure and simple, and corruption is the best thing you can hope for, because the wrong destructor will get called and operator delete() will be invoked with the wrong object size. :O

sukoy27k
24-06-2005, 17:17
intendi dire come questo? :D
#include <stdlib.h>
#include <stdio.h>

#define BUFLEN 0x100

int main() {
FILE *f1, *f2;
char buf[BUFLEN];
int nRead;
f2 = fopen("target", "w");
if (!f2) {
// unable to open target file
return -2;
}
f1 = fopen("not-found", "r");
if (!f1) {
// unable to open source file
return -1;
}


fin qui nulla di particolar o almeno nessun caso particolare.


while (nRead = fread(buf, 1, BUFLEN, f1)) {
fwrite(buf, nRead, 1, f2);
}
fclose(f2);
fclose(f1);
return 0;
}

a questo punto legge 256 elementi di 1 byte ciascuno,quindi 256 caratteri,setta nRead a 256 e procede con la scrittura.Quando ocorre EOF nread va a 0 ed esce dal ciclo.

Dove sta l'inghippo?

anche se non capisco perchè un file dovrebbe chiamarsi "not-found",vabbè sono congetture

sukoy27k
24-06-2005, 17:18
uhm... produttore e consumatore su un file... non riesco a vedere il problema... :confused:
così credevo... :stordita:

PS: prima di dimenticarmi... nell' esempio precedente c' era un bug vero e proprio un
delete pb;
dall' apparente innocuità ma dagli effetti devastanti a causa della mancanza di un distruttore virtuale nella classe base: :O
se non sbaglio mancava anche il costruttore,scusate la mia ignoranza col c++ :D

jappilas
24-06-2005, 17:26
a occhio direi che non c' erano costruttori perchè si trattava di classi che non incapsulavano dati membri...
praticamente gli oggetti istanziati sembravano puntatori a funzioni ;)

71104
24-06-2005, 17:34
a questo punto legge 256 elementi di 1 byte ciascuno,quindi 256 caratteri,setta nRead a 256 e procede con la scrittura.Quando ocorre EOF nread va a 0 ed esce dal ciclo.

Dove sta l'inghippo? non è certo lì :p

anche se non capisco perchè un file dovrebbe chiamarsi "not-found",vabbè sono congetture l'ho chiamato apposta così per suggerire...? :)

fin qui nulla di particolar o almeno nessun caso particolare. e invece era proprio lì il problema :D
ti do un aiuto: la precedente versione l'ho programmata volutamente male, ma di per se' non avrebbe problemi; nella seguente versione invece il problema si manifesta più o meno gravemente: #include <stdlib.h>
#include <stdio.h>

#define BUFLEN 0x100

int duplicate(char *src, char *tgt) {
FILE *f1, *f2;
char buf[BUFLEN];
int nRead;
f2 = fopen(tgt, "w");
if (!f2) {
// unable to open target file
return -2;
}
f1 = fopen(src, "r");
if (!f1) {
// unable to open source file
return -1;
}
while (nRead = fread(buf, 1, BUFLEN, f1)) {
fwrite(buf, nRead, 1, f2);
}
fclose(f2);
fclose(f1);
return 0;
}

int main() {
int i;
.
.
.
duplicate("not-found", "target1");
.
.
.
duplicate("not-found", "target2");
.
.
.
duplicate("not-found", "target3");
.
.
.
for (i = 1; i < 5; i++) {
char name[9];
sprintf(name, "target%d", i + 3);
duplicate("not-found", name);
}
.
.
.
return duplicate("not-found", "targetN");
}
nella funzione "duplicate" ho copiato il codice della precedente versione.
secondo me questo codice è un buon esempio di quello che diceva fek ;)

PS x cionci: anche questo è C++... o meglio: questo è anche C++... :D

cionci
24-06-2005, 17:40
PS x cionci: anche questo è C++... o meglio: questo è anche C++... :D
No...non è compatibile con lo standard del C++ :sofico:

71104
24-06-2005, 17:44
al posto di "<-edit" c' era il titolo completo del libro (cioè Exceptional C++ - 47 Engineering Puzzles, Programming Problems and Solutions)
l' ho tolto in quanto, come mi faceva notare msciglio, rendeva troppo facile "indovinare" le risposte (cioè buttarle lì senza una spiegazione che dimostri l' interiorizzazione del concetto e la capacità di spiegarlo agli altri, tra cui me, che per primo dico di aver bisogno di imparare) ;) :stordita: :stordita: :stordita:

sukoy27k
24-06-2005, 18:08
porca adesso devo uscire e non ho ancora trovato nulla,rimarrò tutta la serata col dubbio :doh:

VICIUS
24-06-2005, 18:09
Ci provo io:
duplicate("not-found", "target1");
Qui e nelle altre chiamate a duplicate non controlli mai i valori di ritorno :nonsifa:. Si deve sempre controllare il valore di ritorno.
f2 = fopen(tgt, "w");
if (!f2) {
// unable to open target file
return -2;
}
f1 = fopen(src, "r");
if (!f1) {
// unable to open source file
return -1;
}
Qui crei il file di destinazione prima di sapere se puoi aprire il file sorgente. Ci si puo Riempire l'hd cosi :) E poi prima di fare return -1 non fai mai flcose (f2); Ora non ricordo dei i fd vengono chiusi automaticmente dal so all'uscita della funzione o del programma (probabilmente alla chiusura del programma con una exit) ma questo potrebbe portare a problemi con la tabella dei fd e intassare il sistema.

Ah ultima cosa. Visto che in C++ si puo perchè non dichiarare le variabili subito prima di usarle invece di fare un immenso blocco iniziale a-la C ?

ciao ;)

sukoy27k
24-06-2005, 18:15
Ci provo io:
duplicate("not-found", "target1");
Qui e nelle altre chiamate a duplicate non controlli mai i valori di ritorno :nonsifa:. Si deve sempre controllare il valore di ritorno.
f2 = fopen(tgt, "w");
if (!f2) {
// unable to open target file
return -2;
}
f1 = fopen(src, "r");
if (!f1) {
// unable to open source file
return -1;
}
Qui crei il file di destinazione prima di sapere se puoi aprire il file sorgente. Ci si puo Riempire l'hd cosi :) E poi prima di fare return -1 non fai mai flcose (f2); Ora non ricordo dei i fd vengono chiusi automaticmente dal so all'uscita della funzione o del programma (probabilmente alla chiusura del programma con una exit) ma questo potrebbe portare a problemi con la tabella dei fd e intassare il sistema.


no di questo sono sicuro io,ad ogni processo è associata una tabella dei file aperti che viene chiusa col processo.tale tabella ha un entry che fa riferimento ad una tabella dei file aperti globale tenuta dal kernel del sis op(nel caso di sistemi con ext2 ci sarà l'inode nel caso di Ntfs ci sarà l'indice della FAT),che tiene traccia del numero di processi che hanno lo stesso file aperto.
spero di non aver detto inesattezze.
ovviamente come dici te bisognerebbe controllare l'apertura prima del file sorgente e poi di quello di destinazione e credo sia questo il problema in quanto ha cercato di suggerirmelo con il nome not-found,anzi ne sono certo.

VICIUS
24-06-2005, 18:20
no di questo sono sicuro io,ad ogni processo è associata una tabella dei file aperti che viene chiusa col processo.tale tabella ha un entry che fa riferimento ad una tabella dei file aperti globale tenuta dal kernel del sis op(nel caso di sistemi con ext2 ci sarà l'inode nel caso di Ntfs ci sarà l'indice della FAT),che tiene traccia del numero di processi che hanno lo stesso file aperto.
spero di non aver detto inesattezze.
ovviamente come dici te bisognerebbe controllare l'apertura prima del file sorgente e poi di quello di destinazione e credo sia questo il problema in quanto ha cercato di suggerirmelo con il nome not-found,anzi ne sono certo.
Bene allora se viene chiuso tutto solo alla fine del processo c'è anche l'altro problema con la tabella.

ciao ;)

71104
25-06-2005, 14:19
Ci provo io:
duplicate("not-found", "target1");
Qui e nelle altre chiamate a duplicate non controlli mai i valori di ritorno :nonsifa:. Si deve sempre controllare il valore di ritorno. quello era codice esemplificativo e scritto di fretta ^^
naturalmente non scriverei mai codice del genere se non fosse a scopo esemplificativo. la parte su cui volevo focalizzare era il contenuto della funzione duplicate.

f2 = fopen(tgt, "w");
if (!f2) {
// unable to open target file
return -2;
}
f1 = fopen(src, "r");
if (!f1) {
// unable to open source file
return -1;
}
Qui crei il file di destinazione prima di sapere se puoi aprire il file sorgente. Ci si puo Riempire l'hd cosi :) l'HD non si riempie perché in questo caso i files risultano tutti vuoti, ma intanto quello è un problema; poi? :)

E poi prima di fare return -1 non fai mai flcose (f2); centro! :D

Ora non ricordo dei i fd vengono chiusi automaticmente dal so all'uscita della funzione o del programma (probabilmente alla chiusura del programma con una exit) all'uscita della funzione sicuramente no! che notifica ha il sistema operativo dell'uscita da una funzione?

ma questo potrebbe portare a problemi con la tabella dei fd e intassare il sistema. addirittura il sistema non credo: in qualsiasi implementazione fatta con un po' di cervello i descrittori sono locali al processo; ma il leak c'è sempre e dura finché il processo non termina, quindi il vero problema è proprio quello (alla lunga il programma potrebbe non essere più in grado di aprire files), oltre naturalmente allo spreco di HD (tuttavia limitato) e al fatto che fintanto che il programma è in funzione e tiene aperti tutti quei files, l'utente non può nemmeno cancellarli.

Ah ultima cosa. Visto che in C++ si puo perchè non dichiarare le variabili subito prima di usarle invece di fare un immenso blocco iniziale a-la C ? all'università ci hanno abituati così perché quel testicolo di professore di Programmazione 1 compilava i nostri programmi SOLO ED ESCLUSIVAMENTE con la direttiva -ansi o -pedantic del gcc :( :( :(

ciao ;) meno male funziona ancora :D
nel mess precedente c'era stato un breve decadimento sulla C :D

fek
25-06-2005, 14:38
all'università ci hanno abituati così perché quel testicolo di professore di Programmazione 1 compilava i nostri programmi SOLO ED ESCLUSIVAMENTE con la direttiva -ansi o -pedantic del gcc :( :( :(


Quel professore allora dovrebbe imparare a programmare ;)

sukoy27k
25-06-2005, 15:01
Quel professore allora dovrebbe imparare a programmare ;)
perdonami la domanda,a prescindere dall'ignoranza del prof,perchè secondo te attenersi alla sintassi dell'ansi c è sbagliato?
anzi secondo me in ambito scolastico non è male,avendo una portatilità assoluta

ciao

cionci
25-06-2005, 15:06
perdonami la domanda,a prescindere dall'ignoranza del prof,perchè secondo te attenersi alla sintassi dell'ansi c è sbagliato?
Il fatto è che il C99 permette la dichiarazione in ogni punto della funzione ;)

VICIUS
25-06-2005, 15:31
l'HD non si riempie perché in questo caso i files risultano tutti vuoti, ma intanto quello è un problema; poi? :)
100.000 file vuoti non sono "vuoti". Tengono comunque delle spazio. Ma questo dipende da come e progettato il filesystem.

ciao ;)

fek
25-06-2005, 16:20
perdonami la domanda,a prescindere dall'ignoranza del prof,perchè secondo te attenersi alla sintassi dell'ansi c è sbagliato?
anzi secondo me in ambito scolastico non è male,avendo una portatilità assoluta

ciao

In questo caso e' sbagliato perche' i nuovi linguaggi permettono la dichiarazione di variabili in qualunque punto e' c'e' una ragione precisa dietro a questa sintassi.

La spiegazione e' un po' lunga, ma per fare la storia breve esiste una metrica chiamata span di una variabile, che indica la differenza fra il numero di riga in cui una variabile e' dichiarata (ed inizia ad esistere) ed il numero di riga del suo ultimo uso. E' dimostrato da vari studi che il numero di difetti di un metodo o di una funzione e' inversamente proporzionale allo span medio delle variabili locali. E' quindi cosa furba ridurre al minimo lo span medio delle variabili di una funziona ed un professore di programmazione dovrebbe insegnare questo :)

jappilas
25-06-2005, 16:26
In questo caso e' sbagliato perche' i nuovi linguaggi permettono la dichiarazione di variabili in qualunque punto e' c'e' una ragione precisa dietro a questa sintassi.

La spiegazione e' un po' lunga, ma per fare la storia breve esiste una metrica chiamata span di una variabile, che indica la differenza fra il numero di riga in cui una variabile e' dichiarata (ed inizia ad esistere) ed il numero di riga del suo ultimo uso. E' dimostrato da vari studi che il numero di difetti di un metodo o di una funzione e' inversamente proporzionale allo span medio delle variabili locali. E' quindi cosa furba ridurre al minimo lo span medio delle variabili di una funziona ed un professore di programmazione dovrebbe insegnare questo :)
effettivamente intuivo, che utilizzare effettivamente una variabile che si è dovuta dichiarare N (->inf.) righe più su, potesse facilitare le sviste... :D

sukoy27k
25-06-2005, 16:27
In questo caso e' sbagliato perche' i nuovi linguaggi permettono la dichiarazione di variabili in qualunque punto e' c'e' una ragione precisa dietro a questa sintassi.

La spiegazione e' un po' lunga, ma per fare la storia breve esiste una metrica chiamata span di una variabile, che indica la differenza fra il numero di riga in cui una variabile e' dichiarata (ed inizia ad esistere) ed il numero di riga del suo ultimo uso. E' dimostrato da vari studi che il numero di difetti di un metodo o di una funzione e' inversamente proporzionale allo span medio delle variabili locali. E' quindi cosa furba ridurre al minimo lo span medio delle variabili di una funziona ed un professore di programmazione dovrebbe insegnare questo :)

cosa sono i "difetti di un metodo"?o cmq dimmi sotto che voce dovrei cercare,perchè fare una ricerca con parole cosi generiche riporta risultati dispersivi.grazie :D

mho che rileggo il post di jappilas,mi è venuto in mente che forse ti riferisci a errori di programmazione con il termine difetto?tipo stanziare piu variabili del dovuto,riferine una al posto di un altra etc?

ciao

fek
25-06-2005, 16:28
cosa sono i "difetti di un metodo"?o cmq dimmi sotto che voce dovrei cercare,perchè fare una ricerca con parole cosi generiche riporta risultati dispersivi.grazie :D

ciao

difetto = bug :)

VICIUS
25-06-2005, 16:53
In questo caso e' sbagliato perche' i nuovi linguaggi permettono la dichiarazione di variabili in qualunque punto e' c'e' una ragione precisa dietro a questa sintassi.

La spiegazione e' un po' lunga, ma per fare la storia breve esiste una metrica chiamata span di una variabile, che indica la differenza fra il numero di riga in cui una variabile e' dichiarata (ed inizia ad esistere) ed il numero di riga del suo ultimo uso. E' dimostrato da vari studi che il numero di difetti di un metodo o di una funzione e' inversamente proporzionale allo span medio delle variabili locali. E' quindi cosa furba ridurre al minimo lo span medio delle variabili di una funziona ed un professore di programmazione dovrebbe insegnare questo :)
Code Complete 2? Certo che quel libro lo conosci proprio a memoria. :D

ciao ;)

fek
25-06-2005, 16:54
Code Complete 2? Certo che quel libro lo conosci proprio a memoria. :D

:p

mjordan
25-06-2005, 16:56
Il fatto è che l'obiettivo del corso di Programmazione I è quello di introdurre alla programmazione i concetti più significativi e dare un minimo di "testa" alla risoluzione di problemi che richiedono un minimo sforzo "algoritmico". Il linguaggio molte volte in questo tipo di corsi viene posto in secondio piano, proprio perchè non è l'obiettivo primo del corso. Non so che facoltà faccia 71104 e dove, ma dalle parti mie questo è l'obiettivo dell'esame di Programmazione I. Per altre tematiche invece inerenti i linguaggi c'è l'esame di "Linguaggi di programmazione" che insieme all'esame di "Linguaggi di programmazione e Compilatori" trattano tutte le tematiche piu' "intime" dei linguaggi di programmazione. Quindi, secondo me, astrarre un po dal linguaggio in questo caso è cosa buona. Tanto per fare del C hard core c'e' tempo e ci sono esami abbastanza carini. :D

71104
25-06-2005, 19:35
In questo caso e' sbagliato perche' i nuovi linguaggi permettono la dichiarazione di variabili in qualunque punto e' c'e' una ragione precisa dietro a questa sintassi.

La spiegazione e' un po' lunga, ma per fare la storia breve esiste una metrica chiamata span di una variabile, che indica la differenza fra il numero di riga in cui una variabile e' dichiarata (ed inizia ad esistere) ed il numero di riga del suo ultimo uso. E' dimostrato da vari studi che il numero di difetti di un metodo o di una funzione e' inversamente proporzionale allo span medio delle variabili locali. E' quindi cosa furba ridurre al minimo lo span medio delle variabili di una funziona ed un professore di programmazione dovrebbe insegnare questo :) sei un grande :D
infatti sono d'accordo, dichiarare le variabili poco per volta è più comodo perché il codice è ordinato meglio e la tua mente viene aiutata a suddividere i compiti della funzione in parti più piccole; questa è una spiegazione empirica del vantaggio delle dichiarazioni in mezzo al codice :)

71104
25-06-2005, 19:37
[...] una variabile che si è dovuta dichiarare N (->inf.) righe più su [...] esagerato :p

71104
25-06-2005, 19:43
Il fatto è che l'obiettivo del corso di Programmazione I è quello di introdurre alla programmazione i concetti più significativi e dare un minimo di "testa" alla risoluzione di problemi che richiedono un minimo sforzo "algoritmico". Il linguaggio molte volte in questo tipo di corsi viene posto in secondio piano, proprio perchè non è l'obiettivo primo del corso. Non so che facoltà faccia 71104 e dove, ma dalle parti mie questo è l'obiettivo dell'esame di Programmazione I. Per altre tematiche invece inerenti i linguaggi c'è l'esame di "Linguaggi di programmazione" che insieme all'esame di "Linguaggi di programmazione e Compilatori" trattano tutte le tematiche piu' "intime" dei linguaggi di programmazione. Quindi, secondo me, astrarre un po dal linguaggio in questo caso è cosa buona. Tanto per fare del C hard core c'e' tempo e ci sono esami abbastanza carini. :D faccio Informatica alla Sapienza (mi pareva di averlo detto anche ai sassi :D); cmq per la cronaca alla fine più o meno tutti quanti quelli che programmavano per la prima volta facendo esperimenti e programmetti col C hanno scoperto che le dichiarazioni possono essere anche "sfuse"; poi fortunatamente quello era l'unico prof. cretino che ci dava queste imposizioni assurde e immotivate che castravano l'inaudita potenza del C: ora penso che negli altri corsi non si arrabbi nessuno se in mezzo al codice ci mettiamo addirittura una classe con metodi astratti :D (non è C ma il gcc lo compila lo stesso).

fek
25-06-2005, 19:45
ora penso che negli altri corsi non si arrabbi nessuno se in mezzo al codice ci mettiamo addirittura una classe con metodi astratti :D (non è C ma il gcc lo compila lo stesso).

Ora non esagerare pero' :D

jappilas
07-07-2005, 19:20
faccio Informatica alla Sapienza (mi pareva di averlo detto anche ai sassi :D); cmq per la cronaca alla fine più o meno tutti quanti quelli che programmavano per la prima volta facendo esperimenti e programmetti col C hanno scoperto che le dichiarazioni possono essere anche "sfuse"; poi fortunatamente quello era l'unico prof. cretino che ci dava queste imposizioni assurde e immotivate che castravano l'inaudita potenza del C: ora penso che negli altri corsi non si arrabbi nessuno se in mezzo al codice ci mettiamo addirittura una classe con metodi astratti :D (non è C ma il gcc lo compila lo stesso).
... quasi quasi sarei tentato di installare questo (http://www.research.att.com/projects/cyclone/) sulle macchine in laboratorio SW dov'è usato il gcc per vedere le reazioni della gente... :Perfido:
tanto se il codice che scrivono è safe non dovrebbe succedere nulla no? :sofico:

(questo post è un up per il thread nel mentre penso a un quesito da postare ;) )

mjordan
09-07-2005, 13:45
... quasi quasi sarei tentato di installare questo (http://www.research.att.com/projects/cyclone/) sulle macchine in laboratorio SW dov'è usato il gcc per vedere le reazioni della gente... :Perfido:
tanto se il codice che scrivono è safe non dovrebbe succedere nulla no? :sofico:

(questo post è un up per il thread nel mentre penso a un quesito da postare ;) )

Molto simpatico direi... Certo quante ne inventano :sofico: