Toon posts:

[C++] Integer met vaste bit-grootte?

Pagina: 1
Acties:
  • 457 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
De bit-grootte van het type 'int' staat niet vast. Verschillende platforms en compilers geven er hun eigen draai aan, zoals bekend.

Nu wil ik echter een vaste bit-grootte van bepalen door middel van de type-definitie van een bepaalde variabele. De (verplichte ;() compiler is Borland C++BuilderX. Deze heeft de volgende limits-header:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*  _lim.h - Internal version of "C" limits.h header

    Defines implementation specific limits on type values.

*/

/*
 *      C/C++ Run Time Library - Version 11.0
 *
 *      Copyright (c) 1987, 2002 by Borland Software Corporation
 *      All Rights Reserved.
 *
 */


#ifndef __LIMITS_H
#define __LIMITS_H
#define _INC_LIMITS  /* MSC Guard name */

#include <_stddef.h>

#define CHAR_BIT        8               /* number of bits in a char */
#define MB_LEN_MAX      2               /* max. # bytes in multibyte char */

#define SCHAR_MIN     (-128)            /* minimum signed   char value */
#define SCHAR_MAX       127             /* maximum signed   char value */
#define UCHAR_MAX       255             /* maximum unsigned char value */

#if ('\x80' < 0)
#define CHAR_MIN        SCHAR_MIN       /* minimum char value */
#define CHAR_MAX        SCHAR_MAX       /* maximum char value */
#else
#define CHAR_MIN        0
#define CHAR_MAX        UCHAR_MAX
#endif

#define SHRT_MIN      (-32767-1)        /* minimum signed   short value */
#define SHRT_MAX        32767           /* maximum signed   short value */
#define USHRT_MAX       65535U          /* maximum unsigned short value */

#define LONG_MIN      (-2147483647L-1)  /* minimum signed   long value */
#define LONG_MAX        2147483647L     /* maximum signed   long value */
#define ULONG_MAX       4294967295UL    /* maximum unsigned long value */

#if defined (_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS >= 64)
#define _I64_MIN      (-9223372036854775807i64-1) /* minimum signed   __int64 value */
#define _I64_MAX        9223372036854775807i64    /* maximum signed   __int64 value */
#define _UI64_MAX       18446744073709551615ui64  /* maximum unsigned __int64 value */
#endif

#define INT_MIN         LONG_MIN        /* minimum signed   int value */
#define INT_MAX         LONG_MAX        /* maximum signed   int value */
#define UINT_MAX        ULONG_MAX       /* maximum unsigned int value */

#if defined(_POSIX_)

#define _POSIX_ARG_MAX          4096
#define _POSIX_CHILD_MAX        6
#define _POSIX_LINK_MAX         8
#define _POSIX_MAX_CANON        255
#define _POSIX_MAX_INPUT        255
#define _POSIX_NAME_MAX         14
#define _POSIX_NGROUPS_MAX      0
#define _POSIX_OPEN_MAX         16
#define _POSIX_PATH_MAX         255
#define _POSIX_PIPE_BUF         512
#define _POSIX_SSIZE_MAX        32767
#define _POSIX_STREAM_MAX       8
#define _POSIX_TZNAME_MAX       3

#define ARG_MAX                 (16384 - 256)   /* 16k-(heap overhead+safety) */
#define CHILD_MAX               32
#define LINK_MAX                _POSIX_LINK_MAX
#define MAX_CANON               _POSIX_MAX_CANON
#define MAX_INPUT               _POSIX_MAX_INPUT
#define NAME_MAX                255
#define NGROUPS_MAX             16
#define OPEN_MAX                32
#define PATH_MAX                512
#define PIPE_BUF                _POSIX_PIPE_BUF
#define SSIZE_MAX               _POSIX_SSIZE_MAX
#define STREAM_MAX              20
#define TZNAME_MAX              10

#endif /* POSIX */
#endif  /* __LIMITS_H */


Maar hoe kan ik mijn code cross-platform/cross-compiler maken met behoud van bepaalde vaste bit-groottes voor types?

Ik kan wel met shorts en longs gaan pielen, maar ik wil o.a. een 8-bits unsigned int (ja, ik kan natuurlijk casten naar van een unsigned char). Bovendien heb ik de indruk (correct me if I'm wrong) dat zelfs de bit-grootte van longs en shorts niet altijd geheel uniform is...

Of het suboptimaal is of 'onnodig' is nu even niet het issue, mind you. ;)

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Alleen de grootte van 'char' staat vast op 1 byte. (dat hoeven niet eens 8 bits te zijn)

Vandaar, wat de meeste mensen doen, is een typedef maken in de vorm van 'typedef unsigned int uint32;'. Per platform zet je deze typedefs dan goed. Je kan dit nog compiletime laten checken, door traits/limits te raadplegen bij het compilen, en kijken of de range van je type klopt.

Overigens gebruik je in C++ <limits> en de klasse std::numeric_limits. Dan kan je bv zo checken of je type klopt: static_check(std::numeric_limits<uint32>::is_signed, uint32_is_not_unsigned);

[ Voor 24% gewijzigd door Zoijar op 06-12-2004 19:33 ]


  • MaxxRide
  • Registratie: April 2000
  • Laatst online: 09-01 10:13

MaxxRide

Surf's up

Met deze header file is dat toch gedefinieerd? Een 8 bit unsigned int is van 0 tot 255. In jouw header file geef je al duidelijk aan wat de ranges (en dus het aantal bits en signed status) is.

Of begrjip ik je niet goed?

If you are not wiping out you are nog pushing enough...


  • Eelis
  • Registratie: Januari 2003
  • Laatst online: 21-02-2015
.

[ Voor 98% gewijzigd door Eelis op 18-02-2015 19:10 ]


Verwijderd

Verwijderd schreef op maandag 06 december 2004 @ 19:21:
Maar hoe kan ik mijn code cross-platform/cross-compiler maken met behoud van bepaalde vaste bit-groottes voor types?
Met cross-platform neem ik aan dat er hier een binair bestandsformaat of netwerkprotocol bedoeld wordt? In dat geval moet je met meer dingen rekening houden dan alleen de bit- en bytesizes van je variabelen; je moet ook rekening houden met endianness, de volgorde waarin de bytes van een multibyte-type geschreven worden (er zijn zelfs obscure platforms met een omgekeerde bit-endianness). Zoijars tips zijn prima voor sizeof() en signedness, maar lossen het endianness probleem niet op.

Verwijderd

Ligt dat gewoon niet aan wat de data model is van het platform dat je runt:

Data TypeLP32ILP32ILP64LLP64LP64
char88888
short1616161616
int3232
int1632643232
long3232643264
long long (int64)64
pointer323264

Verwijderd

Topicstarter
Zoijar schreef op maandag 06 december 2004 @ 19:27:
Alleen de grootte van 'char' staat vast op 1 byte. (dat hoeven niet eens 8 bits te zijn)

Vandaar, wat de meeste mensen doen, is een typedef maken in de vorm van 'typedef unsigned int uint32;'. Per platform zet je deze typedefs dan goed. Je kan dit nog compiletime laten checken, door traits/limits te raadplegen bij het compilen, en kijken of de range van je type klopt.

Overigens gebruik je in C++ <limits> en de klasse std::numeric_limits. Dan kan je bv zo checken of je type klopt: static_check(std::numeric_limits<uint32>::is_signed, uint32_is_not_unsigned);
Jouw antwoord is wat ik ongeveer verwachtte...

In allerlei Linux-broncode gebruikt men ook dat soort uint32's e.d., merkte ik op.

Niet zo fraai, dat dit via eigen typedef's moet (per platform verschillend ook nog, om een of andere reden? :?). Is er misschien een voorbeeld-headerfile beschikbaar (ik ga zometeen googelen)?

Verwijderd

Alleen de grootte van 'char' staat vast op 1 byte.
Helaas is dat ook niet meer gegarandeerd. Onder unicode is een char 1, 2 of 4 bytes groot, afhankelijk van compiler settings...

Verwijderd

Topicstarter
MaxxRide schreef op maandag 06 december 2004 @ 19:27:
Met deze header file is dat toch gedefinieerd? Een 8 bit unsigned int is van 0 tot 255. In jouw header file geef je al duidelijk aan wat de ranges (en dus het aantal bits en signed status) is.

Of begrjip ik je niet goed?
Ik zie alleen een (8-bits) char beschrijving...

Verder is dit dus afhankelijk van die header file. Een andere compiler kan net zo goed met een andere headerfile komen om de limits te bepalen. Wellicht kan je deze overriden... maar of dat zo verstandig en productief is vraag ik me dan af.

Verwijderd

Topicstarter
Eelis schreef op maandag 06 december 2004 @ 19:58:
C99's <stdint.h> biedt allerhande fixed-size integer types.
Fantastisch! :)

De C99-compliance vrijwel nergens 100%, maar kan jij mogelijk iets zeggen over de ondersteuning/aanwezigheid van deze headerfile onder compilers (ik denk in het bijzonder aan: de eerder genoemde Borland IDE/compiler, de Borland C++Builder 6, GCC en MS Visual Studio (.NET eventueel)?)?

BTW: aangezien het een extra headerfile betreft, zijn dit dus geen standaard primitives. Ik vraag me dan af waarom er niet ten minste fixed-size integer types als standaard primitives aanwezig zijn. Ik zie het nut van een platformafhankelijke int bit-grootte wel in hoor, maar waarom is er niet gewoon de mogelijkheid tot fixed-size integer types zonder het hoeven includen van allerlei headerfiles, in moderne compilers?

Verwijderd

Verwijderd schreef op maandag 06 december 2004 @ 20:50:
[...]

Helaas is dat ook niet meer gegarandeerd. Onder unicode is een char 1, 2 of 4 bytes groot, afhankelijk van compiler settings...
Dat zijn wchar_t (of hoe dat type ook heet), geen char.

Verwijderd

Topicstarter
Verwijderd schreef op maandag 06 december 2004 @ 21:02:
[...]


Dat zijn wchar_t (of hoe dat type ook heet), geen char.
idd. :)

Levert (voor mij :P) wederom een vraag op: waarom is er niet gewoon een 'byte' primitive type, of anders de eerder genoemde fixed-size integer, in dit geval van 8-bits? :?
Nu komt men erachter dat het gelijkstellen van een char en een byte nare gevolgen heeft...
Of dacht men vroeger nog niet zo 'internationalized'? >:)

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Verwijderd schreef op maandag 06 december 2004 @ 20:50:
Helaas is dat ook niet meer gegarandeerd. Onder unicode is een char 1, 2 of 4 bytes groot, afhankelijk van compiler settings...
De C++ standaard garandeert dat, anders is de compiler niet standard compliant. (een byte is simpelweg het kleinst adreseerbare stukje geheugen. Het is in principe niet ondekbaar bij deze definitie dat een 64bit machine, 16bit bytes heeft, 'char' zal dan in C++ op die systemen 16bits zijn)
Verwijderd schreef op maandag 06 december 2004 @ 20:46:
Jouw antwoord is wat ik ongeveer verwachtte...

In allerlei Linux-broncode gebruikt men ook dat soort uint32's e.d., merkte ik op.

Niet zo fraai, dat dit via eigen typedef's moet (per platform verschillend ook nog, om een of andere reden? :?). Is er misschien een voorbeeld-headerfile beschikbaar (ik ga zometeen googelen)?
Normaal gesproken boeit het toch ook niet echt? Je wilt een integer of float hebben, en het liefst eentje van machine grootte omdat dat het meest efficient is. Alleen bij dingen als data opslag of netwerken boeit het echt, maar daar heb je zoals mietje al opmerkte, nog de endianness problemen. Dus dan gebruik je toch al conversie routines.

Vaak heb je op een systeem wel een header file staan met dat soort types, maar dat is niet verplicht; je kan er dus niet vanuit gaan. Het is beter dat je als applicatie programmeur de aan names over je systeem doet (mbv typedefs etc) dan dat de taal/platform die aan je oplegt.

[ Voor 8% gewijzigd door Zoijar op 06-12-2004 21:11 ]


Verwijderd

Verwijderd schreef op maandag 06 december 2004 @ 21:05:
[...]

idd. :)

Levert (voor mij :P) wederom een vraag op: waarom is er niet gewoon een 'byte' primitive type, of anders de eerder genoemde fixed-size integer, in dit geval van 8-bits? :?
Nu komt men erachter dat het gelijkstellen van een char en een byte nare gevolgen heeft...
Of dacht men vroeger nog niet zo 'internationalized'? >:)
Ik weet niet op hoeveel platforms jij je applicatie moet draaien. Enige waar jij je zorgen over hoeft te maken is: wat de grootte is van een int (32 of 64) en of er een 64 bits type int voorkomt (__int64 op windows en long long op Linux en op sommige unixs niet aanwezig) char en short zijn op de huidige gebruikte platformen overal het zelfde.

* disclaimer: ik neem aan dat embedded platforms zich hier ook aan houden... heb ik geen ervaring mee

Verwijderd

Topicstarter
Verwijderd schreef op maandag 06 december 2004 @ 20:25:
[...]


