|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#26 |
|
Messages: n/a
Hébergeur: |
James Harris wrote:
<snip> > I'm not sure it's a question of learning the meaning of size_t. The > problem was in printing it with printf prior to C99. > > The recommendation seems to be to cast to unsigned long or similar but > surely if size_t is wider than unsigned long In a C90 conforming implementation size_t cannot be wider than unsigned long since the latter is the largest integral type specified by the Standard, and size_t is defined as an unsigned integral type. BTW, is it conforming for a C90 implementation to implement size_t as an unsigned integral type larger than unsigned long? Is there a specific statement in the Standard that forbids this? Won't the "as if" rule rescue such an implementation? > it will fail to print correctly. This is exceedingly unlikely to the point that I don't think you need to worry about it. > In the absence of C99's %z component perhaps the best way > is to print it by a function (which hasn't been mentioned so may be > wrong or impossible....). The Standard defined size_t as an unsigned integral type, but the exact nature of the type is implementation defined. If you know that your implementation conforms to C99 then the specific format specifier %zu is the way to go. Otherwise just cast the size_t value to the largest unsigned integral type that your implementation supports (either unsigned long or unsigned long long) and print it. You can set a small macro similar to the ones in inttypes.h for this purpose, which will expand to the correct (or best) format specifier for each implementation. Like say: #if __STDC_VERSION__ >= 199901L #define PRI_SIZE_T "zu" #else #define PRI_SIZE_T "lu" #endif You could also test for ULLONG_MAX and change "lu" to "llu", though that may be overkill. |
|
|
|
#27 |
|
Messages: n/a
Hébergeur: |
On 27 Jul, 00:33, CBFalconer <cbfalco...@yahoo.com> wrote:
> James Harris wrote: > > pete <pfil...@mindspring.com> wrote: > > ... snip ... > > >> The get_line function is set up so that if you know that you're > >> going to be dealing with a file which has significantly long > >> lines, then you can supply an adequately large original buffer > >> so that no reallocation will be needed. > > > Ebuf_full allows a buffer of arbitrary size to be pre-allocated, > > if preferred. Whether pre-allocated or not increasing the buffer > > by factors allows it to scale. > > Investigate using ggets, written in purely standard C and released > to the public domain. The whole package is available at: > > <http://cbfalconer.home.att.net/download/ggets.zip> > Pete added line reading to the discussion. The code I proposed is NOT specifically for reading lines. It is intended to be used any time a variable length buffer is needed. The buffer contents could be generated in a loop, for example. As I understand it ggets only works when reading lines. I believe the xbuf functions have other benefits: - The user maintains control and can always choose whether to allow the buffer to expand or not based on whatever criteria the programmer wishes - for example, when the current size of the buffer reaches a certain limit. - Related to this, if using the functions to read from an input stream the input can be terminated on any number of specific characters - for example, carriage return, null, line feed, and/or any control character. - The xbuf functions will work with a buffer allocated by the caller which tends to keep the malloc and free functions in the same code and, I hope this makes the programmer more aware of the need to free any buffer space used. - The caller can manipulate the buffer at any time with realloc (along with noting the new length) and the xbuf functions will still work on the same buffer. - More than one buffer can be grown at the same time - for example, if reading two interleaved streams or reading one stream and generating another buffer. - Control is not relinqushed to the called function as it is with ggets. If reading a long line over a slow link I understand that ggets will keep control until the line ends. Multi-threading can address this but is a very heavy handed approach. and lastly, - The names of the functions are intended to make it clear that they are not part of the standard library. (The name ggets looks too much like those in standard libraries for my taste - but that is a personal preference.) If the xbuf functions fail to do any of the above or can be bettered improvements would be welcome. |
|
|
|
#28 |
|
Messages: n/a
Hébergeur: |
On Sun, 27 Jul 2008 12:59:49 +0530, santosh wrote:
> James Harris wrote: > > <snip> > >> I'm not sure it's a question of learning the meaning of size_t. The >> problem was in printing it with printf prior to C99. >> >> The recommendation seems to be to cast to unsigned long or similar but >> surely if size_t is wider than unsigned long > > In a C90 conforming implementation size_t cannot be wider than unsigned > long since the latter is the largest integral type specified by the > Standard, and size_t is defined as an unsigned integral type. > > BTW, is it conforming for a C90 implementation to implement size_t as an > unsigned integral type larger than unsigned long? Is there a specific > statement in the Standard that forbids this? Won't the "as if" rule > rescue such an implementation? No, it won't. Since the C90 standard says that size_t must be a typedef for unsigned char, unsigned short, unsigned int, or unsigned long (the only unsigned integer types), this is a strictly conforming C90 program: #include <stddef.h> #include <limits.h> #define SIZE_MAX ((size_t) -1) int main(void) { return SIZE_MAX != UCHAR_MAX && SIZE_MAX != USHRT_MAX && SIZE_MAX != UINT_MAX && SIZE_MAX != ULONG_MAX; } It must return 0. If the implementation makes size_t larger than unsigned long, the program returns 1. Returning 1 where the standard requires 0 is not allowed by the as-if rule :-) There are plenty of more convincing correct C90 programs that would be broken by such an implementation, but converting size_t to unsigned long and expecting no change in value is one such example, and you weren't convinced by that. Could you explain why in a bit more detail? |
|
|
|
#29 |
|
Messages: n/a
Hébergeur: |
Harald van D?k wrote:
> On Sun, 27 Jul 2008 12:59:49 +0530, santosh wrote: >> James Harris wrote: >> >> <snip> >> >>> I'm not sure it's a question of learning the meaning of size_t. The >>> problem was in printing it with printf prior to C99. >>> >>> The recommendation seems to be to cast to unsigned long or similar >>> but surely if size_t is wider than unsigned long >> >> In a C90 conforming implementation size_t cannot be wider than >> unsigned long since the latter is the largest integral type specified >> by the Standard, and size_t is defined as an unsigned integral type. >> >> BTW, is it conforming for a C90 implementation to implement size_t as >> an unsigned integral type larger than unsigned long? Is there a >> specific statement in the Standard that forbids this? Won't the "as >> if" rule rescue such an implementation? > > No, it won't. Since the C90 standard says that size_t must be a > typedef for unsigned char, unsigned short, unsigned int, or unsigned > long (the only unsigned integer types), this is a strictly conforming > C90 program: Okay. I do not have access to the C90 standard and I seem to have misunderstood. I was under the impression that size_t was defined as "an unsigned integer type" in C90, like it is in C99. So C90 strictly restricts size_t to be an alias for one of unsigned char/short/int/long. > #include <stddef.h> > #include <limits.h> > #define SIZE_MAX ((size_t) -1) > int main(void) { > return SIZE_MAX != UCHAR_MAX > && SIZE_MAX != USHRT_MAX > && SIZE_MAX != UINT_MAX > && SIZE_MAX != ULONG_MAX; > } > > It must return 0. If the implementation makes size_t larger than > unsigned long, the program returns 1. Returning 1 where the standard > requires 0 is not allowed by the as-if rule :-) > > There are plenty of more convincing correct C90 programs that would be > broken by such an implementation, but converting size_t to unsigned > long and expecting no change in value is one such example, and you > weren't convinced by that. Could you explain why in a bit more detail? I think my real question was whether C90 requires size_t to be a typedef for the "fundamental" unsigned integer types that it defines, or whether it would be conforming for an implementation to define size_t as /an/ unsigned integer type, but distinct from unsigned char/short/int/long. But your program above has answered that question. So I suppose it's impossible to write a fully conforming C90 program under 64 bit Windows that calls a Windows API function. |
|
|
|
#30 |
|
Messages: n/a
Hébergeur: |
On Sun, 27 Jul 2008 15:02:40 +0530, santosh wrote:
> Harald van D?k wrote: >> On Sun, 27 Jul 2008 12:59:49 +0530, santosh wrote: >>> James Harris wrote: >>> >>> <snip> >>> >>>> I'm not sure it's a question of learning the meaning of size_t. The >>>> problem was in printing it with printf prior to C99. >>>> >>>> The recommendation seems to be to cast to unsigned long or similar >>>> but surely if size_t is wider than unsigned long >>> >>> In a C90 conforming implementation size_t cannot be wider than >>> unsigned long since the latter is the largest integral type specified >>> by the Standard, and size_t is defined as an unsigned integral type. >>> >>> BTW, is it conforming for a C90 implementation to implement size_t as >>> an unsigned integral type larger than unsigned long? Is there a >>> specific statement in the Standard that forbids this? Won't the "as >>> if" rule rescue such an implementation? >> >> No, it won't. Since the C90 standard says that size_t must be a typedef >> for unsigned char, unsigned short, unsigned int, or unsigned long (the >> only unsigned integer types), this is a strictly conforming C90 >> program: > > Okay. I do not have access to the C90 standard and I seem to have > misunderstood. I was under the impression that size_t was defined as "an > unsigned integer type" in C90, like it is in C99. It is. However, ... > So C90 strictly > restricts size_t to be an alias for one of unsigned char/short/int/long. ....C90 does not consider any type other than those four an unsigned integer type. C90's "unsigned integer type" is what C99 calls a "standard unsigned integer type", and C90 does not recognise what C99 calls "extended integer types". If the implementation supports some type that behaves exactly as an integer type would, and is represented exactly the same way, it still cannot be an integer type according to the C90's definition. |
|
|
|
#31 |
|
Messages: n/a
Hébergeur: |
Harald van D?k wrote:
> On Sun, 27 Jul 2008 15:02:40 +0530, santosh wrote: >> Harald van D?k wrote: >>> On Sun, 27 Jul 2008 12:59:49 +0530, santosh wrote: >>>> James Harris wrote: >>>> >>>> <snip> >>>> >>>>> I'm not sure it's a question of learning the meaning of size_t. >>>>> The problem was in printing it with printf prior to C99. >>>>> >>>>> The recommendation seems to be to cast to unsigned long or similar >>>>> but surely if size_t is wider than unsigned long >>>> >>>> In a C90 conforming implementation size_t cannot be wider than >>>> unsigned long since the latter is the largest integral type >>>> specified by the Standard, and size_t is defined as an unsigned >>>> integral type. >>>> >>>> BTW, is it conforming for a C90 implementation to implement size_t >>>> as an unsigned integral type larger than unsigned long? Is there a >>>> specific statement in the Standard that forbids this? Won't the "as >>>> if" rule rescue such an implementation? >>> >>> No, it won't. Since the C90 standard says that size_t must be a >>> typedef for unsigned char, unsigned short, unsigned int, or unsigned >>> long (the only unsigned integer types), this is a strictly >>> conforming C90 program: >> >> Okay. I do not have access to the C90 standard and I seem to have >> misunderstood. I was under the impression that size_t was defined as >> "an unsigned integer type" in C90, like it is in C99. > > It is. However, ... > >> So C90 strictly >> restricts size_t to be an alias for one of unsigned >> char/short/int/long. > > ...C90 does not consider any type other than those four an unsigned > integer type. C90's "unsigned integer type" is what C99 calls a > "standard unsigned integer type", and C90 does not recognise what C99 > calls "extended integer types". If the implementation supports some > type that behaves exactly as an integer type would, and is represented > exactly the same way, it still cannot be an integer type according to > the C90's definition. Hmm, seems pretty restrictive to me. Glad that that was rectified with C99. I suppose this same restriction would make ptrdiff_t potentially unusable with objects greater than LONG_MAX bytes, though of course, objects of that size aren't guaranteed in the first place? Wouldn't an unsigned ptrdiff_t have been more suitable than a signed one? |
|
|
|
#32 |
|
Messages: n/a
Hébergeur: |
On Sun, 27 Jul 2008 18:09:03 +0530, santosh wrote:
> Harald van D?k wrote: >> On Sun, 27 Jul 2008 15:02:40 +0530, santosh wrote: >>> Okay. I do not have access to the C90 standard and I seem to have >>> misunderstood. I was under the impression that size_t was defined as >>> "an unsigned integer type" in C90, like it is in C99. >> >> It is. However, ... >> >>> So C90 strictly >>> restricts size_t to be an alias for one of unsigned >>> char/short/int/long. >> >> ...C90 does not consider any type other than those four an unsigned >> integer type. C90's "unsigned integer type" is what C99 calls a >> "standard unsigned integer type", and C90 does not recognise what C99 >> calls "extended integer types". If the implementation supports some >> type that behaves exactly as an integer type would, and is represented >> exactly the same way, it still cannot be an integer type according to >> the C90's definition. > > Hmm, seems pretty restrictive to me. Glad that that was rectified with > C99. I suppose this same restriction would make ptrdiff_t potentially > unusable with objects greater than LONG_MAX bytes, Indeed. But there's no guarantee that ptrdiff_t is large enough to hold the largest difference between two pointers anyway. > though of course, > objects of that size aren't guaranteed in the first place? True, but (assuming size_t is wide enough) there's nothing stopping you from passing a large value to malloc, and only using an object of that size if malloc succeeds. > Wouldn't an > unsigned ptrdiff_t have been more suitable than a signed one? (p - 1) - p should evaluate to -1. This is not possible if ptrdiff_t were unsigned. |
|
|
|
#33 |
|
Messages: n/a
Hébergeur: |
santosh wrote:
> Harald van D?k wrote: > >> On Sun, 27 Jul 2008 15:02:40 +0530, santosh wrote: >>> Harald van D?k wrote: >>>> On Sun, 27 Jul 2008 12:59:49 +0530, santosh wrote: >>>>> James Harris wrote: >>>>> >>>>> <snip> >>>>> >>>>>> I'm not sure it's a question of learning the meaning of size_t. >>>>>> The problem was in printing it with printf prior to C99. >>>>>> >>>>>> The recommendation seems to be to cast to unsigned long or similar >>>>>> but surely if size_t is wider than unsigned long >>>>> In a C90 conforming implementation size_t cannot be wider than >>>>> unsigned long since the latter is the largest integral type >>>>> specified by the Standard, and size_t is defined as an unsigned >>>>> integral type. >>>>> >>>>> BTW, is it conforming for a C90 implementation to implement size_t >>>>> as an unsigned integral type larger than unsigned long? Is there a >>>>> specific statement in the Standard that forbids this? Won't the "as >>>>> if" rule rescue such an implementation? >>>> No, it won't. Since the C90 standard says that size_t must be a >>>> typedef for unsigned char, unsigned short, unsigned int, or unsigned >>>> long (the only unsigned integer types), this is a strictly >>>> conforming C90 program: >>> Okay. I do not have access to the C90 standard and I seem to have >>> misunderstood. I was under the impression that size_t was defined as >>> "an unsigned integer type" in C90, like it is in C99. >> It is. However, ... >> >>> So C90 strictly >>> restricts size_t to be an alias for one of unsigned >>> char/short/int/long. >> ...C90 does not consider any type other than those four an unsigned >> integer type. C90's "unsigned integer type" is what C99 calls a >> "standard unsigned integer type", and C90 does not recognise what C99 >> calls "extended integer types". If the implementation supports some >> type that behaves exactly as an integer type would, and is represented >> exactly the same way, it still cannot be an integer type according to >> the C90's definition. > > Hmm, seems pretty restrictive to me. Glad that that was rectified with > C99. I suppose this same restriction would make ptrdiff_t potentially > unusable with objects greater than LONG_MAX bytes, though of course, > objects of that size aren't guaranteed in the first place? ptrdiff_t doesn't have that problem with programs that don't exceed any of the guaranteed minimum environmental limits. N869 7.18.3 Limits of other integer types [#2] -- limits of ptrdiff_t PTRDIFF_MIN -65535 PTRDIFF_MAX +65535 -- limit of size_t SIZE_MAX 65535 But, the size of an object doesn't have to exceed LONG_MAX bytes to have that problem. It only has to exceed 65535 bytes. N869 6.5.6 Additive operators [#9] When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header. If the result is not representable in an object of that type, the behavior is undefined. > Wouldn't an > unsigned ptrdiff_t have been more suitable than a signed one? The POSIX solution, is a signed size_t. http://bytes.com/forum/thread458286.html -- pete |
|
|
|
#34 |
|
Messages: n/a
Hébergeur: |
"James Harris" <james.harris.1@googlemail.com> wrote in message
news:d0f617e1-dedd-4de8-8bc4-1fd242b58846@79g2000hsk.googlegroups.com... [...] > Here's a rewrite where I've improved the code slightly by simplifying > a few bits of it. It now uses offsets rather than lengths and bases > the increase on the requested offset so eliminating some of the > checks. It does require the factor to be greater than or equal to 1. > I'll include the functions and a sample main in one go. [...] Three small nit-picks in the test code: > int main(void) { > char *buf1 = NULL; > size_t buf1_limit = 0; > size_t offset; > > for (offset = 0; offset < 1000; offset += 200) { > fprintf(stderr, "\n---Checking for offset %d\n", offset); > > if (offset >= buf1_limit && ebuf_full(&buf1, &buf1_limit, offset)) > { ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ If `buf1' is not NULL, and `ebuf_full' returns 1, AFAICT, your leaking memory here. > fprintf(stderr, "-Ebuf overflow %d/%d bytes", buf1_limit, > offset); > exit(1); > } > buf1[offset] = 'x'; > } > > fprintf(stderr, "\n---Trim from %d to %d\n", buf1_limit, offset); > if (ebuf_trim(&buf1, &buf1_limit, offset)) { ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ If `buf1' is not NULL, and `ebuf_trim' returns 1, your leaking memory here as well... > fprintf(stderr, "-Buffer trim to %d failure\n", offset); > exit(1); > } > > free(buf1); > return 0; > } Also, for printing `size_t', its probably "better" to use something like: printf("sizeof(void*) == %lu\n", (unsigned long)sizeof(void*)); [...] |
|
|
|
#35 |
|
Messages: n/a
Hébergeur: |
blargg wrote:
> .... snip ... > > Does the Windows API prevent a C90 compiler on 64-bit windows from > making unsigned long 64 bits wide? If long must be 32 bits, could > such a compile at least make 2^32-1 the maximum object size, so > that the 32-bit unsigned long would be sufficient to hold the size > of any object? No, the minimum size of a long is 32 bits. Emphasize, minimum. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section. |
|
|
|
#36 |
|
Messages: n/a
Hébergeur: |
On Mon, 28 Jul 2008 15:19:37 -0400, CBFalconer wrote:
> blargg wrote: >> Does the Windows API prevent a C90 compiler on 64-bit windows from >> making unsigned long 64 bits wide? > > No, the minimum size of a long is 32 bits. Emphasize, minimum. The C standard allows long to hold more than 32 bits, but that doesn't mean the Windows API does. It's similar to how you shouldn't expect an implementation that makes system(NULL) returns 0 to conform to POSIX, even though any POSIX-conforming implementation is also an conforming C implementation. |
|
|
|
#37 |
|
Messages: n/a
Hébergeur: |
blargg wrote:
> In article <g6hfc4$jre$1@registered.motzarella.org>, santosh > <santosh.k83@gmail.com> wrote: >> ... >> I think my real question was whether C90 requires size_t to be a >> typedef for the "fundamental" unsigned integer types that it defines, >> or whether it would be conforming for an implementation to define >> size_t as /an/ unsigned integer type, but distinct from unsigned >> char/short/int/long. But your program above has answered that >> question. >> >> So I suppose it's impossible to write a fully conforming C90 program >> under 64 bit Windows that calls a Windows API function. > > Does the Windows API prevent a C90 compiler on 64-bit windows from > making unsigned long 64 bits wide? IIRC long is constrained to be 32 bits for code which interfaces with the Windows API. > If long must be 32 bits, could such > a compile at least make 2^32-1 the maximum object size, so that the > 32-bit unsigned long would be sufficient to hold the size of any > object? It could do so, but then you are giving up one advantage of using a larger address-space computer. Honestly, I don't know much about 64 bit Windows, so I expect that I'm either wrong in what I said above or that there are system specific workarounds. Please don't take my word for this but ask in a group like <news:comp.os.ms-windows.programmer.win32> or a suitable group under the <news:microsoft.public> category. |
|
|
|
#38 |
|
Messages: n/a
Hébergeur: |
pete wrote:
> santosh wrote: >> Harald van D?k wrote: >> >>> On Sun, 27 Jul 2008 15:02:40 +0530, santosh wrote: >>>> Harald van D?k wrote: >>>>> On Sun, 27 Jul 2008 12:59:49 +0530, santosh wrote: >>>>>> James Harris wrote: >>>>>> >>>>>> <snip> >>>>>> >>>>>>> I'm not sure it's a question of learning the meaning of size_t. >>>>>>> The problem was in printing it with printf prior to C99. >>>>>>> >>>>>>> The recommendation seems to be to cast to unsigned long or >>>>>>> similar but surely if size_t is wider than unsigned long >>>>>> In a C90 conforming implementation size_t cannot be wider than >>>>>> unsigned long since the latter is the largest integral type >>>>>> specified by the Standard, and size_t is defined as an unsigned >>>>>> integral type. >>>>>> >>>>>> BTW, is it conforming for a C90 implementation to implement >>>>>> size_t as an unsigned integral type larger than unsigned long? Is >>>>>> there a specific statement in the Standard that forbids this? >>>>>> Won't the "as if" rule rescue such an implementation? >>>>> No, it won't. Since the C90 standard says that size_t must be a >>>>> typedef for unsigned char, unsigned short, unsigned int, or >>>>> unsigned long (the only unsigned integer types), this is a >>>>> strictly conforming C90 program: >>>> Okay. I do not have access to the C90 standard and I seem to have >>>> misunderstood. I was under the impression that size_t was defined >>>> as "an unsigned integer type" in C90, like it is in C99. >>> It is. However, ... >>> >>>> So C90 strictly >>>> restricts size_t to be an alias for one of unsigned >>>> char/short/int/long. >>> ...C90 does not consider any type other than those four an unsigned >>> integer type. C90's "unsigned integer type" is what C99 calls a >>> "standard unsigned integer type", and C90 does not recognise what >>> C99 calls "extended integer types". If the implementation supports >>> some type that behaves exactly as an integer type would, and is >>> represented exactly the same way, it still cannot be an integer type >>> according to the C90's definition. >> >> Hmm, seems pretty restrictive to me. Glad that that was rectified >> with C99. I suppose this same restriction would make ptrdiff_t >> potentially unusable with objects greater than LONG_MAX bytes, though >> of course, objects of that size aren't guaranteed in the first place? > > ptrdiff_t doesn't have that problem with programs that > don't exceed any of the guaranteed minimum environmental limits. > > N869 > 7.18.3 Limits of other integer types > [#2] > -- limits of ptrdiff_t > PTRDIFF_MIN -65535 > PTRDIFF_MAX +65535 > -- limit of size_t > SIZE_MAX 65535 > > But, the size of an object doesn't have to exceed LONG_MAX bytes > to have that problem. It only has to exceed 65535 bytes. So it is. Thanks for that correction. <snip> > The POSIX solution, is a signed size_t. > http://bytes.com/forum/thread458286.html I wonder why ISO C decided not to adopt it? After all, size_t is specifically meant for counting the bytes of an object, and presumably, would be suitable for holding pointer offset values too. |
|
![]() |
| Outils de la discussion | |
|
|