|
| Konvertering mellem typer Fra : Mogens Christiansen |
Dato : 17-10-01 13:31 |
|
Hej
Er det muligt konverterer mellem typer i C++, således at intet information
går tabt, fx sammensætte to char (8-bit) til en int (16-bit)? Eller, hvis
man har en array af char, kan man da gemme en int på 2 pladser i arrayet, fx
int tal = 32000;
char array[10];
char[0] = tal;
Ovenstående virker ikke, da kun lsb af tal gemmes på plads 0 i arrayet.
| |
Mogens Hansen (17-10-2001)
| Kommentar Fra : Mogens Hansen |
Dato : 17-10-01 14:03 |
|
"Mogens Christiansen" <mogchris@worldonline.dk> wrote in message
news:lSez7.2259$5v1.237095@news010.worldonline.dk...
> Hej
>
> Er det muligt konverterer mellem typer i C++, således at intet information
> går tabt, fx sammensætte to char (8-bit) til en int (16-bit)? Eller, hvis
> man har en array af char, kan man da gemme en int på 2 pladser i arrayet,
fx
> int tal = 32000;
> char array[10];
>
> char[0] = tal;
> Ovenstående virker ikke, da kun lsb af tal gemmes på plads 0 i arrayet.
>
Du kan bruge funktionen "memcpy"
memcpy(array, &tal, sizeof(int));
Det vil virke såfremt "array" er tilstrækkeligt stort til at rumme "tal".
Du kan læse værdien igen vd at skrive
memcpy(&tal, array, sizeof(int));
Venlig hilsen
Mogens Hansen
| |
Bertel Lund Hansen (17-10-2001)
| Kommentar Fra : Bertel Lund Hansen |
Dato : 17-10-01 14:17 |
|
Mogens Christiansen skrev:
>man har en array af char, kan man da gemme en int på 2 pladser i arrayet, fx
> int tal = 32000;
> char array[10];
Det nemmeste er at overlejre arrayet:
int tal = 32000;
char array[10];
int *pos;
int main () {
pos=(int *) array;
*pos=tal;
++pos;
*pos=17000;
}
Men jeg vil fraråde det, for det er noget klamp at erklære et
array på én måde og bruge det på en anden. Hvad vil du gerne
opnå?
--
Bertel
http://lundhansen.dk/bertel/ FIDUSO: http://fiduso.dk/
| |
Igor V. Rafienko (17-10-2001)
| Kommentar Fra : Igor V. Rafienko |
Dato : 17-10-01 16:53 |
|
[ Bertel Lund Hansen ]
[ snip ]
> Det nemmeste er at overlejre arrayet:
>
> int tal = 32000;
> char array[10];
> int *pos;
>
> int main () {
> pos=(int *) array;
> *pos=tal;
Det finnes arkitekturer som stiller krav til alignment av
dataelementer. SVJV finnes det _ingen_ garanti om at 'array' vil være
"alignet" på en passende grense (slik kode gir SIGBUS på sparc, fx.)
[ snip ]
ivr
--
"Kashu maslom ne isportish'" - skazal traktorist,
slivaya otrabotku na grechishnoe pole.
| |
Jesper Wolf Jesperse~ (17-10-2001)
| Kommentar Fra : Jesper Wolf Jesperse~ |
Dato : 17-10-01 14:32 |
|
Hej Mogens.
> Er det muligt konverterer mellem typer i C++, således at intet information
> går tabt, fx sammensætte to char (8-bit) til en int (16-bit)? Eller, hvis
> man har en array af char, kan man da gemme en int på 2 pladser i arrayet,
fx
> int tal = 32000;
> char array[10];
>
> char[0] = tal;
> Ovenstående virker ikke, da kun lsb af tal gemmes på plads 0 i arrayet.
Det kan du gøre på flere måder, den letteste er at benytte sig af pointer
casts, i dit tilfælde:
((short*)array) [0] = tal;
Dette er en meget effektiv måde at konvertere på men mange mennesker er
bange for pointeraritmetik og kan ikke lide denne formulering.
En anden måde at gøre det på er ved at lave opdelingen pr håndkraft:
array[0] = tal & 0xff; // de lave 8 bit
array[1] = (tal >> 8) & 0xff; // de høje 8 bit
Jeg bryder mig ikke om denne måde da der er alt for mange fejlkilder,
glemmer du for eksempel at afskæringen i linie 2 så får du helt sindsyge
resultater for negative tal
Man kan også bruge unions men det er ikke alle compilere der vil lave unions
der pakker på de samme grænser som de underliggende datatyper. Hvis de ville
gøre det rigtigt kunne man gøre sådan:
union
{
char array[2];
short . tallet;
} ekempel;
{
eksempel.tallet=tal;
char low = eksempel.array[0];
char high = eksempel.array[1];
}
Min favorit er nummer 1, her er en lille stump kode der viser teknikken
brugt:
// -------------------------------------------------------------------------
------
#include <iostream.h>
#include <iomanip>
const int CPS = sizeof(short)/sizeof(char); // characters pr short
const int CHARS = 10; // size of char array
const int SHORTS = CHARS/CPS; // how many shorts can we contain
const short tal = 32000;
int main(int argc, char *argv[], char *environ[])
{
char array [CHARS];
for (int i=0; i < SHORTS; i ++)
((short*)array)[i] = tal;
for(int i=0;i < CHARS; i++)
cout << "byte "<< setw(2) << i << " = " << short( array[i] ) << endl;
for (int i=0; i < SHORTS ; i ++)
cout << "short "<< setw(2) << i << " = " << ((short *)array)[i] << endl;
return 0;
}
// -------------------------------------------------------------------------
------
Med venlig hilsen
Jesper Wolf Jespersen
| |
Igor V. Rafienko (17-10-2001)
| Kommentar Fra : Igor V. Rafienko |
Dato : 17-10-01 17:15 |
|
[ Jesper Wolf Jespersen ]
[ snip ]
> Det kan du gøre på flere måder, den letteste er at benytte sig af
> pointer casts, i dit tilfælde:
Den _mest_ gale metoden er å bruke typecasts, ja.
> ((short*)array) [0] = tal;
Nei.
> Dette er en meget effektiv måde at konvertere på men mange mennesker
> er bange for pointeraritmetik og kan ikke lide denne formulering.
Denne effektiviteten har en portabilitetspris.
> En anden måde at gøre det på er ved at lave opdelingen pr håndkraft:
>
> array[0] = tal & 0xff; // de lave 8 bit
> array[1] = (tal >> 8) & 0xff; // de høje 8 bit
Heller ikke dette vil fungere, av den enkel grunn at:
1) CHAR_BIT kan være forskjellig fra 8 (det koster _ingenting_ å lage
kode som tar hensyn til det i slike tilfeller, men av en eller
annen merkelig grunn er det mange som velger å ikke gjøre det)
2) >> er implementasjonsavhengig (eller ikke-definert?) for
negative heltall ('tal' er en int).
> Jeg bryder mig ikke om denne måde da der er alt for mange
> fejlkilder, glemmer du for eksempel at afskæringen i linie 2 så får
> du helt sindsyge resultater for negative tal
Du kan få sinnsyke resultater uansett. En typecast til unsigned
(int/long) er å foretrekke først.
[ snip ]
> #include <iostream.h>
> #include <iomanip>
>
> const int CPS = sizeof(short)/sizeof(char); // characters pr short
> const int CHARS = 10; // size of char array
> const int SHORTS = CHARS/CPS; // how many shorts can we contain
> const short tal = 32000;
> int main(int argc, char *argv[], char *environ[])
> {
> char array [CHARS];
> for (int i=0; i < SHORTS; i ++)
> ((short*)array)[i] = tal;
>
> for(int i=0;i < CHARS; i++)
> cout << "byte "<< setw(2) << i << " = " << short( array[i] ) << endl;
> for (int i=0; i < SHORTS ; i ++)
> cout << "short "<< setw(2) << i << " = " << ((short *)array)[i] << endl;
> return 0;
> }
La oss se bort fra implementasjonsspesifikke hacks, og heller
kompilere dette programmet på et par maskiner. En liten modifikasjon,
siden OP har etterspurt etter ints (og ikke shorts):
const int SHORTS = CHARS / sizeof( int );
const int tal = 32000;
og
((int*)array)[i] = tal;
[ snip ]
og så kjører vi:
$ uname -ms
SunOS sun4u
$ CC bar.cpp
$ ./a.out
Bus Error
$
(akkurat short skaper ingen problemer på sparc, men du er med på
resonnementet, ikke sant?)
memmove, tenker jeg. Eller unions. Eller, aller helst, et ekstra
spørsmål -- "hvorfor". Kanskje bitset<>::to_ulong eller
bitset<>::to_string<> gjør jobben.
ivr
--
Much of this software was user-friendly, meaning that it was intended
for users who did not know anything about computers, and furthermore
had absolutely no intention whatsoever of learning.
-- A. S. Tanenbaum, "Modern Operating Systems, ch 1.2.4"
| |
Jesper Wolf Jesperse~ (18-10-2001)
| Kommentar Fra : Jesper Wolf Jesperse~ |
Dato : 18-10-01 10:19 |
|
Hej Igor.
Der er noget der tyder på at vi træffer ret forskellige valg når vi skriver
kode, og det er også helt fint. Men kunne du ikke prøve at lade være med at
udtale dig kategorisk om hvad der er rigtigt og forkert når du blot
udtrykker din mening, så undgår vi lettere at komme op og skændes.
Tag lige og læs oplæget fra Mogens Christensen:
>>> Er det muligt konverterer mellem typer i C++, således at intet
information
>>> går tabt, fx sammensætte to char (8-bit) til en int (16-bit)? Eller,
hvis
>>> man har en array af char, kan man da gemme en int på 2 pladser i
arrayet, fx
>>> int tal = 32000;
>>> char array[10];
>>>
>>> char[0] = tal;
>>> Ovenstående virker ikke, da kun lsb af tal gemmes på plads 0 i arrayet.
Han spørger hvordan man får gemt en 16 bit størrelse i to 8 bit størrelser.
Han kalder 16 bit størrelsen int, jeg har taget ham på ordet med
bitantallet, du tager ham på ordet med datatypen uden at du ved hvilken
arkitektur han befinder sig på.
Ved du om manden skriver til en 16 bits platform så som intel 8080, 8086,
Zilog Z80 eller lignende? Så kan hans int faktisk godt være 16 bit.
> > Det kan du gøre på flere måder, den letteste er at benytte sig af
> > pointer casts, i dit tilfælde:
> Den _mest_ gale metoden er å bruke typecasts, ja.
Tror du ikke du burde skrive Smalltalk eller Java ?
C++ giver os nogle meget stærke værktøjer hvis du tør bruge dem, men at
kalde dem gale er vist at fornærme både Dennis Ritchie og Bjarne Stoustrup.
> > ((short*)array) [0] = tal;
> Denne effektiviteten har en portabilitetspris.
Ikke hvis du sørger for at holde din destinations adresse allignet på samme
grænser som kilden, det er det problem du stødte på på¨sun ved at ændre
datatypen til int og dermed kræve at destinationsadressen skal være delelig
med 4. Det kan man opnå med implementationsafhængige pragmaer så som #pragma
pack(4).
Men læg lige mærke til at det er dig selv der fremkalder problemet ved at
tolke Mogens brev anderledes en jeg gør, jeg tror nemlig han mener hvad han
skriver.
> > En anden måde at gøre det på er ved at lave opdelingen pr håndkraft:
> >
> > array[0] = tal & 0xff; // de lave 8 bit
> > array[1] = (tal >> 8) & 0xff; // de høje 8 bit
>
>
> Heller ikke dette vil fungere, av den enkel grunn at:
>
> 1) CHAR_BIT kan være forskjellig fra 8 (det koster _ingenting_ å lage
> kode som tar hensyn til det i slike tilfeller, men av en eller
> annen merkelig grunn er det mange som velger å ikke gjøre det)
Jeg fraråder netop også metoden, der er mange der bruger den men for det
første gør man sig afhængig af om det er en little endian arkitektur eller
en big endian arkitektur, men der er også alt for mange muligheder for at
skrive forkert, ligesom vi er helt låst til antallet af bytes pr short.
> 2) >> er implementasjonsavhengig (eller ikke-definert?) for
> negative heltall ('tal' er en int).
Sludder, det er implementationsafhængigt hvordan man shifter right, det
implementationsafhængige består i at man på nogle platforme ikke har både en
logisk og en aritmetisk shift right. Men alle arkitekturer fra den mindste
8080 til en Cray kan lave shift right.
> La oss se bort fra implementasjonsspesifikke hacks, og heller
> kompilere dette programmet på et par maskiner. En liten modifikasjon,
> siden OP har etterspurt etter ints (og ikke shorts):
Haløj kig lige i hans mail, det er 16 bit ints han vil have. Mine
arkitekturer er alle 32 bits, men enhver C kompiler skal have en short
datatype der er 16 bit, derfor har jeg skrevet koden med shorts.
Med shorts virker skidtet på alle de 8 maskinarkitekturer jeg lige kan få
fat i, Motorola 68030 Unix SVR3, Mips R4400 SVR3, Mips R4400 SVR4, Sparc
SunOs 4, Ultrasparc Solaris 7, Intel Pentium SCO 5, Winnt 4.
Faktisk kan jeg skifte til int og stadigt få det til at virke på alle 8
platforme, men det er sansynligvis fordi compileren har andre konventioner
en dine. (prøv med en #pragma pack(4) og se om dit selvskabte problem
forsvinder).
> (akkurat short skaper ingen problemer på sparc, men du er med på
> resonnementet, ikke sant?)
Selvfølgeligt kender jeg problemet, men det var der altså ikke i
opgavestillerens oplæg, det er dig der har indført det.
> memmove, tenker jeg. Eller unions. Eller, aller helst, et ekstra
> spørsmål -- "hvorfor". Kanskje bitset<>::to_ulong eller
> bitset<>::to_string<> gjør jobben.
Memmove er en udmærket måde at gøre det på, sjovt at jeg slet ikke tænkte på
den.
Men prøv lige at kigge i kildeteksten til memmove.
Det er også pointer gymnastik, her castes til char pointere og hele
kopieringen foregår som char.
Der er selvfølgeligt intet alignment problem her, men teknikken er den
samme.
> Much of this software was user-friendly, meaning that it was intended
> for users who did not know anything about computers, and furthermore
> had absolutely no intention whatsoever of learning.
Jeg håber at folk der læser denne konference har lyst til at lære, specielt
er det vigtigt at lære at alting kan gøres på forskellige måder og at de
forskellige implementationer har forskellige konsekvenser. At udråbe een til
at være den bedste er blot at opfordre til mudderkastning. Jeg vil hellere
udråbe mine favoritter og så lade folk selv vælge.
Med venlig hilsen
Jesper Wolf Jespersen
| |
Igor V. Rafienko (18-10-2001)
| Kommentar Fra : Igor V. Rafienko |
Dato : 18-10-01 12:43 |
|
[ Jesper Wolf Jespersen ]
[ snip ]
> Der er noget der tyder på at vi træffer ret forskellige valg når vi
> skriver kode, og det er også helt fint.
Jeg prøver å treffe det valget som er pedantisk korrekt. Hvilke valg
_du_ treffer får være din sak, sålenge andre slipper å lære av dine
gale antagelser.
> Men kunne du ikke prøve at lade være med at udtale dig kategorisk om
> hvad der er rigtigt og forkert når du blot udtrykker din mening, så
> undgår vi lettere at komme op og skændes.
Ehh... jeg kan henvise deg til de relevante seksjonene i standarden,
om det er nødvendig. Påstandene tas liksom ikke ut av den løse luften.
Iallfall ikke fra min side.
[ snip ]
> Han spørger hvordan man får gemt en 16 bit størrelse i to 8 bit
> størrelser.
Jeg ser int'er og jeg ser en char array. 8bits char og 16bits int var
_eksempler_, ikke det generelle spørsmålet.
> Han kalder 16 bit størrelsen int, jeg har taget ham på ordet med
> bitantallet, du tager ham på ordet med datatypen uden at du ved
> hvilken arkitektur han befinder sig på.
Jeg leser spørsmålet, ikke eksempelet.
> Ved du om manden skriver til en 16 bits platform så som intel 8080,
> 8086, Zilog Z80 eller lignende? Så kan hans int faktisk godt være 16
> bit.
Jada, for all del. Men dersom arkitekturen hans har alignment krav til
short (irrespektivt av hvor mange bit en short måtte oppta), vil ikke
koden din fungere. Og det er _enkelt_ å rette opp. Så hva med at du
innrømmer at du har tatt feil og innser at Mogens Hansens forslag var
det eneste riktige?
[ snip ]
> > Den _mest_ gale metoden er å bruke typecasts, ja.
>
> Tror du ikke du burde skrive Smalltalk eller Java ?
Tror ikke _du_ at du burde prøve å _forstå_ hva jeg skriver?
> C++ giver os nogle meget stærke værktøjer hvis du tør bruge dem, men
> at kalde dem gale er vist at fornærme både Dennis Ritchie og Bjarne
> Stoustrup.
Jeg har gitt et eksempel hvor koden din ikke vil fungere. _Det_ er
tydeligvis ikke nok. Ved konvertering fra "pointer to T1" til "pointer
to T2", det eneste som garanteres _under forutsetning_ at T2 ikke har
strengere alignment krav enn T1, er at ved konvertering tilbake til
T1, vil den opprinnelige pekerverdien være bevart (5.2.10, p 7)
Man kan ikke typecast'e en char* til en short* og regne med at ting
vil fungere.
Og når du først insisterer på å ta fornærmelser inn i bildet, hva med
å _stave_ navnene riktig?
[ snip ]
> Ikke hvis du sørger for at holde din destinations adresse allignet
> på samme grænser som kilden, det er det problem du stødte på på¨sun
> ved at ændre datatypen til int og dermed kræve at
> destinationsadressen skal være delelig med 4. Det kan man opnå med
> implementationsafhængige pragmaer så som #pragma pack(4). Men læg
> lige mærke til at det er dig selv der fremkalder problemet ved at
> tolke Mogens brev anderledes en jeg gør, jeg tror nemlig han mener
> hvad han skriver.
Hva om short _skal_ være align'et på en passende grense? Hva om short
og int er den samme datatypen? Hva sier standarden om effekten (eller
eksistens) av pragma'er?
Jeg fatter ikke dette -- du ser problemet, men greier ikke å se at
koden din er feil. Hvordan er dette mulig?
[ snip ]
> Jeg fraråder netop også metoden, der er mange der bruger den men for
> det første gør man sig afhængig af om det er en little endian
> arkitektur eller en big endian arkitektur,
Det er _trivielt_ å teste for det.
> men der er også alt for mange muligheder for at skrive forkert,
> ligesom vi er helt låst til antallet af bytes pr short.
Hva er det du fraråder? Å skrive en funksjon som er:
a) uavhengig av endianess
2) uavhengig av bits/char
? Og hva skyldes et slikt råd?
> > 2) >> er implementasjonsavhengig (eller ikke-definert?) for
> > negative heltall ('tal' er en int).
>
> Sludder, det er implementationsafhængigt hvordan man shifter right,
_Effekten_ av 'tal >> 3' er implementasjonsavhengig. Du vet vel hva
det betyr i både teori og praksis?
> det implementationsafhængige består i at man på nogle platforme ikke
> har både en logisk og en aritmetisk shift right. Men alle
> arkitekturer fra den mindste 8080 til en Cray kan lave shift right.
Utrolig. Kan du _garantere_ at effekten av
int x = <expr>;
x >> 8;
_ikke_ vil resultere i en exceptiontilstand på CPUen? (jeg protesterte
ikke på manglende shift right, eller arkitekturens inhabilitet til å
gjøre det; jeg protesterte på effekten av >> på signed integral
types). Heller ikke her er løsningen vanskelig, men _du_ velger
allikevel å ikke gjøre det. Hva skyldes denne sløvheten?
Du _vet_ også hvordan man skal fikse det. Så hva med å fikse det, og
slutte å gnåle?
> > La oss se bort fra implementasjonsspesifikke hacks, og heller
> > kompilere dette programmet på et par maskiner. En liten
> > modifikasjon, siden OP har etterspurt etter ints (og ikke shorts):
>
> Haløj kig lige i hans mail, det er 16 bit ints han vil have.
Jeg foreslår at _du_ leser den opprinnelige meldningen en gang til.
> Mine arkitekturer er alle 32 bits, men enhver C kompiler skal have
> en short datatype der er 16 bit, derfor har jeg skrevet koden med
> shorts.
Virkelig? _Hvor_ fant du kravet om at sizeof( short ) * CHAR_BIT ==
16? Det eneste jeg kan finne er at short-intervallet omfatter signed
char-intervallet og ligger inneholdt i int-intervallet (3.9.1).
> Med shorts virker skidtet på alle de 8 maskinarkitekturer jeg lige
> kan få fat i, Motorola 68030 Unix SVR3, Mips R4400 SVR3, Mips R4400
> SVR4, Sparc SunOs 4, Ultrasparc Solaris 7, Intel Pentium SCO 5,
> Winnt 4. Faktisk kan jeg skifte til int og stadigt få det til at
> virke på alle 8 platforme, men det er sansynligvis fordi compileren
> har andre konventioner en dine. (prøv med en #pragma pack(4) og se
> om dit selvskabte problem forsvinder).
Selvskapte? Ikke tilegn _meg_ _dine_ mangler. Jeg poengterte problemet
som _du_ forfattet.
> > (akkurat short skaper ingen problemer på sparc, men du er med på
> > resonnementet, ikke sant?)
>
> Selvfølgeligt kender jeg problemet, men det var der altså ikke i
> opgavestillerens oplæg, det er dig der har indført det.
Les postingen til oppgavestilleren en gang til, takk.
> > memmove, tenker jeg. Eller unions.
For ordens skyld bør det bemerkes at uniontrickset ikke vil fungere.
Det irriterer meg at standarden ikke krevde en bestemt layout av
unions, men det er vel lite man kan gjøre med det. Og takk til Mogens
Hansen for rettelsen.
> > Eller, aller helst, et ekstra spørsmål -- "hvorfor". Kanskje
> > bitset<>::to_ulong eller bitset<>::to_string<> gjør jobben.
>
> Memmove er en udmærket måde at gøre det på, sjovt at jeg slet ikke
> tænkte på den. Men prøv lige at kigge i kildeteksten til memmove.
Er du dum, eller later du som? _Hva_ som står i memmove trenger ikke å
være _syntaktisk_ korrekt engang. _Kompilatoren_ står fri til å gjøre
så mye magi som den vil (minnes om et eksempel til Chris Torek der
offsetof-makroen var syntaktisk feil. Og den fungerte, fordi den var
kompilatorens egen).
En implementasjon kan forbipassere standardens krav, så lenge den
observerte effekten utad programmereren (eller, rettere sagt,
implementasjonens oppførsel med hensyn på en abstrakt maskin, slik den
er definert i standarden) er slik den er beskrevet i standarden. Dette
skiller _implementasjonen_ fra dens _brukere_.
> Det er også pointer gymnastik, her castes til char pointere og hele
> kopieringen foregår som char. Der er selvfølgeligt intet alignment
> problem her, men teknikken er den samme.
Utrolig.
[ snip ]
> Jeg håber at folk der læser denne konference har lyst til at lære,
> specielt er det vigtigt at lære at alting kan gøres på forskellige
> måder og at de forskellige implementationer har forskellige
> konsekvenser.
Det er _en_ måte å lære ting på: man bearbeider og forstår det
korrekte og man forkaster det gale etter å ha forstått hvorfor det er
galt.
Jeg _håper_ inderlige at _du_ såvel som andre har forstått _hvorfor_
ting vil gå galt i eksemplene _dine_. Og jeg håper inderlig at _du_
ikke har villedet noen.
> At udråbe een til at være den bedste er blot at opfordre til
> mudderkastning. Jeg vil hellere udråbe mine favoritter og så lade
> folk selv vælge.
Det er ikke snakk om favoritter (faen heller, det er ikke
"Twist"-reklamen vi lager), det er snakk om hva som er korrekt eller
galt. Forslaget til Mogens Hansen er _garantert_ korrekt. Forslaget
med unions er visstnok ikke helt bra, så det blir man nødt til å
forkaste (av pedantiske heller enn praktiske grunner). Forslagene dine
er miserable eksempler på C knotting som fremkaller det desidert
_verste_ som språket bringer med seg.
Hva med å innse feilen og akseptere rettelsene?
ivr
--
Typical biased DRC opinion: All ADT's should be made in C++ rather than C
if a choice between those two fundamental languages exists. Templates make
the old C way of doing things downright foolish (when it comes to ADT's).
-- Dann Corbit on <news:comp.lang.c>
| |
Kim Petersen (18-10-2001)
| Kommentar Fra : Kim Petersen |
Dato : 18-10-01 13:12 |
|
igorr@ifi.uio.no (Igor V. Rafienko) writes:
> [ Jesper Wolf Jespersen ]
[ megen snip ]
> > C++ giver os nogle meget stærke værktøjer hvis du tør bruge dem, men
> > at kalde dem gale er vist at fornærme både Dennis Ritchie og Bjarne
> > Stoustrup.
>
> Jeg har gitt et eksempel hvor koden din ikke vil fungere. _Det_ er
> tydeligvis ikke nok. Ved konvertering fra "pointer to T1" til "pointer
> to T2", det eneste som garanteres _under forutsetning_ at T2 ikke har
> strengere alignment krav enn T1, er at ved konvertering tilbake til
> T1, vil den opprinnelige pekerverdien være bevart (5.2.10, p 7)
>
> Man kan ikke typecast'e en char* til en short* og regne med at ting
> vil fungere.
Rigtigt, faktisk kan jeg komme på et par gamle arkitekturer hvor det ikke
en gang er muligt [med mindre compileren begynder på lidt "magi"]. På nogle
rene 16 bit word arkitekturer, hvor en char er "unaligned" kan det rent
faktisk ikke lade sig gøre at accesse denne short - med mindre man accesser
de to chars (lsb første, og msb anden) og sammensætter dem [heraf "magien"].
Det burde måske i samme åndedræt nævnes, at char-pointere på denne arki-
tektur egentlig er en "feature" i processoren.
--
Mvh. Kim Petersen /| Tlf: +4575831551 |\ Jomfru Ingefreds Vej 18
Software Engineer / | Fax: (none atm.) | \ 7100 Vejle
LSS / | Email: kim@vindinggaard.dk | \ DK - Danmark
| |
Mogens Hansen (19-10-2001)
| Kommentar Fra : Mogens Hansen |
Dato : 19-10-01 08:03 |
|
"Igor V. Rafienko" <igorr@ifi.uio.no> wrote in message
> Så hva med at du
> innrømmer at du har tatt feil og innser at Mogens Hansens forslag var
> det eneste riktige?
Der er typisk 3 reaktioner, når en fejltagelse bliver påpeget.
Novicerne, som straks erkender at de har taget fejl, fordi de ikke har det
store overblik.
De temmeligt dygtige som virkeligt ved meget og har stor erfaring.
De vil kæmpe en hård kamp fordi de virkeligt _troede_ det var rigtigt hvad
de sagde.
Så er der de rigtigt dygtige personer, som ved at de af og til tager fejl,
og som bliver glade og takker, når man gør sig den ulejlighed, dels at læse
hvad de skriver og dels korrigerer fejltagelsen (hvor små de end måtte
være). De ser det som en mulighed for at få deres viden yderligere skærpet,
og deres budskab præciseret.
Det _ved_ jeg af erfaring. F.eks.:
http://www.research.att.com/~bs/3rd_loc0.html
http://www.research.att.com/~bs/3rd_safe0.html
http://www.research.att.com/~ark/bibliography/accelerated.errata.html
http://www.cs.wustl.edu/~schmidt/ACE-members.html
http://www.langer.camelot.de/IOStreams/errata.htm (Igor V. Rafienko står
også her)
Det er iøvrigt nok en væsentlig grund (udover deres intelligens naturligvis)
til at de er så dygtige, at de er meget åbne over for kommentarer og
vurderer dem nøgternt.
Det giver nogle fantastiske resultater, hvor folk er positive, hjælpsomme og
inspirerende og dejligt fri for reaktioner baseret på Janteloven.
Alle kan lære noget.
Hvis man tror noget andet, går man glip af meget.
Venlig hilsen
Mogens Hansen
| |
Mogens Hansen (17-10-2001)
| Kommentar Fra : Mogens Hansen |
Dato : 17-10-01 17:19 |
|
"Jesper Wolf Jespersen" <spam.jwj@ehuset.com.spam> wrote in message
news:VKfz7.251$8Z.2951@news.get2net.dk...
>
> Det kan du gøre på flere måder, den letteste er at benytte sig af pointer
> casts, i dit tilfælde:
>
> ((short*)array) [0] = tal;
>
> Dette er en meget effektiv måde at konvertere på men mange mennesker er
> bange for pointeraritmetik og kan ikke lide denne formulering.
>
Det er vist ikke garanteret at det virker
Se Igor V. Rafienko's bemærkning.
> En anden måde at gøre det på er ved at lave opdelingen pr håndkraft:
>
> array[0] = tal & 0xff; // de lave 8 bit
> array[1] = (tal >> 8) & 0xff; // de høje 8 bit
>
> Jeg bryder mig ikke om denne måde da der er alt for mange fejlkilder,
> glemmer du for eksempel at afskæringen i linie 2 så får du helt sindsyge
> resultater for negative tal
>
Det er ikke garanteret at sizeof(int) er 2 - ofte er det ikke.
> Man kan også bruge unions men det er ikke alle compilere der vil lave
unions
> der pakker på de samme grænser som de underliggende datatyper. Hvis de
ville
> gøre det rigtigt kunne man gøre sådan:
>
> union
> {
> char array[2];
> short . tallet;
> } ekempel;
>
> {
> eksempel.tallet=tal;
> char low = eksempel.array[0];
> char high = eksempel.array[1];
> }
>
I C++ giver det "undefined behaviour" §9.5 (og i C89)
I C99 giver det "implementation defined behaviour" §6.5.2.3
Det der er specificeret til at virke (§3.9 i C++ Standarden) er brugen af
"memcpy" som jeg skrev i mit oprindelige indlæg.
> Min favorit er nummer 1, her er en lille stump kode der viser teknikken
> brugt:
>
>
// -------------------------------------------------------------------------
> ------
> #include <iostream.h>
Det hedder <iostream>
> #include <iomanip>
>
> const int CPS = sizeof(short)/sizeof(char); // characters pr short
sizeof(char) er defineret til at være 1 - men det skader naturligvis ikke
> const int CHARS = 10; // size of char array
> const int SHORTS = CHARS/CPS; // how many shorts can we contain
> const short tal = 32000;
> int main(int argc, char *argv[], char *environ[])
> {
> char array [CHARS];
> for (int i=0; i < SHORTS; i ++)
> ((short*)array)[i] = tal;
>
> for(int i=0;i < CHARS; i++)
> cout << "byte "<< setw(2) << i << " = " << short( array[i] ) << endl;
Det hedder std::cout, std::setw og std::endl, når der er ikke er nogen
"using ..."
> for (int i=0; i < SHORTS ; i ++)
> cout << "short "<< setw(2) << i << " = " << ((short *)array)[i] <<
endl;
Ditto her
> return 0;
> }
Venlig hilsen
Mogens Hansen
| |
Jesper Wolf Jesperse~ (18-10-2001)
| Kommentar Fra : Jesper Wolf Jesperse~ |
Dato : 18-10-01 11:00 |
|
Hej Mogens.
> > union
> > {
> > char array[2];
> > short . tallet;
> > } ekempel;
> >
> > {
> > eksempel.tallet=tal;
> > char low = eksempel.array[0];
> > char high = eksempel.array[1];
> > }
> >
>
> I C++ giver det "undefined behaviour" §9.5 (og i C89)
> I C99 giver det "implementation defined behaviour" .5.2.3
Som jeg også skrev i min posting så afhænger det her meget af compileren
hvorfor jeg ikke anbefalede teknikken, det forhindrer den dog ikke at virke
> Det der er specificeret til at virke (§3.9 i C++ Standarden) er brugen af
> "memcpy" som jeg skrev i mit oprindelige indlæg.
memcpy eller memmove er udmærkede forslag, jeg havde slet ikke tænkt på de
rutiner og dit indlæg var altså ikke kommet i newsgroup'en da jeg skrev mit
svar.
> > const int CPS = sizeof(short)/sizeof(char); // characters pr short
> sizeof(char) er defineret til at være 1 - men det skader naturligvis ikke
Nej det skader ikke og gør læseren opmærksom på hvad det 1 tal betyder.
Min holdning til immediates i koden er at det skal være synligt hvad de
betyder således at koden kan modificeres af andre med en rimelig chance for
success.
> > for(int i=0;i < CHARS; i++)
> > cout << "byte "<< setw(2) << i << " = " << short( array[i] ) <<
endl;
>
> Det hedder std::cout, std::setw og std::endl, når der er ikke er nogen
> "using ..."
Hvorfor vil du bruge scope resoulution operatoreren på ting der altid er i
scope ?.
Jeg mener slet ikke du kan få std ud af scope, og da der er ikke noget at
forveksle med skulle jeg mene det er helt overflødigt.
Jeg kender ikke using syntaxen, måske skulle jeg kigge i den nyeste C++
definition
Koden oversættes i gnu C++ (2.7.2, 2.8.1, 2.9.1) uden bemærkninger, også
selv om man instruerer dem om at være pedantisk. Men måske er den også
basere på en for gammel C++ spec
Med venlig hilsen
Jesper Wolf Jespersen
| |
Mogens Hansen (18-10-2001)
| Kommentar Fra : Mogens Hansen |
Dato : 18-10-01 11:45 |
|
Hej Jesper,
"Jesper Wolf Jespersen" <spam.jwj@ehuset.com.spam> wrote in message
news:yKxz7.59$8N1.2115@news.get2net.dk...
> Hej Mogens.
>
> > > union
> > > {
> > > char array[2];
> > > short . tallet;
> > > } ekempel;
> > >
> > > {
> > > eksempel.tallet=tal;
> > > char low = eksempel.array[0];
> > > char high = eksempel.array[1];
> > > }
> > >
> >
> > I C++ giver det "undefined behaviour" §9.5 (og i C89)
> > I C99 giver det "implementation defined behaviour" .5.2.3
>
> Som jeg også skrev i min posting så afhænger det her meget af compileren
> hvorfor jeg ikke anbefalede teknikken, det forhindrer den dog ikke at
virke
>
Ja, jeg så godt at du skrev at det afhang af compileren, og det virker ofte.
Men teknikken er ikke særligt anbefalelsesværdigt.
Se eventuelt også beskrivelsen af "union tricket" i Bjarne Stroustrup bog
"The C++ Programming Language, Special Edition" (eller Third Edition) side
842 nederst.
Se også forklaringer fra Andrew Koenig, f.eks.
http://groups.google.com/groups?q=union+Andrew+Koenig+undefined&hl=en&rnum=2
&selm=FFovKH.FI5%40research.att.com
http://groups.google.com/groups?q=union+Andrew+Koenig+undefined&hl=en&rnum=4
&selm=FxAorz.Fnw%40research.att.com
>
> > > for(int i=0;i < CHARS; i++)
> > > cout << "byte "<< setw(2) << i << " = " << short( array[i] ) <<
> endl;
> >
> > Det hedder std::cout, std::setw og std::endl, når der er ikke er nogen
> > "using ..."
>
> Hvorfor vil du bruge scope resoulution operatoreren på ting der altid er i
> scope ?.
Fordi de er ikke i scope.
Det er gammel stil at skrive
#include <iostream.h>
I den form kommer klasserne og objekterne typisk til at ligge i globalt
namespace, og derfor er der ikke behov for at bruge scope-resolution.
Bemærk at denne gamle stil ikke er i overensstemmelse med ISO C++
Standarden.
Den rigtige måde (i henhold til ISO C++ Standarden) er at skrive
#include <iostream>
hvorved alle klasserne og objekterne kommer til at tilhøre "namespace std".
Det vil sige at "cout" kan bruges ved at skrive:
std::cout << ...
eller
using std::cout;
cout << ...
eller
using namespace std;
cout << ...
> Jeg mener slet ikke du kan få std ud af scope, og da der er ikke noget at
> forveksle med skulle jeg mene det er helt overflødigt.
Det er ikke overflødigt - det er påkrævet i henhold til ISO C++ Standarden.
> Jeg kender ikke using syntaxen, måske skulle jeg kigge i den nyeste C++
> definition
>
C++ Standarden kan købes for 18 $.
Ellers kan Bjarne Stroustrups bøger "The C++ Programming Language, Special
Edition" (ISBN 0-201-70073-5) eller "The C++ Programming Language, Third
Edition" varmt anbefales.
Inholdet af de 2 bøger er identisk (for Third Edition trykt efter foråret
2000 - tidligere udgaver er lidt mindre, men de 2 ekstra kapitler kan hentes
fra Bjarne Stroustrups hjemmeside: http://www.research.att.com/~bs/).
Special Edition er hårdt indbundet og trykt på bedre papir.
Normalt er Special Edition dyrest - naturligvis.
> Koden oversættes i gnu C++ (2.7.2, 2.8.1, 2.9.1) uden bemærkninger, også
> selv om man instruerer dem om at være pedantisk. Men måske er den også
> basere på en for gammel C++ spec
Ja, det er en gammel spec.
Den iostream implementering jeg har til gcc 2.96 på Red Hat Linux 7.1 er
temmeligt gammelt.
Den er bl.a. ikke template baseret.
Det giver _lidt_ problemer af og til.
Den understøtter dog den nye stil for include, og at f.eks. cout tilhører
namespace std.
Hvis man er i tvivl om hvorvidt noget kode er i overensstemmelse med C++
Standarden kan jeg anbefale at teste med Comeau compileren.
Den kan prøves gratis på
http://www.comeaucomputing.com
Den er, som en del andre compilere, baseret på EDG frontend'en
( www.edg.com).
Det er naturligvis ikke en C++ reference implementering - men det er nok det
tætteste på vi kommer på.
Venlig hilsen
Mogens Hansen
| |
Jesper Wolf Jesperse~ (18-10-2001)
| Kommentar Fra : Jesper Wolf Jesperse~ |
Dato : 18-10-01 23:06 |
|
Hej Mogens.
[cut]
> Se eventuelt også beskrivelsen af "union tricket" i Bjarne Stroustrup bog
> "The C++ Programming Language, Special Edition" (eller Third Edition) side
> 842 nederst.
> Se også forklaringer fra Andrew Koenig, f.eks.
>
http://groups.google.com/groups?q=union+Andrew+Koenig+undefined&hl=en&rnum=2
> &selm=FFovKH.FI5%40research.att.com
>
http://groups.google.com/groups?q=union+Andrew+Koenig+undefined&hl=en&rnum=4
> &selm=FxAorz.Fnw%40research.att.com
Jeg har first edition af Bjarnes bog, men den er jo lidt gammel idag.
Når jeg skal læse op på tingene plejer jeg at bruge dette link:
http://www.icce.rug.nl/docs/cplusplus/
Jeg kan bedst lide at have bøger om emnerne men mig bogbudget er begrænset.
> Det er gammel stil at skrive
> #include <iostream.h>
>
> I den form kommer klasserne og objekterne typisk til at ligge i globalt
> namespace, og derfor er der ikke behov for at bruge scope-resolution.
> Bemærk at denne gamle stil ikke er i overensstemmelse med ISO C++
> Standarden.
Hihi, du har lige forklaret hvorfor jeg ikke er stødt på problemet
Min kode virker fordi jeg bruger den gamle include fil og tingene får global
status.
> Den rigtige måde (i henhold til ISO C++ Standarden) er at skrive
> #include <iostream>
>
> hvorved alle klasserne og objekterne kommer til at tilhøre "namespace
std".
> Det vil sige at "cout" kan bruges ved at skrive:
>
> std::cout << ...
> eller
> using std::cout;
> cout << ...
> eller
> using namespace std;
Du har ret hvis jeg tvinger f.eks. Borland til kun at acceptere Ansi C++ og
bruger den anden include fil iostream så skal jeg også bruge en "using
namespace std" for at slippe for problemerne.
> > Koden oversættes i gnu C++ (2.7.2, 2.8.1, 2.9.1) uden bemærkninger, også
> > selv om man instruerer dem om at være pedantisk. Men måske er den også
> > basere på en for gammel C++ spec
>
> Ja, det er en gammel spec.
> Den iostream implementering jeg har til gcc 2.96 på Red Hat Linux 7.1 er
> temmeligt gammelt.
> Den er bl.a. ikke template baseret.
> Det giver _lidt_ problemer af og til.
> Den understøtter dog den nye stil for include, og at f.eks. cout tilhører
> namespace std.
Jeg vil helst skrive kode der virker også i lidt ældre compilere, og nogle
af mine platforme kan altså ikke oversætte nyere versioner af gcc end ver
2.7.2 så det sætter grænserne.
> Hvis man er i tvivl om hvorvidt noget kode er i overensstemmelse med C++
> Standarden kan jeg anbefale at teste med Comeau compileren.
> Den kan prøves gratis på
> http://www.comeaucomputing.com
>
> Den er, som en del andre compilere, baseret på EDG frontend'en
> ( www.edg.com).
> Det er naturligvis ikke en C++ reference implementering - men det er nok
det
> tætteste på vi kommer på.
Jeg vil kigge på dem, måske kan jeg forlænge min kodes levetid ved at sørge
for at teste mod den nyere standard.
Jeg har ihvertfald været nødt til at skrive noget af min kode om mellem
versionerne af gcc gennem tiden, men det er jo hvad der sker når sproget
udvikler sig.
Jeg siger tak for en konstruktiv debat hvor jeg faktisk lærte noget
Med venlig hilsen
Jesper Wolf Jespersen
| |
Mogens Hansen (19-10-2001)
| Kommentar Fra : Mogens Hansen |
Dato : 19-10-01 08:04 |
|
Hej Jesper,
"Jesper Wolf Jespersen" <spam.jwj@ehuset.com.spam> wrote in message
news:mnIz7.731$8N1.6425@news.get2net.dk...
>
> Jeg har first edition af Bjarnes bog, men den er jo lidt gammel idag.
Det har jeg også - jeg anser den for at være lidt af et klenodie.
Jeg har også Second Edition.
Men de er begge _kun_ historisk interesse.
Jeg har også Third Edition (første optryk) og Special Edition (Europas
første eksemplar).
Ud over sprogdefinitionen er ændret, så er der en langt væsentligere forskel
på C++ dengang og C++ nu: programmeringsstilen i "Moderne C++" er langt mere
effektiv og afklaret end "Klassisk C++".
Se
http://www.two-sdg.demon.co.uk/curbralan/papers/TheMiseducationOfC++.pdf
for en god beskrivelse. (Kevlin Henney har iøvrigt mange andre gode papers
på www.curbralan.com)
Se også bogen
Accelerated C++, Practical Programming by Example
Andrew Koenig, Barbara E. Moo
ISBN 0-201-70353-X
for en god (den bedste) introduktion til moderne C++
Der er en masse væsentlig viden omkring brugen af exceptions, hvor verden er
blevet meget klogere de sidste 3-4 år.
Se
http://www.research.att.com/~bs/3rd_safe0.html
for en beskrivele af exception-safety i forbindelse med Standard Library.
Se også bogen (eller eventuelt www.gotw.com)
Excepional C++
Herb Sutter
ISBN 0-201-61562-2
for en grundig behandling bl.a. af brugen af exceptions.
>
> Jeg kan bedst lide at have bøger om emnerne men mig bogbudget er
begrænset.
Hvis du har det som jeg, er din tid og mentale kapacitet endnu mere
begrænset.
Derfor erdet vigtigt at vælge med omhu.
>
> Jeg vil kigge på dem, måske kan jeg forlænge min kodes levetid ved at
sørge
> for at teste mod den nyere standard.
> Jeg har ihvertfald været nødt til at skrive noget af min kode om mellem
> versionerne af gcc gennem tiden, men det er jo hvad der sker når sproget
> udvikler sig.
>
For praktisk brug er Borland C++Builder V5.0 også temmelig god til at
overholde C++ Standarden.
Ikke så god som Comeau, men langt bedre end Visual C++ V6.0.
Comeau online trial udgaven kan primært bruges til _små_ kode-stykker, og
programmerne kan naturligvis ikke eksekveres.
> Jeg siger tak for en konstruktiv debat hvor jeg faktisk lærte noget
Havde du forventet andet ?
Venlig hilsen
Mogens Hansen
| |
Per Abrahamsen (18-10-2001)
| Kommentar Fra : Per Abrahamsen |
Dato : 18-10-01 14:09 |
|
"Jesper Wolf Jespersen" <spam.jwj@ehuset.com.spam> writes:
> Koden oversættes i gnu C++ (2.7.2, 2.8.1, 2.9.1) uden bemærkninger, også
> selv om man instruerer dem om at være pedantisk. Men måske er den også
> basere på en for gammel C++ spec
Hmm... 2.9.1, det var vist egcs.
De er alle meget gamle, den seneste version of GNU C++ er 3.0.1. GNU
C++ 3.0 var den første der kom med et C++ bibliotek baseret på den
endelig standard, men selv den er delvis bagudkompatibel så din gamle
kode skulle fortsætte med at fungere.
| |
Jesper Wolf Jesperse~ (18-10-2001)
| Kommentar Fra : Jesper Wolf Jesperse~ |
Dato : 18-10-01 23:24 |
|
Hej Per.
"Per Abrahamsen" <abraham@dina.kvl.dk> wrote in message
news:rjd73lqem0.fsf@ssv2.dina.kvl.dk...
> "Jesper Wolf Jespersen" <spam.jwj@ehuset.com.spam> writes:
>
> > Koden oversættes i gnu C++ (2.7.2, 2.8.1, 2.9.1) uden bemærkninger, også
> > selv om man instruerer dem om at være pedantisk. Men måske er den også
> > basere på en for gammel C++ spec
>
> Hmm... 2.9.1, det var vist egcs.
Det er rigtigt, jeg var med i testningen af egcs inden det blev det
officielle gcc spor. Det var sjovt at oversætte nye versioner hver uge og
køre verificationstestene.
Det var den første version af gcc hvor SCO Openserver kom med som fuldt
supporteret platform, og da jeg brugte den platform meget på daværende
tidspunkt blev dette hurtigt den compiler vi brugte.
Desværre kunne den ikke oversættes på vores ældre Mips SVR3 platform hvor
assembleren ikke kunne håndtere nogle af de nye addresserings direktiver, og
binutils kunne ikke oversættes heller da de krævede en nyere gcc end jeg
havde. Så på den platform bruger jeg stadigt gcc ver 2.7.2.
> De er alle meget gamle, den seneste version of GNU C++ er 3.0.1. GNU
> C++ 3.0 var den første der kom med et C++ bibliotek baseret på den
> endelig standard, men selv den er delvis bagudkompatibel så din gamle
> kode skulle fortsætte med at fungere.
Jeg prøver at skrive min kode så den kan bruges i alle versionerne, men af
og til skal jeg rette i gammel kode for at få den kompatibel med nye
compilere, og det er lidt trals at skulle have så mange #ifdef's i koden.
Jeg har slet ikke kigget på gcc 3, for tiden koder jeg til Windows og bruger
Borland C++ builder og Microsofts Visual C++. Jeg har cygwin med gcc ver
2.95.2-6 som jeg bruger til at teste kode kompatibilitet på.
Med venlig hilsen
Jesper Wolf Jespersen
| |
Per Abrahamsen (19-10-2001)
| Kommentar Fra : Per Abrahamsen |
Dato : 19-10-01 08:14 |
|
"Jesper Wolf Jespersen" <spam.jwj@ehuset.com.spam> writes:
> Jeg prøver at skrive min kode så den kan bruges i alle versionerne, men af
> og til skal jeg rette i gammel kode for at få den kompatibel med nye
> compilere, og det er lidt trals at skulle have så mange #ifdef's i koden.
Den gamle stil med <iostream.h> vil reelt være mere protabel end den
ny med <iostream> i nogle år endnu, uanset hvad Mogens og Ivar siger.
> Jeg har slet ikke kigget på gcc 3, for tiden koder jeg til Windows og bruger
> Borland C++ builder og Microsofts Visual C++.
Alle tre har et moderne C++ bibliotek.
> Jeg har cygwin med gcc ver
> 2.95.2-6 som jeg bruger til at teste kode kompatibilitet på.
Men det har Cygwin (GCC 2.95) ikke.
Jeg ved ikke hvornår Cygwin har tænkt sig at opgradere, men det er
forståeligt de ikke har gjort det endnu. GCC 3.0 har nogle
performance problemer. Det er blevet bedre i 3.0.1 og 3.0.2, men de
afgørende forbedringer kommer først i 3.1 (der forventes til foråret).
| |
Igor V. Rafienko (19-10-2001)
| Kommentar Fra : Igor V. Rafienko |
Dato : 19-10-01 13:58 |
|
[ Per Abrahamsen ]
[ snip ]
> Den gamle stil med <iostream.h> vil reelt være mere protabel end den
> ny med <iostream> i nogle år endnu, uanset hvad Mogens og Ivar
> siger.
Det mer interessante spørsmålet er hva er det som koster mest -- å
legge ut for et ordentlig C++ miljø, skrape alt det arkaiske og
omskrive det _eller_ å være bakoverkompatibel med kompilatorne fra
urtiden som har like mye med C++ å gjøre som ENIAC med dagens
datamaskiner.
Det _er_ strevsomt å jobbe seg rundt begrensninger som skyldes
steingample implementasjoner og det finnes en øvre grense på hvor
mange ifdef'er man gidder å rote seg bort i. IMHO, selvsagt.
Det er en skam at C++ ikke har et miljø som understøtter
språkdefinisjonen 100% (det miljøet ville ikke ha trengt å være
effektivt (og ej heller kompilert), men det ville ha vært et ypperlig
referansepunkt).
[ snip ]
ivr
--
Compilers that are far behind the standard is a burden on the community
because they force people who need portability to program to the lowest
common denominator.
-- B. Stroustrup on compiler compliance, 1999-01-04
| |
|
|