Met cross-platform neem ik aan dat er hier een binair bestandsformaat of netwerkprotocol bedoeld wordt?
Jij bedoelt de toepassing, denk ik. :)
Ik bedoelde dus cross-platform compilen (is puur iets waartoe ik me zoveel mogelijk dwing, is slechts een console applicatie ter leering ende zwoeghen :)).
Maar een toepassing van het door mij geopperde 'probleem' (gevaarlijk woord :P) is idd een binair bestandsformaat dat (gelukkig) een DWORD-veld bevat met een decimaal getal, dat ik wil casten naar een int. Schiet me niet af als deze benadering onzinnig, onnodig, of gevaarlijk zou zijn. :o
In dat geval moet je met meer dingen rekening houden dan alleen de bit- en bytesizes van je variabelen; je moet ook rekening houden met endianness, de volgorde waarin de bytes van een multibyte-type geschreven worden (er zijn zelfs obscure platforms met een omgekeerde bit-endianness). Zoijars tips zijn prima voor sizeof() en signedness, maar lossen het endianness probleem niet op.
Hmmm, endianness kan toch door de compiler afgehandeld worden (als ik dat probleem voldoende in acht neem natuurlijk)? Goed, daaraan zitten natuurlijk meerdere aspecten. Bedoel je dat ik in een aantal #define's e.d. etc. op moet nemen om rekening te kunnen houden met de endianness? Of dat die casts waar ik eerder over schreef niet zondermeer slagen?

Verwijderd

Topicstarter
Verwijderd schreef op maandag 06 december 2004 @ 20:32:
Ligt dat gewoon niet aan wat de data model is van het platform dat je runt:
Hehehe, dat feit was al wel duidelijk. ;)

Verwijderd

Verwijderd schreef op maandag 06 december 2004 @ 21:12:
[...]

Jij bedoelt de toepassing, denk ik. :)
Ik bedoelde dus cross-platform compilen (is puur iets waartoe ik me zoveel mogelijk dwing, is slechts een console applicatie ter leering ende zwoeghen :)).
Maar een toepassing van het door mij geopperde 'probleem' (gevaarlijk woord :P) is idd een binair bestandsformaat dat (gelukkig) een DWORD-veld bevat met een decimaal getal, dat ik wil casten naar een int. Schiet me niet af als deze benadering onzinnig, onnodig, of gevaarlijk zou zijn. :o
DWORD is toch al 32 bits...? Weinig te casten lijkt mij.
Hmmm, endianness kan toch door de compiler afgehandeld worden (als ik dat probleem voldoende in acht neem natuurlijk)? Goed, daaraan zitten natuurlijk meerdere aspecten. Bedoel je dat ik in een aantal #define's e.d. etc. op moet nemen om rekening te kunnen houden met de endianness? Of dat die casts waar ik eerder over schreef niet zondermeer slagen?
Nee, moet je zelf doen. Als jij een file openent waarin een bepaalde endianness wordt gehouden dat moet je checken of het platform waar je op draait de zelfde endianness heeft, zoniet alles converteren tijdens het inlezen. Zelfde idee als je het gaat uitschrijven.

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Overigens zijn weining dingen compleet platform onafhankelijk hoor. Een bekende quote hierover is "There is no such thing as portable code; only ported code."

Verwijderd

Topicstarter
Zoijar schreef op maandag 06 december 2004 @ 21:09:

[...]

Normaal gesproken boeit het toch ook niet echt?
:D
Tja.
Daar ga ik voor de verandering eens niet op in, om een eindeloze discussie te vermijden. :P
Je wilt een integer of float hebben, en het liefst eentje van machine grootte omdat dat het meest efficient is. Alleen bij dingen als data opslag of netwerken boeit het echt, maar daar heb je zoals mietje al opmerkte, nog de endianness problemen. Dus dan gebruik je toch al conversie routines.
Zie het volgende deel van mijn reactie voor een reactie aangaande deze hoofdzaak. Maar iets ter overweging: wat zou er sneller zijn, een cast van een paar bytes naar een int (in één keer) eventueel met ondersteuning van wat conversie routines, of... tja wat kan je anders doen... allerlei OS-specifieke constructies inbouwen (in de headerfiles, is dan het eerste waar ik aan zou denken)?
Vaak heb je op een systeem wel een header file staan met dat soort types, maar dat is niet verplicht; je kan er dus niet vanuit gaan. Het is beter dat je als applicatie programmeur de aan names over je systeem doet (mbv typedefs etc) dan dat de taal/platform die aan je oplegt.
Mwa, het gaat niet zozeer om opleggen. Als de type-naam __intx is, lijkt me wel duidelijk welke restrictie je je precies aanmeet met het nemen van dat type voor een variabele. Ik vraag me alleen af, waarom deze fixed-size types niet als primitives zijn opgenomen. Eventuele types met variabele bit-grootte hebben uiteraard hun nut, en ik heb er niets op tegen als die ook opgenomen worden.

Per slot van rekening is een fixed-size type stukken 'primitiever' dan dat soort variabele dingen, vind je niet?

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Verwijderd schreef op maandag 06 december 2004 @ 21:25:
Mwa, het gaat niet zozeer om opleggen. Als de type-naam __intx is, lijkt me wel duidelijk welke restrictie je je precies aanmeet met het nemen van dat type voor een variabele. Ik vraag me alleen af, waarom deze fixed-size types niet als primitives zijn opgenomen. Eventuele types met variabele bit-grootte hebben uiteraard hun nut, en ik heb er niets op tegen als die ook opgenomen worden.

Per slot van rekening is een fixed-size type stukken 'primitiever' dan dat soort variabele dingen, vind je niet?
Omdat je dan de taal niet op elk platform kan draaien. Stel dat jouw machine dus 16bit bytes heeft, en je hebt een type __int8 in je taal standaard opgenomen; wat ga je dan doen? Of een bekender voorbeeld, __int64 op een 32bit systeem? Mijn code met __int64 is platform onafhankelijk, want dat zegt de standaard...alleen draait het niet op een 32bit systeem. Dat is een tegenstelling.

__int64 is geen standaard type, en hoeft dus nergens te werken. Dat het met MSVC7 werkt, zegt niet dat het overal werkt ... :)

[ Voor 7% gewijzigd door Zoijar op 06-12-2004 21:32 ]


Verwijderd

Topicstarter
Verwijderd schreef op maandag 06 december 2004 @ 21:11:
[...]


Ik weet niet op hoeveel platforms jij je applicatie moet draaien. Enige waar jij je zorgen over hoeft te maken is: wat de grootte is van een int (32 of 64) en of er een 64 bits type int voorkomt (__int64 op windows en long long op Linux en op sommige unixs niet aanwezig) char en short zijn op de huidige gebruikte platformen overal het zelfde.

* disclaimer: ik neem aan dat embedded platforms zich hier ook aan houden... heb ik geen ervaring mee
Ach, moet...
Zolang het maar POSIX/Windows-compatibel is... Een wild guess.

Ik wil ook een 8-bits integer hebben hé...
En waar ik me zorgen over zou hoeven maken, is eigenlijk juist wat ik hiermee uit de weg probeer te ruimen. Liever een fixed-size int dan allerlei delicate afhankelijkheden en constructies die later mijn code kunnen breaken...

Zou __int64 niet correct worden gehanteerd op het Linux-platform? :?
Dat heeft de compiler toch zelf in de hand? Waarom zou dat dan zo incompatibel worden gemaakt?

Verwijderd

Verwijderd schreef op maandag 06 december 2004 @ 21:31:
[...]

Ach, moet...
Zolang het maar POSIX/Windows-compatibel is... Een wild guess.

Ik wil ook een 8-bits integer hebben hé...
Dat heb je: char
En waar ik me zorgen over zou hoeven maken, is eigenlijk juist wat ik hiermee uit de weg probeer te ruimen. Liever een fixed-size int dan allerlei delicate afhankelijkheden en constructies die later mijn code kunnen breaken...
Ik ken eigenlijk geen enkel huidig platform (POSIX/Windows) waar de int niet 32 bits. ILP64 wordt denk ik haast nergen gebruikt.
Zou __int64 niet correct worden gehanteerd op het Linux-platform? :?
Dat heeft de compiler toch zelf in de hand? Waarom zou dat dan zo incompatibel worden gemaakt?
Zou kunnen, maar long long wordt door de Sun Compiler en GCC compiler als een 64bits aangezien. En aangezien 64bits int niet in ILP32 standaard is gedefineerd mag elke compiler het anders doen.

Verwijderd

Topicstarter
Zoijar schreef op maandag 06 december 2004 @ 21:28:
[...]

Omdat je dan de taal niet op elk platform kan draaien. Stel dat jouw machine dus 16bit bytes heeft, en je hebt een type __int8 in je taal standaard opgenomen; wat ga je dan doen?
Een systeem met 16-bit bytes?
Wellicht één of ander obscuur embedded-systeem, dat dat zo heeft denk ik maar. :P
Maar enfin, uiteraard ga ik hierbij uit van 8 bits per byte...
Maar dat is puur een kunstmatige barriere, die je daar noemt.
Dan noemt men het toch __int8_16? Of wat begrijpelijker: int_16_8.
En dan voor zowel 16 bits per byte als 8 bits per byte definities bepalen.
Uiteraard is de wildgroei aan platforms wat dit betreft een probleem, maar volgens mij kan deze methode hier voldoende het hoofd aan bieden.
Of een bekender voorbeeld, __int64 op een 32bit systeem? Mijn code met __int64 is platform onafhankelijk, want dat zegt de standaard...alleen draait het niet op een 32bit systeem. Dat is een tegenstelling.
Bedoel je met dat systeem een systeem met 32-bits per byte, of met een 32-bits adress space?
In het laatste geval: de compiler kan, in theorie tenminste, die types best mappen naar 2 CPU registers. Traag en inefficient, okay, maar als je zo veel waarde hecht aan cross-platform compilability dan heb je daarmee de oplossing.

Verwijderd

Topicstarter
Na-na. Ik citeer:
maar ik wil o.a. een 8-bits unsigned int (ja, ik kan natuurlijk casten naar een unsigned char)
Die mogelijkheid geef ik al aan (en doe ik impliciet af ;)).
Echter, die 8-bit int dient als index in een array.
Daar gaat je char. :P
(Of ik weet niet dat je ook een char als index kunt opgeven :o)
[...]


Ik ken eigenlijk geen enkel huidig platform (POSIX/Windows) waar de int niet 32 bits. ILP64 wordt denk ik haast nergen gebruikt.
Dat zal best, maar ik streeft theoretische (benadering van) perfectie na hé. :P
Waarom berusten in allerlei aannames en toevalligheden als er (mogelijk) ook een fixed-size integer type beschikbaar is? :)
[...]


Zou kunnen, maar long long wordt door de Sun Compiler en GCC compiler als een 64bits aangezien. En aangezien 64bits int niet in ILP32 standaard is gedefineerd mag elke compiler het anders doen.
De ILP32-standaard ken ik niet. Maar aan de naam te zien, is deze gericht op 32-bits platforms. Dan is dat vrij logisch. Het kan natuurlijk zijn dat er nog geen standaarden bestaan die rekening houden met 64-bits primitives. In dat geval is het puur een praktische beperking, geen fundamentele beperking van C++ die niet binnen afzienbare tijd opgelost kan/gaat worden.

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Ja, maar dan krijg je dus een explosie van mappings and conversies die compiler schrijver moeten gaan implementeren, voor elk platform dat compiler op draait. Waarvan sommige conversies compleet inefficient zullen worden, of andere zelf niet mogelijk.(je kan bv geen 8bit deel van een 16bit unit atomisch zetten, zonder het andere deel te wijzigen) Dus wordt de keuze gelegd bij de gebruiker; als je het perse wilt, dan kan je het zelf implementeren :)

16bit byte is niet zo obscuur hoor, het zou zo maar kunnen gebeuren op een 64bit architectuur. Je kan al geen registers meer indexeren op 8bit units tegenwoordig. Het geheugen zou ook prima over kunnenstappen op 16bit units. Oh, ja ik bedoelde idd 32bit adres space, net als 64 nu.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Niemand nog std::bitset<N> genoemd? Werkt overal, heeft overal N bits. Converteerbaar naar unsigned long voor N<=32.

Overigens is er wel wat discussie over <stdint.h> uit C99 in de C++ commissie. Je hoort wel vaak dat hun huidige oplossing niet goed past in C++. Zo zit het vol met hacks die het gemis aan operator overloading, UDT's, en uniforme conversie regels proberen te compenseren. C++ heeft dat in vergelijking wel. Ook is het erg verrassend dat int8_t niet het meest efficiente 8 bits type is.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Topicstarter
Zoijar schreef op maandag 06 december 2004 @ 21:49:
Ja, maar dan krijg je dus een explosie van mappings and conversies die compiler schrijver moeten gaan implementeren, voor elk platform dat compiler op draait.
Hoe bedoel je voor elk platform?
In de zin van: OS(-groep), helemaal niet als het goed is.
In de zin van: systeem-architectuur, ja idd.
Maar stel dat men rekening houdt met die 8-bits per byte en die 16-bits per byte.
Dan krijg je dus grofweg een headerfile van dezelfde lengte als hij nu is, maal 2 (voor het beschrijven van de laatste).

De huidige headerfile zoals meegeleverd bij Borland C++BuilderX:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*  stdint.h

    Integer types - c99 7.18
*/

/*
 *      C/C++ Run Time Library - Version 11.0
 *
 *      Copyright (c) 2002 by Borland Software Corporation
 *      All Rights Reserved.
 *
 */


#ifndef __STDINT_H
#define __STDINT_H

/* 7.18.1.1 Exact-width integer types */

typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;

typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;



/* 7.18.1.2 Minimum-width integer types */

typedef __int8 int_least8_t;
typedef __int16 int_least16_t;
typedef __int32 int_least32_t;
typedef __int64 int_least64_t;

typedef unsigned __int8 uint_least8_t;
typedef unsigned __int16 uint_least16_t;
typedef unsigned __int32 uint_least32_t;
typedef unsigned __int64 uint_least64_t;



/* 7.18.1.3 Fastest minimum-width integer types */

typedef __int8 int_fast8_t;
typedef __int16 int_fast16_t;
typedef __int32 int_fast32_t;
typedef __int64 int_fast64_t;

typedef unsigned __int8 uint_fast8_t;
typedef unsigned __int16 uint_fast16_t;
typedef unsigned __int32 uint_fast32_t;
typedef unsigned __int64 uint_fast64_t;



/* 7.18.1.4 Integer types capable of holding object pointers */

typedef int32_t intptr_t;
typedef uint32_t uintptr_t;



/* 7.18.1.5 Greatest-width integer types */

typedef int64_t intmax_t;
typedef uint64_t uintmax_t;



/* 7.18.2.1 Limits of exact-width integer types */

#define INT8_MIN ((int8_t) -128)
#define INT16_MIN ((int16_t) -32768)
#define INT32_MIN ((int32_t) -2147483648) 
#define INT64_MIN ((int64_t) -9223372036854775808)

#define INT8_MAX ((int8_t) 127)
#define INT16_MAX ((int16_t) 32767)
#define INT32_MAX ((int32_t) 2147483647)
#define INT64_MAX ((int64_t) 9223372036854775807)

#define UINT8_MAX ((uint8_t) 255)
#define UINT16_MAX ((uint16_t) 65535)
#define UINT32_MAX ((uint32_t) 4294967295)
#define UINT64_MAX ((uint64_t) 18446744073709551615)



/* 7.18.2.2 Limits of minimum-width integer types */

#define INT_LEAST8_MIN ((int_least8_t) -128)
#define INT_LEAST16_MIN ((int_least16_t) -32768)
#define INT_LEAST32_MIN ((int_least32_t) -2147483648)
#define INT_LEAST64_MIN ((int_least64_t) -9223372036854775808)

#define INT_LEAST8_MAX ((int_least8_t) 127)
#define INT_LEAST16_MAX ((int_least16_t) 32767)
#define INT_LEAST32_MAX ((int_least32_t) 2147483647)
#define INT_LEAST64_MAX ((int_least64_t) 9223372036854775807)

#define UINT_LEAST8_MAX ((uint_least8_t) 255)
#define UINT_LEAST16_MAX ((uint_least16_t) 65535)
#define UINT_LEAST32_MAX ((uint_least32_t) 4294967295)
#define UINT_LEAST64_MAX ((uint_least64_t) 18446744073709551615)



/* 7.18.2.3 Limits of fastest minimum-width integer types */

#define INT_FAST8_MIN ((int_fast8_t) -128)
#define INT_FAST16_MIN ((int_fast16_t) -32768)
#define INT_FAST32_MIN ((int_fast32_t) -2147483648)
#define INT_FAST64_MIN ((int_fast64_t) -9223372036854775808)

#define INT_FAST8_MAX ((int_fast8_t) 127)
#define INT_FAST16_MAX ((int_fast16_t) 32767)
#define INT_FAST32_MAX ((int_fast32_t) 2147483647)
#define INT_FAST64_MAX ((int_fast64_t) 9223372036854775807)

#define UINT_FAST8_MAX ((uint_fast8_t) 255)
#define UINT_FAST16_MAX ((uint_fast16_t) 65535)
#define UINT_FAST32_MAX ((uint_fast32_t) 4294967295)
#define UINT_FAST64_MAX ((uint_fast64_t) 18446744073709551615)



/* 7.18.2.4 Limits of integer types capable of holding object pointers */

#define INTPTR_MIN ((intptr_t) -32768)
#define INTPTR_MAX ((intptr_t) 32767)
#define UINTPTR_MAX ((intptr_t) 65535)



/* 7.18.2.5 Limits of greatest-width integer types */

#define INTMAX_MIN ((intmax_t) -9223372036854775808)
#define INTMAX_MAX ((intmax_t) 9223372036854775807)
#define UINTMAX_MAX ((uintmax_t) 18446744073709551615)



/* 7.18.3 Limits of other integer types */

#define PTRDIFF_MIN ((int32_t) -65536)
#define PTRDIFF_MAX ((int32_t) 65535)

#ifdef __STDC_LIMIT_MACROS
#define SIG_ATOMIC_MIN INT32_MIN
#define SIG_ATOMIC_MAX INT32_MAX
#endif

#define SIZE_MAX 65535

#ifdef __STDC_CONSTANT_MACROS
#define WCHAR_MIN INT16_MIN
#define WCHAR_MAX INT16_MAX
#define WINT_MIN INT16_MIN
#define WINT_MAX INT16_MAX
#endif



/* 7.18.4.1 Macros for minimum-width integer constants */

#define INT8_C(x) ((int8_t) x)
#define INT16_C(x) ((int16_t) x)
#define INT32_C(x) ((int32_t) x)
#define INT64_C(x) ((int64_t) x)

#define UINT8_C(x) ((uint8_t) x)
#define UINT16_C(x) ((uint16_t) x)
#define UINT32_C(x) ((uint32_t) x)
#define UINT64_C(x) ((uint64_t) x)



/* 7.18.4.2 Macros for greatest-width integer constants */

#define INTMAX_C(x) ((intmax_t) x)
#define UINTMAX_C(x) ((uintmax_t) x)

#endif /* __STDINT_H */


Dat is toch niet zo gigantisch?
Eventueel wordt bepaald dat er aparte headerfiles dienen te komen voor iedere architectuur (in de zin van: een bepaald aantal bits per byte). Dan kan iedereen mooi bepalen wat hij wel of niet include. Bovendien gaat het om fixed-size types. Dus ik zie niet in wat voor speciale mappings en conversies er dan opgenomen zouden moeten worden in deze headerfiles. Jij doelt op de compilers zelf. Tja, ze zullen waarschijnlijk wat meer moeten zwoegen nu, die coders daarvan. :P
Waarvan sommige conversies compleet inefficient zullen worden,
Nota bene: de programmeur kiest er zelf voor om bepaalde types te benutten in zijn code, en te eisen dat deze voor bepaalde platforms compileert. Dus niets en niemand wordt gedwongen tot het doen van inefficiente conversies e.d.. Eigen verantwoordelijkheid dus. :)
of andere zelf niet mogelijk.(je kan bv geen 8bit deel van een 16bit unit atomisch zetten, zonder het andere deel te wijzigen)
Hoe bedoel je precies? Er zijn toch higher en lower bits?
Tja, de losse delen an sich vormen inderdaad geen (zondermeer) scheidbaar deel van het grotere 16-bits geheel, maar wil je zoiets per se (zou goed kunnen hoor, ik ben benieuwd :))?
Dus wordt de keuze gelegd bij de gebruiker; als je het perse wilt, dan kan je het zelf implementeren :)
Maar let wel, er is een verschil van benadering. Wat jij nu stelt kan wel, maar alleen met includes van (aangepaste) headerfiles. Ik pleit nu (in feite :)) voor het opnemen van primitieve types van fixed-size int's voor bepaalde platforms/architecturen. Okay, dan zullen er natuurlijk keuzes gemaakt moeten worden. Desnoods neem je alle praktisch mogelijke varianten op, zo veel zijn het er ook weer niet (welke platforms bestaan er nog meer, met een afwijkend aantal bits per byte?).
16bit byte is niet zo obscuur hoor, het zou zo maar kunnen gebeuren op een 64bit architectuur. Je kan al geen registers meer indexeren op 8bit units tegenwoordig.
Hoe bedoel je dit precies?
Werken mijn dierbare ah, al, etc. niet meer? :{ :'(
Het geheugen zou ook prima over kunnenstappen op 16bit units. Oh, ja ik bedoelde idd 32bit adres space, net als 64 nu.
Op het eerste gezicht lijkt die stap me wat vergezocht. Niet dat ik er geen voorstander van zou zijn, maar het is een beetje een (hoe ging die beeldspraak ook al weer, met die koe :?) 'betekenisloze' redenering. Alles kan natuurlijk, maar zie jij dit zomaar gebeuren?

Verwijderd

Topicstarter
MSalters schreef op maandag 06 december 2004 @ 22:00:
Niemand nog std::bitset<N> genoemd? Werkt overal, heeft overal N bits. Converteerbaar naar unsigned long voor N<=32.
Maar dus wel <= 32... Waarom eigenlijk, dat kan jij vast wel vertellen... :)

Maar wat als ik een gegeven unsigned char heb, en een char[] met een size van 4 bytes?
Deze wil ik omzetten naar respectievelijk een 8-bits unsigned integer en een 32-bits unsigned integer, cross-platform(!).
Overigens is er wel wat discussie over <stdint.h> uit C99 in de C++ commissie. Je hoort wel vaak dat hun huidige oplossing niet goed past in C++. Zo zit het vol met hacks die het gemis aan operator overloading, UDT's, en uniforme conversie regels proberen te compenseren. C++ heeft dat in vergelijking wel. Ook is het erg verrassend dat int8_t niet het meest efficiente 8 bits type is.
C++ = C99, toch? :? (waarbij '=' staat voor de golvende = ;))

Maar hoe bedoel je precies, die problemen. Hebben die een onontkoombare oorzaak? Je noemt natuurlijk al dat gemis, dus de voorziening in die functionaliteiten zou die hacks onnodig maken. Maar wordt hier (op korte termijn) nog iets aan gedaan? Want als stdint.h zo problematisch is had men dat al wel kunnen zien tijdens het opstellen van de C99-standaard, niet?

Verwijderd

Verwijderd schreef op maandag 06 december 2004 @ 21:12:
Jij bedoelt de toepassing, denk ik. :)
Ik bedoelde dus cross-platform compilen (is puur iets waartoe ik me zoveel mogelijk dwing, is slechts een console applicatie ter leering ende zwoeghen :)).
Dat bedoel ik ook. Sommige architecturen werken intern met multi-byte types zoals ints door het laagstwaardige byte het eerst op te slaan gevolgd door steeds hoogwaardigere bytes, andere architecturen slaan het hoogstwaardige byte het eerst op en eindigen met het laagstwaardige byte. Als je bestandsformaat leesbaar moet zijn op beide architecturen, dan zal een van de twee architecturen multi-byte types moeten omschrijven.
Maar een toepassing van het door mij geopperde 'probleem' (gevaarlijk woord :P) is idd een binair bestandsformaat dat (gelukkig) een DWORD-veld bevat met een decimaal getal, dat ik wil casten naar een int. Schiet me niet af als deze benadering onzinnig, onnodig, of gevaarlijk zou zijn. :o
Veronderstel dat de decimale waarde "1234" in een DWORD is opgeslagen als 4 bytes, dan zal dat door little-endian machines worden opgeslagen als "4321" en door big-endian machines als "1234". Als je echt portable code, cq. echt portable binaire bestands- of netwerkprotocollen wilt schrijven, moet je daar rekening mee houden (zoals bv. met de bekende htonl() en ntohl() conversies bij tcp/ip). Dat kan de compiler niet voor je doen, de compiler hanteert altijd de native endianness van de architectuur en weet niet welke endianness het bestands- of netwerkprotocol gebruikt.

Verwijderd

Verwijderd schreef op maandag 06 december 2004 @ 21:48:
Die mogelijkheid geef ik al aan (en doe ik impliciet af ;)).
Echter, die 8-bit int dient als index in een array.
Daar gaat je char. :P
(Of ik weet niet dat je ook een char als index kunt opgeven :o)
Hoe denk je dat int8_t is gedefineerd... ?

typedef signed char int8_t;

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Verwijderd schreef op dinsdag 07 december 2004 @ 02:49:
[...]
Hoe denk je dat int8_t is gedefineerd... ?

typedef signed char int8_t;
Lijkt me gangbaar, maar niet verplicht. Als char 16 bits is (niet ongebruikelijk in mobieltjes, naar het schijnt) dan mag dit niet. int8_t moet precies 8 bits range hebben, alhoewel de hoeveelheid gebruikte bits groter mag zijn.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Verwijderd schreef op maandag 06 december 2004 @ 22:29:
[...]

Maar dus wel <= 32... Waarom eigenlijk, dat kan jij vast wel vertellen... :)
Omdat unsigned long tenminste 32 bits is, dus portable kun je er van uitgaan dat een bitset<32> in een unsigned long past.
Maar wat als ik een gegeven unsigned char heb, en een char[] met een size van 4 bytes?
Deze wil ik omzetten naar respectievelijk een 8-bits unsigned integer en een 32-bits unsigned integer, cross-platform(!).
Waarom? Wat wil je er precies mee doen? Wil je modulo-256 wiskunde? En wat ga je doen als je char[4] 64 bits bevat? cross-platform kan dat gebeuren.
[...]

C++ = C99, toch? :? (waarbij '=' staat voor de golvende = ;))
Absoluut niet. C++98 is gebaseerd op C94 (=C89+bugfixes), daarna is C geforked en zijn er een aantal uitbreidingen bijgekomen (_Bool, _Complex, embedded spul). Dat wordt C99 genoemd. In C++03 zijn die extra zaken niet meegenomen; ook deze mid-term update is een bugfix release.
Maar hoe bedoel je precies, die problemen. Hebben die een onontkoombare oorzaak? Je noemt natuurlijk al dat gemis, dus de voorziening in die functionaliteiten zou die hacks onnodig maken. Maar wordt hier (op korte termijn) nog iets aan gedaan? Want als stdint.h zo problematisch is had men dat al wel kunnen zien tijdens het opstellen van de C99-standaard, niet?
De problemen zijn natuurlijk gezien tijdens de ontwikkeling van C99. Alleen,om ze in C99 op te lossen had C99 een heleboel features van C++ moeten terugporten. Dat zou de compilers complexer maken, maar de taal makkelijker. Daarvoor is niet gekozen, en dat heeft te maken met de mensen die nog C compilers maken. Dat zijn meestal kleine bedrijfjes voor embedded systemen. De "grote jongens" in de wereld (Microsoft, Sun, Borland, Gnu) hebben wel de resources om iets als operator overloading te intrduceren (zo'n feature zal al gauw 5.000 euro kosten)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Even volledig uit context wil ik op deze opmerking inhaken:
Zoijar schreef op maandag 06 december 2004 @ 21:49:
[...]
(je kan bv geen 8bit deel van een 16bit unit atomisch zetten, zonder het andere deel te wijzigen)
[...]
Dat weet ik nog niet zeker. Ik weet nog van het assembler proggelen van vrûûger op mijn trouwe 286 (een 16-bits machine met 8-bit woorden), dat je prima de twee 4-bits halven van een 8-bits woord kon adresseren (van registers dan toch, en die manipuleer je toch het meest).

Ik zie dus niet in waarom er op een machine met 16-bits woorden niet zo'n faciliteit zou zijn.

(Maar nogmaals, dit is waarschijnlijk lichtelijk off-topic :))

Verwijderd

Topicstarter
Verwijderd schreef op dinsdag 07 december 2004 @ 01:18:
[...]


Dat bedoel ik ook. Sommige architecturen werken intern met multi-byte types zoals ints door het laagstwaardige byte het eerst op te slaan gevolgd door steeds hoogwaardigere bytes, andere architecturen slaan het hoogstwaardige byte het eerst op en eindigen met het laagstwaardige byte. Als je bestandsformaat leesbaar moet zijn op beide architecturen, dan zal een van de twee architecturen multi-byte types moeten omschrijven.
Als ik vaststel dat in het bewuste bestandsformaat het getal big endian wordt beschreven, dan kan ik toch htonl() gebruiken? In dat geval gaat het immers om een 32-bits byte-reeks.
En data wordt op byte-niveau getransporteerd/opgeslagen, dus met de systeem-architecturen die Zoijar noemde, met 16 bits per byte, hoef ik in principe geen rekening te houden.
Hoewel, het probleem begint pas bij het uitlezen van de char's in een IO-routine. Op die architectuur zijn die char's dus 16 bits, als het goed is. Dus op dat punt moet er ik al rekening mee houden... :o
Zijn er geen handige defines om uit te zoeken hoeveel bits per byte de doel-systeem-architectuur hanteert? Zo niet dan wordt het idd allemaal vrij lastig. Maar er is al veel geklaagd over de wildgroei aan platforms en/of systeem-architecturen, dus dat probleem lijkt me al bekend.
Bovendien krijg je het probleem dat je niet weet volgens welke endianness het ingelezen bestand oorspronkelijk is weggeschreven. Maar dat zou je kunnen afvangen door een heldere standaard neer te zetten.
[...]


Veronderstel dat de decimale waarde "1234" in een DWORD is opgeslagen als 4 bytes, dan zal dat door little-endian machines worden opgeslagen als "4321" en door big-endian machines als "1234".
Hehe, dat principe begreep ik al wel hoor. ;)
Maar dit legt wel weer een ander probleem bloot, namelijk het wegschrijven van data. Dat zal ik op dit moment nog niet doen in dat bestandsformaat, maar ook daar zal de systeem-architectuur zijn eigen draai geven aan het gewenste resultaat ja... :|
Als je echt portable code, cq. echt portable binaire bestands- of netwerkprotocollen wilt schrijven, moet je daar rekening mee houden (zoals bv. met de bekende htonl() en ntohl() conversies bij tcp/ip). Dat kan de compiler niet voor je doen, de compiler hanteert altijd de native endianness van de architectuur en weet niet welke endianness het bestands- of netwerkprotocol gebruikt.
In hoeverre hanteert de compiler dit precies? Of eigenlijk, hanteren de standaard-headerfiles de endianness ook (bijv. bij IO-methodes)? Volgens mij zie ik dat wel goed, als ik vermoed dat dit ook in de headerfiles wordt gehanteerd, toch? Lijkt me iig logisch.
Hmmm, iets wat me te binnen schoot: kan je geen compiler optie meegeven die bepaalt welke endianness de compiler hanteert bij het compilen van de broncode? Dus los van de systeem-architectuur waar je op werkt? Als je niet te low level gaat (d.m.v. assembly routines bijv.), zou dat toch moet kunnen werken, of zie ik dan iets over het hoofd?

[ Voor 1% gewijzigd door Verwijderd op 07-12-2004 17:01 . Reden: Smiley-fix ]


Verwijderd

Topicstarter
Verwijderd schreef op dinsdag 07 december 2004 @ 02:49:
[...]


Hoe denk je dat int8_t is gedefineerd... ?

typedef signed char int8_t;
typedef __int8 int8_t;

#define INT8_MIN ((int8_t) -128)

#define INT8_C(x) ((int8_t) x)
Eerder baseren ze de char-definities op deze int, zij het alleen voor wchar_t natuurlijk.
Maar ik wil die int dus als index van een array gebruiken, en dat kan voor zover ik weet niet met enige char oid.

Verwijderd

Topicstarter
MSalters schreef op dinsdag 07 december 2004 @ 10:06:
[...]

Omdat unsigned long tenminste 32 bits is, dus portable kun je er van uitgaan dat een bitset<32> in een unsigned long past.
Ja precies, maar waarom (maximaal) unsigned long?
Waarom niet de eerder genoemde long long of __int64 (waarom er onderscheid tussen die 2 is gemaakt vraag ik me nog steeds af...)?
[...]

Waarom? Wat wil je er precies mee doen? Wil je modulo-256 wiskunde? En wat ga je doen als je char[4] 64 bits bevat? cross-platform kan dat gebeuren.
Het heeft wat weg van wiskunde met een modulo van 256, maar dat zal in dit geval gewoon het max. bereik van de index van een bepaalde array zijn (unsigned dus hé). Ik snap wel dat het ook met een int-type met een grotere bit-grootte zou kunnen, maar waarom zou ik dat willen. Is theoretisch gezien minder efficient. :D
Dat 2e punt heeft Zoijar idd al aangestipt. Ik beperk me in dat geval tot platforms met een bepaald aantal bits per byte (8 dus waarschijnlijk), of er moet een manier bestaan om dit aantal compile-time te achterhalen.
[...]

Absoluut niet. C++98 is gebaseerd op C94 (=C89+bugfixes), daarna is C geforked en zijn er een aantal uitbreidingen bijgekomen (_Bool, _Complex, embedded spul). Dat wordt C99 genoemd. In C++03 zijn die extra zaken niet meegenomen; ook deze mid-term update is een bugfix release.
Welke compilers ondersteunen (100%) C++03 (just curious)?
En zijn die problemen omtrent stdint.h dan niet van toepassing op (moderne) C++-compilers?
Je hebt het namelijk wel over C99 in relatie tot C++.
En nog iets (wat ik vergeten was te vragen :P): waarom is int8_t niet het meest efficiente 8-bits type?
[...]

De problemen zijn natuurlijk gezien tijdens de ontwikkeling van C99. Alleen,om ze in C99 op te lossen had C99 een heleboel features van C++ moeten terugporten. Dat zou de compilers complexer maken, maar de taal makkelijker. Daarvoor is niet gekozen, en dat heeft te maken met de mensen die nog C compilers maken. Dat zijn meestal kleine bedrijfjes voor embedded systemen. De "grote jongens" in de wereld (Microsoft, Sun, Borland, Gnu) hebben wel de resources om iets als operator overloading te intrduceren (zo'n feature zal al gauw 5.000 euro kosten)
Wederom inhakend op het verband C99/C++: zijn er dan werkelijk features weggehaald uit C99 die men terug zou moeten porten vanuit C++?

Verwijderd

Verwijderd schreef op dinsdag 07 december 2004 @ 16:57:
Dat 2e punt heeft Zoijar idd al aangestipt. Ik beperk me in dat geval tot platforms met een bepaald aantal bits per byte (8 dus waarschijnlijk), of er moet een manier bestaan om dit aantal compile-time te achterhalen.
CHAR_BIT in limits.h cq. climits doet dat toch?

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <climits>
#include <iostream>

#if CHAR_BIT == 8
const char ARCH[] = "PC";
#elif CHAR_BIT == 7
const char ARCH[] = "PDP";
#elif CHAR_BIT == 12
const char ARCH[] = "VAX";
#elif CHAR_BIT == 32
const char ARCH[] = "GSM";
#else
#error "Unknown architecture!"
#endif

int main()
{
    std::cout << ARCH << '\n';
    return 0;
}


(De waardes voor CHAR_BIT zijn uit de duim gezogen.)

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Verwijderd schreef op dinsdag 07 december 2004 @ 11:14:
Even volledig uit context wil ik op deze opmerking inhaken:
Dat weet ik nog niet zeker. Ik weet nog van het assembler proggelen van vrûûger op mijn trouwe 286 (een 16-bits machine met 8-bit woorden), dat je prima de twee 4-bits halven van een 8-bits woord kon adresseren (van registers dan toch, en die manipuleer je toch het meest).

Ik zie dus niet in waarom er op een machine met 16-bits woorden niet zo'n faciliteit zou zijn.

(Maar nogmaals, dit is waarschijnlijk lichtelijk off-topic :))
Omdat een byte een atomisch stukje geheugen is; het kleinste dat je kan adresseren. Voor registers kunnen er andere dingen gelden, maar het voorbeeld dat ik al gaf is de nieuwe 64bit architectuur die geen 8bit delen van registers meer kan aanspreken (AH, AL, etc).

Stel dat je een CDR hebt met 16bit bytes, het kleinste wat je op deze cd dus kunt schrijven zijn 16bits. Als je nu in je programma met 8bit bytes werkt, dan is er geen oplossing als je per byte schrijft naar deze cd.

Ik geef toe dat deze dingen soms wat vergezocht zijn, maar zeker niet ondenkbaar (kijk maar naar de PDP-11 met haar heerlijke 11 bit bytes :P) Dat is dus ook (een van de) de rede(s) dat de taal geen standaard bit grootte types wil introduceren. Het gaat er niet om wat logischerwijs aanwezig zou zijn qua faciliteiten; als het er niet is, dan kan de taal niet draaien op dat platform, ongeacht de compiler...de taal zelf kan er nooit draaien. Dat is niet wenselijk voor een taal standaard.

(voor zover ik weet is/was het idee gewoon dat een 'char' een byte is, een 'int' een machine woord, een 'short' een half woord, en een 'long' een dubbelwoord. Dat werkt iha veel makkelijker, omdat het niet boeit hoeveel bits het dan zijn)

[ Voor 8% gewijzigd door Zoijar op 07-12-2004 17:58 ]


Verwijderd

Vergeten...
Verwijderd schreef op dinsdag 07 december 2004 @ 16:38:
In hoeverre hanteert de compiler dit precies? Of eigenlijk, hanteren de standaard-headerfiles de endianness ook (bijv. bij IO-methodes)? Volgens mij zie ik dat wel goed, als ik vermoed dat dit ook in de headerfiles wordt gehanteerd, toch? Lijkt me iig logisch.
Zoals ik al zei, de compiler hanteert standaard alleen de endianness van de host, anders was er geen noodzaak tot htonl() en consorten.
Hmmm, iets wat me te binnen schoot: kan je geen compiler optie meegeven die bepaalt welke endianness de compiler hanteert bij het compilen van de broncode? Dus los van de systeem-architectuur waar je op werkt? Als je niet te low level gaat (d.m.v. assembly routines bijv.), zou dat toch moet kunnen werken, of zie ik dan iets over het hoofd?
Het is inefficient om in een andere endianness te werken dan die van de hardware, dus converteer je zo vroeg mogelijk naar het host-formaat (met bv. ntohl()), zodat je vervolgens efficient kunt rekenen met die getallen en zo laat mogelijk naar het bestands- netwerkformaat. Om de compiler automatisch te kunnen laten converteren zou je dus moeten kunnen specificeren welke geheugenbereiken big-endian en welke little-endian getallen bevatten, normale C++ compilers kunnen dat niet want dat is geen onderdeel van de taal.

Verwijderd

Topicstarter
Verwijderd schreef op dinsdag 07 december 2004 @ 17:42:
[...]


CHAR_BIT in limits.h cq. climits doet dat toch?

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <climits>
#include <iostream>

#if CHAR_BIT == 8
const char ARCH[] = "PC";
#elif CHAR_BIT == 7
const char ARCH[] = "PDP";
#elif CHAR_BIT == 12
const char ARCH[] = "VAX";
#elif CHAR_BIT == 32
const char ARCH[] = "GSM";
#else
#error "Unknown architecture!"
#endif

int main()
{
    std::cout << ARCH << '\n';
    return 0;
}


(De waardes voor CHAR_BIT zijn uit de duim gezogen.)
Mooi zo, dan is het toch ook mogelijk om een (aanvullende) stdint-headerfile te maken die zich baseert op CHAR_BIT? En voorts ook als opgenomen primitives.

Verwijderd

Topicstarter
Zoijar schreef op dinsdag 07 december 2004 @ 17:53:
[...]

Omdat een byte een atomisch stukje geheugen is; het kleinste dat je kan adresseren. Voor registers kunnen er andere dingen gelden, maar het voorbeeld dat ik al gaf is de nieuwe 64bit architectuur die geen 8bit delen van registers meer kan aanspreken (AH, AL, etc).
Tja, maar dat is een hardware-technische beperking.
Een (betreurenswaardige) keuze van processorfabrikanten, voortgekomen uit kortzichtigheid. Het voorzien in een minder aantal registers levert immers een kleinere 'die size' op, en dus meer kosten en hitte. AMD heeft hier ook op gestudeerd, maar klaarblijkelijk de software-technische aspecten niet echt goed meegenomen...
Stel dat je een CDR hebt met 16bit bytes, het kleinste wat je op deze cd dus kunt schrijven zijn 16bits. Als je nu in je programma met 8bit bytes werkt, dan is er geen oplossing als je per byte schrijft naar deze cd.

Ik geef toe dat deze dingen soms wat vergezocht zijn, maar zeker niet ondenkbaar (kijk maar naar de PDP-11 met haar heerlijke 11 bit bytes :P) Dat is dus ook (een van de) de rede(s) dat de taal geen standaard bit grootte types wil introduceren. Het gaat er niet om wat logischerwijs aanwezig zou zijn qua faciliteiten; als het er niet is, dan kan de taal niet draaien op dat platform, ongeacht de compiler...de taal zelf kan er nooit draaien. Dat is niet wenselijk voor een taal standaard.

(voor zover ik weet is/was het idee gewoon dat een 'char' een byte is, een 'int' een machine woord, een 'short' een half woord, en een 'long' een dubbelwoord. Dat werkt iha veel makkelijker, omdat het niet boeit hoeveel bits het dan zijn)
Maar zoals ik al schreef introduceert het toevoegen van fixed-size int's als primitives geen incompatibiliteit. Wellicht zal het e.e.a. wat ingewikkelder/inefficienter maken als de programmeur per se bepaalde fixed-size int's wil gebruiken op één of ander minder geschikt platform, maar dat is aan hem om te overwegen.

Het idee dat een 'int' een machine woord is gaat bijv. al niet op. Tegenwoordig is deze vaak 32-bits i.p.v. 16-bits. Dus zo wenselijk/gemakkelijk is de huidige situatie niet...

[ Voor 3% gewijzigd door Verwijderd op 07-12-2004 18:45 ]


Verwijderd

Topicstarter
Verwijderd schreef op dinsdag 07 december 2004 @ 18:09:
Vergeten...


[...]


Zoals ik al zei, de compiler hanteert standaard alleen de endianness van de host, anders was er geen noodzaak tot htonl() en consorten.
Dat lijkt me vreemd, want in bijv. de headerfiles die netwerkprotocollen beschrijven kan men toch ook niet lukraak uitgaan van de endianness van de compiler host?
En ik neem aan dat je voorbehoud 'standaard' inhoudt dat dit wel overridden kan worden d.m.v. een compiler optie oid? :)
[...]


Het is inefficient om in een andere endianness te werken dan die van de hardware, dus converteer je zo vroeg mogelijk naar het host-formaat (met bv. ntohl()), zodat je vervolgens efficient kunt rekenen met die getallen en zo laat mogelijk naar het bestands- netwerkformaat. Om de compiler automatisch te kunnen laten converteren zou je dus moeten kunnen specificeren welke geheugenbereiken big-endian en welke little-endian getallen bevatten, normale C++ compilers kunnen dat niet want dat is geen onderdeel van de taal.
Tja, het specificeren van de endianness van afzonderlijke geheugenbereiken is wat dat betreft nog een stapje verder, maar het lijkt me toch vrij basaal om voor de hele adress space van het te compileren programma één bepaalde endianness te hanteren, ongeacht de endianness van het host-systeem van de compiler? Dan kunnen asm statements niet meer (gemakkelijk) geprocessed worden maar dat hoeft ook niet altijd per se, toch?

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Verwijderd schreef op dinsdag 07 december 2004 @ 18:42:
Tja, maar dat is een hardware-technische beperking.
Een (betreurenswaardige) keuze van processorfabrikanten, voortgekomen uit kortzichtigheid. Het voorzien in een minder aantal registers levert immers een kleinere 'die size' op, en dus meer kosten en hitte. AMD heeft hier ook op gestudeerd, maar klaarblijkelijk de software-technische aspecten niet echt goed meegenomen...
Het maakt niet echt uit voor software; want gelukkig zijn er geen fixed bit size types ;) Hoe kan je in een paar zinnen, zo maar, even AMD de grond in boren over hun architectuur ontwerp; ik denk heus wel dat daar een heel team van mensen lang over gedacht heeft...het is vaak niet zo simpel als het lijkt.
Maar zoals ik al schreef introduceert het toevoegen van fixed-size int's als primitives geen incompatibiliteit. Wellicht zal het e.e.a. wat ingewikkelder/inefficienter maken als de programmeur per se bepaalde fixed-size int's wil gebruiken op één of ander minder geschikt platform, maar dat is aan hem om te overwegen.
Nee, dat is dan dus niet aan hem om te overwegen; de taal moet het in dit geval ondersteunen. Bovendien gaf ik toch al genoeg voorbeelden dat het wel incompatibiliteit veroorzaakt.
Het idee dat een 'int' een machine woord is gaat bijv. al niet op. Tegenwoordig is deze vaak 32-bits i.p.v. 16-bits. Dus zo wenselijk/gemakkelijk is de huidige situatie niet...
Een machine woord is geen 16bits perse. Tegenwoordig is een machine woord idd vaak 32bits of 64bits, een machine woord is de adresserings grootte. (kies je definitie...iets van het kleinste getal dat het maximale adres kan bevatten oid) Bovendien is het een gedachte gang, geen regel.

Verwijderd

Verwijderd schreef op dinsdag 07 december 2004 @ 18:42:
[...]
Tja, maar dat is een hardware-technische beperking.
Een (betreurenswaardige) keuze van processorfabrikanten, voortgekomen uit kortzichtigheid.

[...]

maar het lijkt me toch vrij basaal om voor de hele adress space van het te compileren programma één bepaalde endianness te hanteren,
Mischien een beetje offtopic, maar wel interesant. Wat doe je eigenlijk in het dagelijkse leven? Als ik het zo zie heb je veel ideeen over hoe onlogisch engineers zowel taal standaarden als processor architecturen neerzetten.

Mischien is het een idee om zelf eens wat werk in die richting te gaan zoeken? MSalters kan je wat betreft het C++ standaard werk mischien wel wat op weg helpen. Voorts is gcc opensource, en zoals het mantra gaat in de open source wereld: "if you don't agree with something, supply a patch". M.a.w wellicht een goed idee om een patch te schrijven die de endianess nu eens goed regelt met de door jou voorgestelde optie?

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Haha ;) Ik had ook al een soort gelijk stukje ingetyped, maar het toen toch maar weer gewist...

Verwijderd

Topicstarter
Verwijderd schreef op dinsdag 07 december 2004 @ 19:14:
[...]


Mischien een beetje offtopic, maar wel interesant. Wat doe je eigenlijk in het dagelijkse leven? Als ik het zo zie heb je veel ideeen over hoe onlogisch engineers zowel taal standaarden als processor architecturen neerzetten.

Mischien is het een idee om zelf eens wat werk in die richting te gaan zoeken? MSalters kan je wat betreft het C++ standaard werk mischien wel wat op weg helpen. Voorts is gcc opensource, en zoals het mantra gaat in de open source wereld: "if you don't agree with something, supply a patch". M.a.w wellicht een goed idee om een patch te schrijven die de endianess nu eens goed regelt met de door jou voorgestelde optie?
offtopic:
Haha, heb je wederom een topic gevonden om op het prikbord in de gang te laten prijken? :D

De ondertoon in je post is dat ik veel zou klagen maar er zelf niets aan doe (niets aan kan doen, misschien zelfs?). Ach ik heb inderdaad zo mijn opvattingen, maar hoe je het ook wendt of keert: ergens heb ik meestal wel enig punt als ik weer eens een topic open over onlogica in programmeertalen.

Zo nu en dan heb ik ook wel wat discussies gestart bij OSS-projecten, maar de bureaucratische barriere blijft natuurlijk groot. Als ik net als jou eenmaal op kantoor zit, zal ik me wat meer praktisch bezig houden met het aandragen van problemen en oplossingen op programmeergebied. Maar voor die RAW-sockets kwestie gaat zeker nog een patch volgen voor een OSS BSD-variant, eerst even kijken hoe het daar is geregeld, enz. enz...

Ik kom om in de (programmeer-)projectjes dus veel initiatieven blijven steken op mijn HD, wachtende op afronding (hoewel ik weldegelijk ver kom, in de regel). Ik doe niet veel anders als wat veel jongere mensen doen in het dagelijks leven, waarschijnlijk dan wel wat nuttigere bezigheden. ;)


Die endianness-patch zou natuurlijk heel pittig zijn. Daarom stookte ik de discussie ook aan, want wat dat betreft dacht ik dat er nog wel bezwaren zouden worden aangedragen door enkele der experts. Volgens mij kan het ook worden opgelost met custom header files, die niet allerlei #define-constructies hanteren voor het bepalen van de endianness en allerlei condities inbouwen die inspelen op platformafhankelijke zaken. Vandaar ook mijn vraag: is de endianness niet vast in de networking protocols-headerfiles? Van wat ik me herinner (ja, ik ben meer bereid lange uiteenzettingen te typen dan at this very moment headerfiles te gaan bestuderen om mijn indruk te staven), wordt de endianness van het host-systeem bepaald, en omgezet naar de juiste endianness. Eigenlijk niet zo delicaat in de praktijk, aangezien er maar 2 types endianness bestaan.
Maar goed, waar het op neer zou komen in dit geval: alleen de networking protocols-headerfiles vangen systeem-architectuur-afhankelijke uitzonderingscondities af. De andere headerfiles laten zich blind leiden door de endianness van het compiler host systeem.

Okay, ik mis nu vast heel wat in deze perceptie etc., maar ik heb geen tijd om er nu over na te denken, en deze uiteenzetting is dus puur het resultaat van eenvoudige en zwakke lineaire logica. :|

offtopic:
Er schijnt vandaag een storing geweest te zijn bij TrueServer, dit topic wilde ook maar niet laden....
Nu heb ik vandaag te weinig tijd om in te gaan op de voorgaande reacties, gaarne wat geduld.
Morgen meer, C++-liefhebbers. ;)

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Verwijderd schreef op dinsdag 07 december 2004 @ 23:39:
Volgens mij kan het ook worden opgelost met custom header files, die niet allerlei #define-constructies hanteren voor het bepalen van de endianness en allerlei condities inbouwen die inspelen op platformafhankelijke zaken.
Custom headers, maar zonder #define's, en niet inspelen op platformafhankelijke zaken...wat wil je nou? :)
Vandaar ook mijn vraag: is de endianness niet vast in de networking protocols-headerfiles? Van wat ik me herinner (ja, ik ben meer bereid lange uiteenzettingen te typen dan at this very moment headerfiles te gaan bestuderen om mijn indruk te staven), wordt de endianness van het host-systeem bepaald, en omgezet naar de juiste endianness. Eigenlijk niet zo delicaat in de praktijk, aangezien er maar 2 types endianness bestaan.
Het gaat nu toch goed? Je converteert naar een vooraf gedefineerd endian formaat, en vanaf daar weer terug. En beide systemen hebben custom headers/code die dat doen. Ik zie het probleem niet.
Maar goed, waar het op neer zou komen in dit geval: alleen de networking protocols-headerfiles vangen systeem-architectuur-afhankelijke uitzonderingscondities af. De andere headerfiles laten zich blind leiden door de endianness van het compiler host systeem.
Je draait toch maar op 1 systeem tegelijk, dan maakt het toch niks uit? Alleen als je communiceert met een systeem met andere ordening, dan moet je even converteren voor de zekerheid.
Okay, ik mis nu vast heel wat in deze perceptie etc., maar ik heb geen tijd om er nu over na te denken, en deze uiteenzetting is dus puur het resultaat van eenvoudige en zwakke lineaire logica. :|
Misschien moet je voor jezelf eens nadenken hoe je het op zou lossen, en ook eens goed het huidige idee proberen te doorgronden. Want, nofi, je slaat enigszins wartaal uit met de term "headers". Je vraagt hier iets, je krijgt redelijk gedetaileerd antwoord over het hoe en waarom, en dan ben je het er niet mee eens. Je begint dan opnieuw, en haalt weer andere dingen aan en zegt dat de uitgelegde dingen er niet toe doen. Nou, die doen er dus wel toe :)

Verwijderd

Zoijar schreef op dinsdag 07 december 2004 @ 23:51:
Het gaat nu toch goed? Je converteert naar een vooraf gedefineerd endian formaat, en vanaf daar weer terug. En beide systemen hebben custom headers/code die dat doen. Ik zie het probleem niet.
Sterker nog, de voorgestelde patch is op die manier compleet dysfunctioneel, je kunt niet simpelweg een programma schrijven dat geen rekening houdt met endianness en het vervolgens porten naar een andere architectuur door de endianness van alle getalrepresentaties te veranderen. Als dat zou kunnen, zou dat betekenen dat we simpelweg een in "big-endian C" (zonder htonl() ed.) geschreven tcp/ip stack konden nemen en die met de bewuste compilerflag zo voor de (little-endian) i386 architectuur konden compileren, waarbij verwacht wordt dat zaken als crc-codes nog steeds juist berekend worden...

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Verwijderd schreef op dinsdag 07 december 2004 @ 16:57:
[...]

Ja precies, maar waarom (maximaal) unsigned long?
Waarom niet de eerder genoemde long long of __int64 (waarom er onderscheid tussen die 2 is gemaakt vraag ik me nog steeds af...)?
Omdat C++ standaard geen long long of __int64 type heeft.
Het heeft wat weg van wiskunde met een modulo van 256, maar dat zal in dit geval gewoon het max. bereik van de index van een bepaalde array zijn (unsigned dus hé). Ik snap wel dat het ook met een int-type met een grotere bit-grootte zou kunnen, maar waarom zou ik dat willen. Is theoretisch gezien minder efficient. :D
Nee hoor, dat denk je maar. Dat is dus ook de reden dat de C++ commissie zo'n moeite heeft met stdint.h, vanwege dit soort vergissingen. Kleinere types zijn niet altijd efficienter. Als je in HW wel gratis modulo 65536 kunt doen, maar niet gratis modulo 256, dan is een 16 bits type soms efficienter.
Welke compilers ondersteunen (100%) C++03 (just curious)?
En zijn die problemen omtrent stdint.h dan niet van toepassing op (moderne) C++-compilers?
Comeau, vermoed ik, maar dat is vanwege export. Verhaal apart.
Wederom inhakend op het verband C99/C++: zijn er dan werkelijk features weggehaald uit C99 die men terug zou moeten porten vanuit C++?
Niet zozeer weggehaald, C94 is geforked in C++98/C++03 en C99. C++ kreeg echte UDTs, ook voor de library. C99 had dat niet, dus zelfs _Complex is daar een built-in type (geen library).

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Verwijderd schreef op woensdag 08 december 2004 @ 01:20:
[...]
... je kunt niet simpelweg een programma schrijven dat geen rekening houdt met endianness en het vervolgens porten naar een andere architectuur door de endianness van alle getalrepresentaties te veranderen. Als dat zou kunnen, zou dat betekenen dat we simpelweg een in "big-endian C" (zonder htonl() ed.) geschreven tcp/ip stack konden nemen en die met de bewuste compilerflag zo voor de (little-endian) i386 architectuur konden compileren, waarbij verwacht wordt dat zaken als crc-codes nog steeds juist berekend worden...
Kan wel. Is niet efficient. Je introduceert een soort VM, en da's nooit snel. Maar de C standaard probeert niet voor te schrijven hoe snel iets moet zijn.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15-05 06:45
MSalters schreef op woensdag 08 december 2004 @ 18:07:
Omdat C++ standaard geen long long of __int64 type heeft.
Gaat dat trouwens ooit/binnenkort veranderen? Dat is eigenlijk het enige 'probleem' dat ik zeer regelmatig tegenkom (en dan ga ik er gewoon maar vanuit dat 'long long int' een int met 64+ bits is) en ik zou dat veel liever gestandaardiseerd zien dan dingen als exported templates of out-of-class member template partial specializations (ik weet niet eens wat dat is, laat staan dat ik het gebruik).

Verwijderd

MSalters schreef op woensdag 08 december 2004 @ 18:12:
Kan wel. Is niet efficient. Je introduceert een soort VM, en da's nooit snel. Maar de C standaard probeert niet voor te schrijven hoe snel iets moet zijn.
Maar dan doe je dus veel meer dan alleen de endianness van de getalrepresentatie (op een geschikt moment in het programmaverloop) veranderen; je plakt een emulator om een andere CPU/architectuur na te bootsen aan je code zodat er nog correct gerekend kan worden met die in de verkeerde endianness gerepresenteerde getallen.

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Dit dacht ik...

C++:
1
2
3
4
5
6
7
8
class A {
   template <typename T1, typename T2> void foo(const T1&, const T2&) { ...}
   template <typename T2> void foo(const int&, const T2&);
};

// body van A::foo<int, T2> hier, is: out-of-class, member template, partial specialization
// template <typename T2> void A::foo<int, T2>(const int&, const T2&) {...} 
// werkt niet, omdat het template keyword op A:: slaat.

[ Voor 9% gewijzigd door Zoijar op 08-12-2004 18:26 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Soultaker schreef op woensdag 08 december 2004 @ 18:14:
[...]

Gaat dat trouwens ooit/binnenkort veranderen? Dat is eigenlijk het enige 'probleem' dat ik zeer regelmatig tegenkom (en dan ga ik er gewoon maar vanuit dat 'long long int' een int met 64+ bits is) en ik zou dat veel liever gestandaardiseerd zien dan dingen als exported templates of out-of-class member template partial specializations (ik weet niet eens wat dat is, laat staan dat ik het gebruik).
long long is een goede kanshebber. Niet dat we er heel erg blij mee zijn; de grappen over "long long long long" zijn al gemaakt. Alleen is het iets waar we geen incompabilieit met C willen. Eerlijk gezegd had ik zelf nog wel kunnen leven met de observatie dat we pas bij 128-bits CPUs een probleem hebben, want char/short/int/long is genoeg voor 8/16/32/64. Waarom iemand 2 32bits types wil ontgaat me. Sowieso, waarom iemand long kleiner wil houden dan pointers ontgaat me ook al.

[ Voor 4% gewijzigd door MSalters op 08-12-2004 18:37 ]

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

MSalters schreef op woensdag 08 december 2004 @ 18:36:
[...]

long long is een goede kanshebber. Niet dat we er heel erg blij mee zijn; de grappen over "long long long long" zijn al gemaakt. Alleen is het iets waar we geen incompabilieit met C willen. Eerlijk gezegd had ik zelf nog wel kunnen leven met de observatie dat we pas bij 128-bits CPUs een probleem hebben, want char/short/int/long is genoeg voor 8/16/32/64.
Hadden we hier niet een tijdje terug op got al een discussie over? Het valt mij op dat alle recente C++ implementaties voor 64bits platformen die ik het gezien de int niet mee laten groeien naar 64bits maar daarvoor een apart type (nu vendor specific) introduceren. Ten tijde van de overgang van 16- naar 32 bits cpus groeide de int wel van 16 naar 32 bits mee.

Het zou mij logischer lijken als (met inachtename van de gebruikelijke relatieve grootes tussen de types), een int altijd het systeem woord was en een long het grootste type in het systeem, mogelijk groter dan wat direct in hardware gesupport wordt. Op 64 bit systemen zou een long dan mogelijk 128 bits zijn, maar tenminste 64 bits.
Waarom iemand 2 32bits types wil ontgaat me. Sowieso, waarom iemand long kleiner wil houden dan pointers ontgaat me ook al.
Een vreemde zaak.

Je kunt mischien nog onderscheid willen maken tussen architecturen waarbij de databus niet even breed is als de addressbus. Stel dat je een systeem hebt met een 32 bits databus en een 64 bits addressbus. De int zou dan 32 bits kunnen zijn, de pointer 64 bits en de long tenminste 64 bits. Natuurlijk is dit onzin*, want een pointer moet tenminste in een int passen. Ik kan de officiele regel hiervan even niet vinden maar zie bv [rml]flowerp in "[ C++] Pass by reference/pointer/gewoon v..."[/rml]

Bjarne Stroustrup zegt er overigens het volgende over:
[...] the int type is supposed to be chosen to be the most suitable for holding and manipulating integers on a given computer, it is typically a 4-byte (32-bit) word. It is unwise to assume more.
* Toch niet, zie de verklaring van MSalters hieronder

[ Voor 3% gewijzigd door Verwijderd op 09-12-2004 12:42 . Reden: Wat ik schreef bleek helemaal niet waar te zijn. ]


Verwijderd

offtopic:
[quote]Verwijderd schreef op dinsdag 07 december 2004 @ 23:39:
[...]

Haha, heb je wederom een topic gevonden om op het prikbord in de gang te laten prijken? :D
[/quote]

Dat je dat nog herinnert zeg! :D Maar de gangen zijn al aardig vol, de befaamde interface discussie van got, een oude slash-dot discussie over cola en een nogal sterke email wisseling tussen twee collega's (met toestemming van beiden). Het moet natuurlijk geen kermis hal worden ;)

Verwijderd

Topicstarter
Zoijar schreef op dinsdag 07 december 2004 @ 23:51:
[...]

Custom headers, maar zonder #define's, en niet inspelen op platformafhankelijke zaken...wat wil je nou? :)
Het volgende:
Volgens mij kan het ook worden opgelost met custom header files, die niet allerlei #define-constructies hanteren voor het bepalen van de endianness en allerlei condities inbouwen die inspelen op platformafhankelijke zaken.
Dus het staat er weldegelijk duidelijk, en er is nergens tegenspraak hoor...
[...]

Het gaat nu toch goed? Je converteert naar een vooraf gedefineerd endian formaat, en vanaf daar weer terug. En beide systemen hebben custom headers/code die dat doen. Ik zie het probleem niet.
Dan moet ik eerst (compile-time) bepalen welke endianness de systeem-architectuur van het doelplatform heeft. Kortom, dirty hacks en uitzonderingscondities... als dat uberhaupt als mogelijk is.
Natuurlijk is het geen ramp, en ik gebruik deze methode wel voorlopig, maar het is wellicht het overwegen waard om deze kwestie ook eens anders te proberen te benaderen (gericht aan compiler-bouwers/standaard-mensen, niet aan jou direct).
[...]

Je draait toch maar op 1 systeem tegelijk, dan maakt het toch niks uit? Alleen als je communiceert met een systeem met andere ordening, dan moet je even converteren voor de zekerheid.
En bij platformonafhankelijke code die de operaties die ik eerder kenschetste uitvoert, en waarbij een bepaald bestandsformaat betrokken is, is dat laatste nu ook net een vereiste...

Maar wat ik al schreef, het lijkt me efficienter om direct te casten (hoewel strtol(3) voor het geval van die 4 bytes die naar een DWORD omgezet moeten worden ook werkt zie ik, hopelijk redelijk efficient). Maar is er eigenlijk ook een strtol() die een int met een bereik van 0 - 9999 (decimaal) retourneert? Aangezien het getal dus letterlijk een 'string' is in dit ene geval, geen byte-reeks met exacte DWORD-representatie. Gewoon uit interesse, ik snap wel dat het niet per se nodig is om die 28 bits uit te sparen.
[...]

Misschien moet je voor jezelf eens nadenken hoe je het op zou lossen, en ook eens goed het huidige idee proberen te doorgronden. Want, nofi, je slaat enigszins wartaal uit met de term "headers".
Hoe bedoel je? :?
Die headerfiles zijn betrokken bij de discussie door een ander, die wees op de aanwezigheid van stdint.h voor mijn doelen.
Je vraagt hier iets, je krijgt redelijk gedetaileerd antwoord over het hoe en waarom, en dan ben je het er niet mee eens.
Ehm, okay... zo interpreteer jij dat dan, als ik erover doorga wil ik daarmee niet zeggen dat ik denk dat er nog steeds geen 'oplossing' is geboden. De discussie is gewoon nog niet afgelopen, wellicht zijn er diepere redenen/gevolgen aan te wijzen ten aanzien van deze kwestie. Want ik ga er uiteraard niet vanuit dat ik overal wel aan gedacht heb oid. Dus zodoende...
Je begint dan opnieuw, en haalt weer andere dingen aan en zegt dat de uitgelegde dingen er niet toe doen. Nou, die doen er dus wel toe :)
Misverstand, á la 'the Henk story' denk ik. :)

Bij mij is het niet er WEL / NIET toe doen (in hoofdletters om hetgeen dat van toepassing is te kunnen omcirkelen :P), maar of het meer of minder ideaal is. Dus om mijn mening over de status discussie weer te geven zijn zeker 64 bits nodig, i.p.v. 1. ;) :D
De aangedragen oplossingen, in het bijzonder die omtrent stdint.h e.d., vind ik zeer zeker waardevol alleen dat wordt misschien ietwat overschaduwd door mijn karakteristieke reflecterende stijl...

Verwijderd

Topicstarter
Verwijderd schreef op woensdag 08 december 2004 @ 01:20:
[...]


Sterker nog, de voorgestelde patch is op die manier compleet dysfunctioneel, je kunt niet simpelweg een programma schrijven dat geen rekening houdt met endianness en het vervolgens porten naar een andere architectuur door de endianness van alle getalrepresentaties te veranderen. Als dat zou kunnen, zou dat betekenen dat we simpelweg een in "big-endian C" (zonder htonl() ed.) geschreven tcp/ip stack konden nemen en die met de bewuste compilerflag zo voor de (little-endian) i386 architectuur konden compileren, waarbij verwacht wordt dat zaken als crc-codes nog steeds juist berekend worden...
Dat stelde ik al, asm-routines (inclusief checksum-calculaties e.d.) zijn dan idd niet meer zondermeer te gebruiken in code die je wilt compileren. Maar je hebt gelijk, eigenlijk geldt het voor alle bitsgewijzes operatie, shifts e.d. zijn in C/C++ ook mogelijk zonder asm-routines...
Dus wat dat betreft zou het idd niet haalbaar zijn.

Tja, of de compiler 'wrapt' voor het gewenste resultaat van je code, of bezigt soortgelijke trage mechanismes. Of je moet natuurlijk zelf geacht worden er rekening mee te houden. Dat je bijv. zelf je code schrijft en dat de compiler desnoods een fatal compilation error geeft. Zoals "error: endianness cannot be enforced in (...)". Dingen TCP/IP-stacks zullen dan idd niet compileren. Maar ja, het is dan ook een (zelf opgegeven) forcering natuurlijk. :D

Verwijderd

Topicstarter
MSalters schreef op woensdag 08 december 2004 @ 18:07:
[...]

Omdat C++ standaard geen long long of __int64 type heeft.
Hehe, dat is natuurlijk een cirkelredenering van hetzelfde type als het antwoord dat je gaf op mijn vraag waarom een bitset maximaal een DWORD groot kan zijn. :)
Het is (nog) niet opgenomen in een C++-standaard begrijp ik?
Maar er bestaan toch al lang 64-bits systeem-architecturen, worden die dan aan hun lot overgelaten (lees: aan de eigen uitbreidingen van compiler-bouwers overgelaten)?
[...]

Nee hoor, dat denk je maar. Dat is dus ook de reden dat de C++ commissie zo'n moeite heeft met stdint.h, vanwege dit soort vergissingen. Kleinere types zijn niet altijd efficienter. Als je in HW wel gratis modulo 65536 kunt doen, maar niet gratis modulo 256, dan is een 16 bits type soms efficienter.
Dan beland je dus weer bij de vraag waarom dit zou zijn...
Die int laat de C++-compiler toch niet (per se) in een CPU-register plaatsen?
Dat is weer afhankelijk van in hoeverre de compiler optimaliseert.
Maar dan zou het namelijk iig geheugen schelen. Het is dan wel niks, tegenwoordig, maar het blijft een grotere efficiente. Ook vind ik het cleaner om beperkt te worden door de capaciteit van de index-teller i.p.v. het handelen naar de resulaten van boundary-checks op het desbetreffende array.
Als er onverhoopt iets mis mocht gaan krijg je tenminste een integer-overflow, i.p.v. een index-out-of-bounds waar je van schrikt (als je geluk hebt welteverstaan).
[...]

Comeau, vermoed ik, maar dat is vanwege export. Verhaal apart.
Maar wat is je antwoord op die 2e vraag?
[...]

Niet zozeer weggehaald, C94 is geforked in C++98/C++03 en C99. C++ kreeg echte UDTs, ook voor de library. C99 had dat niet, dus zelfs _Complex is daar een built-in type (geen library).
Aha, idd niet 'weggehaald' dus. Bedankt voor de interessante uitleg. :)

Verwijderd

Topicstarter
Verwijderd schreef op woensdag 08 december 2004 @ 18:25:
[...]


Maar dan doe je dus veel meer dan alleen de endianness van de getalrepresentatie (op een geschikt moment in het programmaverloop) veranderen; je plakt een emulator om een andere CPU/architectuur na te bootsen aan je code zodat er nog correct gerekend kan worden met die in de verkeerde endianness gerepresenteerde getallen.
Tja, maar dan is het kiezen tussen twee kwaden. Als je overal in je code (en soms maakt dat uit) rekening moet houden met verschillen in endianness dan word je ook dol....
En dat zal ook niet zo efficient zijn.

Verwijderd

Topicstarter
MSalters schreef op woensdag 08 december 2004 @ 18:36:
[...]

long long is een goede kanshebber. Niet dat we er heel erg blij mee zijn; de grappen over "long long long long" zijn al gemaakt. Alleen is het iets waar we geen incompabilieit met C willen. Eerlijk gezegd had ik zelf nog wel kunnen leven met de observatie dat we pas bij 128-bits CPUs een probleem hebben, want char/short/int/long is genoeg voor 8/16/32/64. Waarom iemand 2 32bits types wil ontgaat me. Sowieso, waarom iemand long kleiner wil houden dan pointers ontgaat me ook al.
Dat zou weer iets zijn waar ik te zijner tijd ongetwijfeld mijn beklag over zou doen.. :D

"long long long" bla bla bla....

De gedachte alleen al. Het is gewoon niet toekomstgericht zo. Waarom zou (_)int64 geen goede kanshebber zijn (niet dat je dat stelt hoor)? Het mag dan wel van MS zijn, die oplossing lijkt me stukken consequenter en duidelijker. En het past mooi bij de wat mij betreft op te nemen fixed-size integer types: intx_t. :) :P
En intx_t_y, uiteraard. :D
Hoewel er in deze thread al een duidelijkere notatiewijze is genoemd.

Maar goed, de exacte naamgeving is niet erg relevant. Maar eigenlijk is heel die opgaaf van data-types (ik heb het niet over de modifiers!) met meerdere keywords in C/C++ geheel te verwachten een bron van problemen. Een correcte naamgeving van de data-types volgens eens of andere logische notatie is toch ook afdoende, zou je zeggen....
Hooguit voor 'signed' en 'unsigned' zou je een extra keyword beschikbaar horen te stellen...

Maar dat is allemaal weer een ander verhaal. :X :P

Verwijderd

Topicstarter
Verwijderd schreef op woensdag 08 december 2004 @ 21:41:
offtopic:
[quote]Verwijderd schreef op dinsdag 07 december 2004 @ 23:39:
[...]

Haha, heb je wederom een topic gevonden om op het prikbord in de gang te laten prijken? :D
[/quote]

Dat je dat nog herinnert zeg! :D Maar de gangen zijn al aardig vol, de befaamde interface discussie van got, een oude slash-dot discussie over cola en een nogal sterke email wisseling tussen twee collega's (met toestemming van beiden). Het moet natuurlijk geen kermis hal worden ;)
Uiteraard herinner ik me dat nog, het is tenslotte nog niet zo lang geleden, en ik was er ietwat ontsteld over. Hopelijk gaan jullie een keer papier inzamelen voor het pensioen van een van je collega's, zoals in die ene reclame. >:)

Verwijderd

Topicstarter
Verwijderd schreef op woensdag 08 december 2004 @ 21:37:
[...]

Bjarne Stroustrup zegt er overigens het volgende over:


[...]
Een beetje zoals die uitspraak van Bill Gates, dat een bepaald aantal kB aan geheugen voor altijd wel genoeg is... :D

Bjarne Stroustrup gaat uit van 32-bits systeem-architecturen, terwijl die over een tijd wellicht eerder uitzondering dan regel zijn.

Verwijderd

Topicstarter
Deze post zag ik nog staan, over het hoofd gezien in de hitte van de discussie. ;)
Zoijar schreef op dinsdag 07 december 2004 @ 19:03:
[...]

Het maakt niet echt uit voor software; want gelukkig zijn er geen fixed bit size types ;)
Berusting in de eigen visie... :P
Hoe kan je in een paar zinnen, zo maar, even AMD de grond in boren over hun architectuur ontwerp; ik denk heus wel dat daar een heel team van mensen lang over gedacht heeft...het is vaak niet zo simpel als het lijkt.
De overwegingen van, in dit geval, AMD zijn even duidelijk als belangrijk...
Natuurlijk wil AMD geen torenhoge kosten en een grote hitteopwekking...
Hoe dan ook levert het weglaten van 'oude' CPU-registers problemen op, jijzelf wierp dit op.
[...]

Nee, dat is dan dus niet aan hem om te overwegen; de taal moet het in dit geval ondersteunen. Bovendien gaf ik toch al genoeg voorbeelden dat het wel incompatibiliteit veroorzaakt.
Uiteraard, het voorbeeld dat ik gaf geldt natuurlijk alleen als die fixed-size int's daadwerkelijk opgenomen zijn.
Voor zover ik weet was het enige valide voorbeeld dat je gaf gebaseerd op (m.i.) onwenselijke en min of meer toevallige hardware-omstandigheden.
[...]

Een machine woord is geen 16bits perse. Tegenwoordig is een machine woord idd vaak 32bits of 64bits, een machine woord is de adresserings grootte. (kies je definitie...iets van het kleinste getal dat het maximale adres kan bevatten oid) Bovendien is het een gedachte gang, geen regel.
Onder 'machine-woord' versta ik een WORD, dus 16-bits. Ik zou het theoretisch(e) adress space of adresbereik noemen, overigens.
Onder 'het idee' versta ik het eigenlijke concept,zoals het in acht genomen diende te worden. Maar ook dat is gewoon verwarring over onze eigen interpretatie. ;)

Verwijderd

Verwijderd schreef op maandag 06 december 2004 @ 19:21:
De bit-grootte van het type 'int' staat niet vast. Verschillende platforms en compilers geven er hun eigen draai aan, zoals bekend.

Nu wil ik echter een vaste bit-grootte van bepalen door middel van de type-definitie van een bepaalde variabele. De (verplichte ;() compiler is Borland C++BuilderX. Deze heeft de volgende limits-header:
Borland C++ Builder X is nou juist een omgeving waar je zo van compiler kan wisselen. Wil je een GCC backend, Intel backend, MS Visual C++ backend, cross platform compileren, allemaal geen probleem. Je kan klagen over de IDE maar de compiler zelf is juist vanuit C++ Builder X min of meer vrij te kiezen. Dat is nou net de reden dat wij deze IDE gebruiken voor Cross Platform werk.

Dat je door Cross Platform programmeren te maken krijgt met het probleem van de definitie van integers, 32 of 64 bits is inderdaad lastig (of kan dat zijn) en dat verschillende compilers ieder hun eigen methode hebben om de fixed size versies van integers te benaderen is niet iets waar veel aan te doen is.

Maar knutselen met compiter directives en eigen typedefs brengt je een heel eind. En is relatief simpel te doen. Als je cross platform programmeert zul je gewoon niet aan dit soort zaken ontkomen. Al was het maar om je programma met een acceptabele snelheid op een X-Scale processor te draaien. :(

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Verwijderd schreef op woensdag 08 december 2004 @ 21:37:
. Natuurlijk is dit onzin, want een pointer moet tenminste in een int passen. Ik kan de officiele regel hiervan even niet vinden maar zie bv [rml]flowerp in "[ C++] Pass by reference/pointer/gewoon v..."[/rml]
Nou nee. Er is geen eis in de standaard die eist dat een pointer in een int past.
Het is misschien verassend, maar Bjarne gaat helemaal niet meer over dat soort details.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Verwijderd schreef op woensdag 08 december 2004 @ 23:20:
[...]
Hehe, dat is natuurlijk een cirkelredenering van hetzelfde type als het antwoord dat je gaf op mijn vraag waarom een bitset maximaal een DWORD groot kan zijn. :)
Het is (nog) niet opgenomen in een C++-standaard begrijp ik?
Maar er bestaan toch al lang 64-bits systeem-architecturen, worden die dan aan hun lot overgelaten (lees: aan de eigen uitbreidingen van compiler-bouwers overgelaten)?
Nee hoor, die hadden altijd de optie om long 64 bits te maken. long long is alleen om C++ compatible te houden met C99. Je moet in het achterhoofd houden dat er een verschil is tussen een specificatie=standaard en een implementatie. De specificatie moet geschreven worden zodat er redelijke implementaties mogelijk zijn; de implementatie moet zoveel mogelijk aan de standaard voldoen. Dat is een wisselwerking die twee kanten opwerkt, maar het zijn wel gescheiden zaken. Die beperking van bitset<32> is gebaseerd op de mogelijkheid van een redelijke implementatie van 32-bits longs op gangbare 16-bits processoren, niet op een bestaande compiler.
Dan beland je dus weer bij de vraag waarom dit zou zijn...
Die int laat de C++-compiler toch niet (per se) in een CPU-register plaatsen?
Nee, het hoeft niet, maar als een compilerbouwer het wil moet het wel kunnen. Daarom is int ook tenminste 16 bits. Tenminste 17 bits zou onredelijk zijn in de praktijk.
Dat is weer afhankelijk van in hoeverre de compiler optimaliseert.
Maar dan zou het namelijk iig geheugen schelen. Het is dan wel niks, tegenwoordig, maar het blijft een grotere efficiente.
Het is maar wat je efficientie noemt. Geheugencapaciteit blijft snel groeien, maar Intel zit te zweten over snelheid. De access van een enkele byte is langzaam op een 32-bits CPU, en sowieso heb jij een goede kans (lees: 95%) dat de compiler 'm toch pad op 32 bits.
Ook vind ik het cleaner om beperkt te worden door de capaciteit van de index-teller i.p.v. het handelen naar de resulaten van boundary-checks op het desbetreffende array.
Als er onverhoopt iets mis mocht gaan krijg je tenminste een integer-overflow, i.p.v. een index-out-of-bounds waar je van schrikt (als je geluk hebt welteverstaan).
Eh? Is dit Java? C++ heeft undefined behavior op integer overflow on index out of bounds. Maar mijn punt was dat een 32-bits processor tijd kwijt is aan het artificeel beperken van de capaciteit. Als je eist dat 255+1=0, dan moet elke optelling intern gevolgd worden door een &0x000000FF operatie. Duur.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Verwijderd schreef op woensdag 08 december 2004 @ 23:43:
De gedachte alleen al. Het is gewoon niet toekomstgericht zo. Waarom zou (_)int64 geen goede kanshebber zijn (niet dat je dat stelt hoor)? Het mag dan wel van MS zijn, die oplossing lijkt me stukken consequenter en duidelijker. En het past mooi bij de wat mij betreft op te nemen fixed-size integer types: intx_t. :) :P
En intx_t_y, uiteraard. :D
Hoewel er in deze thread al een duidelijkere notatiewijze is genoemd.
Het grootste probleem is dat we deze dingen juist niet willen aanmoedigen. Het liefst zouden we de die dingen BILL_GATES_IS_GREAT_int64 noemen op Linux, en OPEN_SOURCE_IS_GREAT_int64 op windows, maar dat helpt de portabiliteit weer niet ;)

Wat je wil is dat mensen aangeven of ze een int willen die (1) precies X bits is, of (2) tenminste X bits, waarbij je nog de keuze hebt uit (2a) kleinste native type met tenminste X bits en (2b) snelste native type met tenminste X bits. (En volgens mij mis ik nog een C99 variant)
Verder zegt C99 niets over overloading. Is int64_t een ander type dan long long? In C++ moet je zeggen of je daarop kunt overloaden.

__int64 is behoorlijk kansloos; leading underscores zijn een hack. _int64 is een legale identifier, en we hebben geen zijn om onnodig dingen te breken (zoals struct _int64 { unsigned long l,h; };)
Dan zou int<64> duidelijker zijn.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

MSalters schreef op donderdag 09 december 2004 @ 10:24:
[...]
Nou nee. Er is geen eis in de standaard die eist dat een pointer in een int past.
Het is misschien verassend, maar Bjarne gaat helemaal niet meer over dat soort details.
Dat verklaart dan waarom ik het zo snel niet kon vinden. Wat ik me dan wel afvraag, waarom is volgens Herb Sutter het gegeven stukje code in de quote van flowerp 'standard conforming'? Hij cast een pointer naar een int en noemt dit legaal. Toch is er geen regel in de standaard die zegt dat een pointer in een int moet passen.

Herb roasted? Of zie ik iets over het hoofd? Mischien dat ie eerder iets bedoelt dat -als- die cast op een bepaald platform legaal is, het dan in elke situatie op dat platform moet werken? (de context van zijn bericht was GC 'pointers', een heel ander verhaal opzich dus).

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Vergissing van Herb. De enige garantie is dat die cast werkt, als de integers groot genoeg zijn. Wat "groot genoeg" is wordt aan de implementatie overgelaten. In win32 zijn dat int en long; in win64 zijn er geen standaard types.
Om te voorkomen dat mensen authoriteiten gaan geloven (Herb of ondergetekende, dat laat ik in het midden ;) ) zal ik maar even 5.2.10 quoten:
4 A pointer can be explicitly converted to any integral type large enough to hold it. The mapping function is implementation-defined. [ Note: it is intended to be unsurprising to those who know the addressing structure of the underlying machine. —end note ]
5 A value of integral type or enumeration type can be explicitly converted to a pointer.65) A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value;

65) Converting an integral constant expression (5.19) with value zero always yields a null pointer (4.10), but converting other expressions that happen to have value zero need not yield a null pointer. mappings between pointers and integers are otherwise implementation-defined.
(bold is nadruk van mij, geen quote)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Zoijar schreef op maandag 06 december 2004 @ 21:49:
Het geheugen zou ook prima over kunnenstappen op 16bit units.
Wat bedoel je daarmee?
In x86 en x86-64 is geheugen sinds de Pentium (volgens mij) al 64 bits breed. Je kunt niet minder benaderen en unaligned access is ook geen optie.
De processor staat dit wel toe maar voert dit onder de motorkap uit als (1 - 4) 64-bit accesses.

[ Voor 13% gewijzigd door Olaf van der Spek op 09-12-2004 16:25 ]


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Zoijar schreef op dinsdag 07 december 2004 @ 17:53:
Omdat een byte een atomisch stukje geheugen is; het kleinste dat je kan adresseren. Voor registers kunnen er andere dingen gelden, maar het voorbeeld dat ik al gaf is de nieuwe 64bit architectuur die geen 8bit delen van registers meer kan aanspreken (AH, AL, etc).
Met 'de' bedoel je AMD64?
Ik dacht dat al juist wel kon (en misschien ah) maar ax niet meer.

Verder vind ik dat het zonder zo'n standaard header met exact, fast and minimal types wel een rotzooi is/wordt, aangezien elke library zijn eigen types gebruikt en je extra infastructuur nodig hebt om die typedefs voor elk platform te leveren.

[ Voor 24% gewijzigd door Olaf van der Spek op 09-12-2004 16:30 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15-05 06:45
Verwijderd schreef op woensdag 08 december 2004 @ 21:37:
Het valt mij op dat alle recente C++ implementaties voor 64bits platformen die ik het gezien de int niet mee laten groeien naar 64bits maar daarvoor een apart type (nu vendor specific) introduceren. [..]

Het zou mij logischer lijken als (met inachtename van de gebruikelijke relatieve grootes tussen de types), een int altijd het systeem woord was en een long het grootste type in het systeem, mogelijk groter dan wat direct in hardware gesupport wordt. Op 64 bit systemen zou een long dan mogelijk 128 bits zijn, maar tenminste 64 bits.
Het verhaal was hierbij dat er veel code in omloop zou zijn die onterecht aannam dat een int een 32-bits waarde was. (Terwijl dat slechts het minimum is, volgens de standaard.) Zelf ben ik een geval tegengekomen van incompatibiliteit (in een PPM-compressielibrary, niet mijn code) en daar gaat het juist fout omdat de programmeur aannam dat een pointerwaarde in een stuk geheugen ter grootte van een int paste (wat op een 32-bits systeem zo is). In dat geval zou het probleem dus juist vermeden zijn als de int wel was meegegroeid.
Verwijderd schreef op woensdag 08 december 2004 @ 21:37:
Het zou mij logischer lijken als (met inachtename van de gebruikelijke relatieve grootes tussen de types), een int altijd het systeem woord was en een long het grootste type in het systeem, mogelijk groter dan wat direct in hardware gesupport wordt. Op 64 bit systemen zou een long dan mogelijk 128 bits zijn, maar tenminste 64 bits.
Ik weet het niet. Als de standaard mij garandeert dat een int tenminste 32 bits heeft, wat heb ik er dan aan dat een int op een bepaald platform 64 of 128 bits heeft? Ik kan geen portable code schrijven die daar gebruik van maakt (omdat de C standaard die lengte niet garandeert) en in platformspecifieke code kan ik ook best __int64 of long long gebruiken.

Zo bezien vind ik het logisch dat een int gewoon zo klein mogelijk is als de standaard toelaat, tenzij dat inefficient is. Een AMD64 CPU kan gewoon prima met 32-bits waarden werken. Een CPU met uitsluitend 64-bits registers moet misschien extra moeite doen om 32-bits werking te garanderen en op zo'n architectuur is het zinnig om in ieder geval int en long (maar misschien ook short) 64 bits groot te maken.

Maar waarom zou je op een AMD64 architectuur in godsnaam een 64 bits int willen hebben? Het neemt alleen maar meer ruimte in als je ze in structures en arrays stopt en het levert je feitelijk geen enkel voordeel op.

[ Voor 1% gewijzigd door Soultaker op 09-12-2004 16:46 . Reden: typo's ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:08

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op donderdag 09 december 2004 @ 16:37:
Het verhaal was hierbij dat er veel code in omloop zou zijn die onterecht aannam dat een int een 32-bits waarde was. (Terwijl dat slechts het minimum is, volgens de standaard.)
Dat is bij long, de int is minimaal 16 bits ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
.oisyn schreef op donderdag 09 december 2004 @ 16:40:
Dat is bij long, de int is minimaal 16 bits ;)
Is dat niet 'recent' 'officieel' veranderd?

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15-05 06:45
MSalters schreef op woensdag 08 december 2004 @ 18:36:
long long is een goede kanshebber. Niet dat we er heel erg blij mee zijn; de grappen over "long long long long" zijn al gemaakt. Alleen is het iets waar we geen incompabilieit met C willen. Eerlijk gezegd had ik zelf nog wel kunnen leven met de observatie dat we pas bij 128-bits CPUs een probleem hebben, want char/short/int/long is genoeg voor 8/16/32/64.
Dat kan dus alleen als de standaard voorschrijft dat long tenminste 64 bits is, en dat is niet zo, en het lijkt me sterk dat er veel bereidheid is dat te veranderen.
Waarom iemand 2 32bits types wil ontgaat me.
Twee types met dezelfde grootte is inderdaad niet nuttig, omdat die types toch al een minimumgrootte specificeren (als ze een vaste grootte zouden hebben, dan was short 16 bits, long 32 bits, en zou je 'int' kunnen zien als een hint van: zie maar wat het efficientste is; maar met de huidige specificatie bepaalt de compiler toch al zelf wat het beste is).
Sowieso, waarom iemand long kleiner wil houden dan pointers ontgaat me ook al.
Zie mijn reactie op henk_DE_man. Verder was het argument bij C geloof ik dat het in sommige vage architecturen lastig is om functie-pointers te bouwen. Die zouden dan (veel) groter kunnen zijn dan 'normale' pointers en het is natuurlijk onacceptabel om int zo groot te maken dat 'ie niet meer efficient is. (Jammer genoeg moet 'void*' wel minimaal zo groot zijn als de grootst mogelijke data of function pointer, maar goed, die gebruik je toch een stuk minder vaak, zeker in C++.)

[ Voor 5% gewijzigd door Soultaker op 09-12-2004 16:44 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15-05 06:45
.oisyn schreef op donderdag 09 december 2004 @ 16:40:
Dat is bij long, de int is minimaal 16 bits ;)
Ah, dat bedoelde ik inderdaad. :)

Maar op de AMD64 is de long dan ook 32 bits (daar ging het eigenlijk om, want anders had je geen long long nodig).

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15-05 06:45
Oh trouwens, als je op een 64-bits machine een portable 64-bits type wil gebruiken, kun je altijd nog size_t {ge,mis}bruiken.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Soultaker schreef op donderdag 09 december 2004 @ 16:43:
(Jammer genoeg moet 'void*' wel minimaal zo groot zijn als de grootst mogelijke data of function pointer, maar goed, die gebruik je toch een stuk minder vaak, zeker in C++.)
Niet dus, en dat is toevallig waarom ik zo op de hoogte ben van de details. Dat stukje van de standaard (5.2.10) leidde tot een Defect Report, die ik heb geprobeerd op te lossen. De conversie void*<->void(*)() was ill-formed, en de klacht was dat een C++ compiler daarom op dlsym een warning moest geven. In C was dit Undefined Behavior, en mocht je gewoon stilletjes de HD formatten. In C++0x wordt dit waarschijnlijk een nieuwe categorie, Conditionally Supported Behavior, wat wil zeggen dat de compiler bouwers de keus krijgen tussen een error, warning of een specificatie in de handleiding. Geen undefined behavior meer, hooguit implementation-defined behavior.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Soultaker schreef op donderdag 09 december 2004 @ 16:48:
Oh trouwens, als je op een 64-bits machine een portable 64-bits type wil gebruiken, kun je altijd nog size_t {ge,mis}bruiken.
Nee, is niet noodzakelijk, zelfs als pointers 64 bits zijn. size_t is gerelateerd aan de grootste objecten. Een klassieke 8086 met large memory model, 20 bits addressing en (dus) 32 bits pointers kan best een 16-bits size_t hebben omdat objecten daar niet groter dan 64K kunnen zijn. Win32 met AWE kan pointers uitbreiden tot 36/64 bits, maar ook dan zou size_t 64 bits blijven.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15-05 06:45
MSalters schreef op donderdag 09 december 2004 @ 17:15:
Niet dus, en dat is toevallig waarom ik zo op de hoogte ben van de details. Dat stukje van de standaard (5.2.10) leidde tot een Defect Report, die ik heb geprobeerd op te lossen. De conversie void*<->void(*)() was ill-formed, en de klacht was dat een C++ compiler daarom op dlsym een warning moest geven. In C was dit Undefined Behavior, en mocht je gewoon stilletjes de HD formatten.
Je hebt gelijk; ik was in de war. Dat probleem speelt dus inderdaad ook in C. Eigenlijk is niet zozeer de programmeertaal stuk, maar dlsym. Die zou dan een union van een object pointer en een function pointer moeten retourneren (ik weet niet zeker of het retourneren van structures/unions voldoende gestandaardiseerd is, maar dat is weer een heel andere discussie).
MSalters schreef op donderdag 09 december 2004 @ 17:20:
Nee, is niet noodzakelijk, zelfs als pointers 64 bits zijn. size_t is gerelateerd aan de grootste objecten. Een klassieke 8086 met large memory model, 20 bits addressing en (dus) 32 bits pointers kan best een 16-bits size_t hebben omdat objecten daar niet groter dan 64K kunnen zijn.
Ah, dan zou ik moeten zeggen dat je 'm kunt gebruiken op platformen die 64 bits objects ondersteunen. Maar daar heb je dan weer zo weinig aan.
Win32 met AWE kan pointers uitbreiden tot 36/64 bits, maar ook dan zou size_t 64 bits blijven.
Uhm, 32 bits bedoel je dan, neem ik aan?

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Net bedacht dat we al lang een type hebben wat aan de eisen voldoet: bitfields.
C++:
1
 struct { int x : 17; }; 

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15-05 06:45
De bitfield is natuurlijk geen type. Ik kan geen array van bitfields bouwen. Wel van zo'n struct, maar die heeft dan weer een ongespecificeerde grootte.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Wat voor gekke gedachten heb jij bij een array van 17-bits integers?

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Een iets ouder artikel:

http://www.opengroup.org/public/tech/aspen/lp64_wp.htm


Hier valt bij op te merken dat Microsoft voor de LLP64 weg is gegaan.
Pagina: 1