Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #168591 > unrolled thread

string to size_t

Started byOğuz <oguzismailuysal@gmail.com>
First post2022-12-19 14:15 +0300
Last post2022-12-19 22:16 +0000
Articles 12 — 7 participants

Back to article view | Back to comp.lang.c


Contents

  string to size_t Oğuz <oguzismailuysal@gmail.com> - 2022-12-19 14:15 +0300
    Re: string to size_t Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-12-19 09:59 -0800
      Re: string to size_t Oğuz <oguzismailuysal@gmail.com> - 2022-12-19 21:34 +0300
        Re: string to size_t Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-12-19 10:49 -0800
          Re: string to size_t Richard Damon <Richard@Damon-Family.org> - 2022-12-19 14:29 -0500
            Re: string to size_t Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-12-19 12:05 -0800
      Re: string to size_t scott@slp53.sl.home (Scott Lurndal) - 2022-12-19 18:40 +0000
        Re: string to size_t Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-12-19 12:07 -0800
          Re: string to size_t scott@slp53.sl.home (Scott Lurndal) - 2022-12-19 20:31 +0000
        Re: string to size_t Tony Oliver <guinness.tony@gmail.com> - 2022-12-19 16:33 -0800
      Re: string to size_t Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-12-19 11:20 -0800
    Re: string to size_t Ben Bacarisse <ben.usenet@bsb.me.uk> - 2022-12-19 22:16 +0000

#168591 — string to size_t

FromOğuz <oguzismailuysal@gmail.com>
Date2022-12-19 14:15 +0300
Subjectstring to size_t
Message-ID<tnph4t$8ind$1@dont-email.me>
I wrote the function below for converting a string to size_t without 
manually calculating its value digit by digit. It first converts the 
string to intmax_t, and if the conversion fails due to a range error and 
SIZE_MAX doesn't fit into an intmax_t, it tries again with uintmax_t. In 
both cases, if the result is less than zero it fails. And on success it 
populates *result with the result.

It works on my machine and a couple others I tried, but I'm not sure if 
it's good C, or a good idea at all. What do you think about it?

int
strtosize(const char *nptr, char **endptr, int base, size_t *result) {
	intmax_t s;
	uintmax_t u;

	errno = 0;
	s = strtoimax(nptr, endptr, base);

	if (errno == 0 && s >= 0 && s <= SIZE_MAX) {
		*result = s;
		return 1;
	}

#if SIZE_MAX > INTMAX_MAX
	if (errno == ERANGE && s == INTMAX_MAX) {
		errno = 0;
		u = strtoumax(nptr, endptr, base);

		if (errno == 0 && u <= SIZE_MAX) {
			*result = u;
			return 1;
		}
	}
#endif

	if (errno == 0)
		errno = ERANGE;

	return 0;
}

[toc] | [next] | [standalone]


#168593

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2022-12-19 09:59 -0800
Message-ID<87r0wvs291.fsf@nosuchdomain.example.com>
In reply to#168591
Oğuz <oguzismailuysal@gmail.com> writes:
> I wrote the function below for converting a string to size_t without
> manually calculating its value digit by digit. It first converts the 
> string to intmax_t, and if the conversion fails due to a range error
> and SIZE_MAX doesn't fit into an intmax_t, it tries again with
> uintmax_t. In both cases, if the result is less than zero it
> fails. And on success it populates *result with the result.
>
> It works on my machine and a couple others I tried, but I'm not sure
> if it's good C, or a good idea at all. What do you think about it?
>
> int
> strtosize(const char *nptr, char **endptr, int base, size_t *result) {
> 	intmax_t s;
> 	uintmax_t u;
>
> 	errno = 0;
> 	s = strtoimax(nptr, endptr, base);
>
> 	if (errno == 0 && s >= 0 && s <= SIZE_MAX) {
> 		*result = s;
> 		return 1;
> 	}
>
> #if SIZE_MAX > INTMAX_MAX
> 	if (errno == ERANGE && s == INTMAX_MAX) {
> 		errno = 0;
> 		u = strtoumax(nptr, endptr, base);
>
> 		if (errno == 0 && u <= SIZE_MAX) {
> 			*result = u;
> 			return 1;
> 		}
> 	}
> #endif
>
> 	if (errno == 0)
> 		errno = ERANGE;
>
> 	return 0;
> }

What is the point of trying strotoimax before using strotoumax?
Just call strtotumax and convert the result to size_t.

The checks are probably unnecessary.  As of the current C standard,
SIZE_MAX cannot be bigger than UINT_MAX.  (C23 will allow for
the possibility that SIZE_MAX > UINT_MAX, but implementations are
unlikely to take advantage of that -- which means your checking
code will at best be difficult to test.)

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#168594

FromOğuz <oguzismailuysal@gmail.com>
Date2022-12-19 21:34 +0300
Message-ID<tnqars$dk10$1@dont-email.me>
In reply to#168593
On 12/19/22 8:59 PM, Keith Thompson wrote:
> What is the point of trying strotoimax before using strotoumax?
To see if the string represents a negative value and fail; can't do that 
with strtoumax alone (or I don't know how to). For example, if I call 
strtoumax("-40", NULL, 10), it returns 18446744073709551576 (UINTMAX_MAX 
- 39) on my computer and leaves errno unchanged. I don't want that, 
perhaps it wasn't clear in OP.

> The checks are probably unnecessary.  As of the current C standard,
> SIZE_MAX cannot be bigger than UINT_MAX.
I didn't know this. Not sure how much adoption the current C standard 
found but it's definitely a step forward for the language. Good.

[toc] | [prev] | [next] | [standalone]


#168596

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2022-12-19 10:49 -0800
Message-ID<87a63jrzxs.fsf@nosuchdomain.example.com>
In reply to#168594
Oğuz <oguzismailuysal@gmail.com> writes:
> On 12/19/22 8:59 PM, Keith Thompson wrote:
>> What is the point of trying strotoimax before using strotoumax?
> To see if the string represents a negative value and fail; can't do
> that with strtoumax alone (or I don't know how to). For example, if I
> call strtoumax("-40", NULL, 10), it returns 18446744073709551576
> (UINTMAX_MAX - 39) on my computer and leaves errno unchanged. I don't
> want that, perhaps it wasn't clear in OP.

Ah, I didn't think of that.  (IMHO that's an unfortunate and
counterintuitive feature.)

You could check for a '-' character following zero or more whitespace
characters.

>> The checks are probably unnecessary.  As of the current C standard,
>> SIZE_MAX cannot be bigger than UINT_MAX.
> I didn't know this. Not sure how much adoption the current C standard
> found but it's definitely a step forward for the language. Good.

uintmax_t and UINT_MAX were introduced in C99.  If an implementation
supports [u]intmax_t at all, it will follow the requirement that
they are the widest supported [un]signed integer types.  (I don't
know of any current implementations that don't support <stdint.h>.)

It turned out that increasing the width of [u]intmax_t as longer
integer types are introduced (typically 128 bits) caused problems
with ABIs.  Adding a 128-bit integer type can be done without
breaking existing code, but changing the size of [u]intmax_t due to
that addition would break the interface been programs and library
codes, since there are standard library functions that take arguments
of those types.  I personally would be much happier if we could
maintain the guarantee that [u]intmax_t are the widest [un]signed
integer types, but apparently there's no consistent way to do that.

C23 will allow an implementation, for example, to provide 64-bit long long
and 128-bit *extended integer types*, but (optionally) keep [u]intmax_t
at 64 bits.

https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3054.pdf
7.22.1.5

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#168598

FromRichard Damon <Richard@Damon-Family.org>
Date2022-12-19 14:29 -0500
Message-ID<sY2oL.15402$5S78.11300@fx48.iad>
In reply to#168596
On 12/19/22 1:49 PM, Keith Thompson wrote:
> Oğuz <oguzismailuysal@gmail.com> writes:
>> On 12/19/22 8:59 PM, Keith Thompson wrote:
>>> What is the point of trying strotoimax before using strotoumax?
>> To see if the string represents a negative value and fail; can't do
>> that with strtoumax alone (or I don't know how to). For example, if I
>> call strtoumax("-40", NULL, 10), it returns 18446744073709551576
>> (UINTMAX_MAX - 39) on my computer and leaves errno unchanged. I don't
>> want that, perhaps it wasn't clear in OP.
> 
> Ah, I didn't think of that.  (IMHO that's an unfortunate and
> counterintuitive feature.)
> 
> You could check for a '-' character following zero or more whitespace
> characters.
> 
>>> The checks are probably unnecessary.  As of the current C standard,
>>> SIZE_MAX cannot be bigger than UINT_MAX.
>> I didn't know this. Not sure how much adoption the current C standard
>> found but it's definitely a step forward for the language. Good.
> 
> uintmax_t and UINT_MAX were introduced in C99.  If an implementation
> supports [u]intmax_t at all, it will follow the requirement that
> they are the widest supported [un]signed integer types.  (I don't
> know of any current implementations that don't support <stdint.h>.)
> 
> It turned out that increasing the width of [u]intmax_t as longer
> integer types are introduced (typically 128 bits) caused problems
> with ABIs.  Adding a 128-bit integer type can be done without
> breaking existing code, but changing the size of [u]intmax_t due to
> that addition would break the interface been programs and library
> codes, since there are standard library functions that take arguments
> of those types.  I personally would be much happier if we could
> maintain the guarantee that [u]intmax_t are the widest [un]signed
> integer types, but apparently there's no consistent way to do that.
> 
> C23 will allow an implementation, for example, to provide 64-bit long long
> and 128-bit *extended integer types*, but (optionally) keep [u]intmax_t
> at 64 bits.
> 
> https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3054.pdf
> 7.22.1.5
> 

I think you mean UINTMAX_MAX, not UINT_MAX.

UINT_MAX is the limit for unsigned int, which on many 64 bits systems is 
only 32 bits big, and will be smaller that SIZE_MAX.

[toc] | [prev] | [next] | [standalone]


#168599

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2022-12-19 12:05 -0800
Message-ID<875ye7rwfp.fsf@nosuchdomain.example.com>
In reply to#168598
Richard Damon <Richard@Damon-Family.org> writes:
> On 12/19/22 1:49 PM, Keith Thompson wrote:
>> Oğuz <oguzismailuysal@gmail.com> writes:
>>> On 12/19/22 8:59 PM, Keith Thompson wrote:
>>>> What is the point of trying strotoimax before using strotoumax?
>>> To see if the string represents a negative value and fail; can't do
>>> that with strtoumax alone (or I don't know how to). For example, if I
>>> call strtoumax("-40", NULL, 10), it returns 18446744073709551576
>>> (UINTMAX_MAX - 39) on my computer and leaves errno unchanged. I don't
>>> want that, perhaps it wasn't clear in OP.
>> Ah, I didn't think of that.  (IMHO that's an unfortunate and
>> counterintuitive feature.)
>> You could check for a '-' character following zero or more
>> whitespace
>> characters.
>> 
>>>> The checks are probably unnecessary.  As of the current C standard,
>>>> SIZE_MAX cannot be bigger than UINT_MAX.
>>> I didn't know this. Not sure how much adoption the current C standard
>>> found but it's definitely a step forward for the language. Good.
>> uintmax_t and UINT_MAX were introduced in C99.  If an implementation
>> supports [u]intmax_t at all, it will follow the requirement that
>> they are the widest supported [un]signed integer types.  (I don't
>> know of any current implementations that don't support <stdint.h>.)
>> It turned out that increasing the width of [u]intmax_t as longer
>> integer types are introduced (typically 128 bits) caused problems
>> with ABIs.  Adding a 128-bit integer type can be done without
>> breaking existing code, but changing the size of [u]intmax_t due to
>> that addition would break the interface been programs and library
>> codes, since there are standard library functions that take arguments
>> of those types.  I personally would be much happier if we could
>> maintain the guarantee that [u]intmax_t are the widest [un]signed
>> integer types, but apparently there's no consistent way to do that.
>> C23 will allow an implementation, for example, to provide 64-bit
>> long long
>> and 128-bit *extended integer types*, but (optionally) keep [u]intmax_t
>> at 64 bits.
>> https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3054.pdf
>> 7.22.1.5
>> 
>
> I think you mean UINTMAX_MAX, not UINT_MAX.
>
> UINT_MAX is the limit for unsigned int, which on many 64 bits systems
> is only 32 bits big, and will be smaller that SIZE_MAX.

Yes, thank you for the correction.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#168595

Fromscott@slp53.sl.home (Scott Lurndal)
Date2022-12-19 18:40 +0000
Message-ID<8e2oL.103648$gGD7.17914@fx11.iad>
In reply to#168593
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>Oğuz <oguzismailuysal@gmail.com> writes:
>> I wrote the function below for converting a string to size_t without
>> manually calculating its value digit by digit. It first converts the 
>> string to intmax_t, and if the conversion fails due to a range error
>> and SIZE_MAX doesn't fit into an intmax_t, it tries again with
>> uintmax_t. In both cases, if the result is less than zero it
>> fails. And on success it populates *result with the result.
>>
>> It works on my machine and a couple others I tried, but I'm not sure
>> if it's good C, or a good idea at all. What do you think about it?
>>
>> int
>> strtosize(const char *nptr, char **endptr, int base, size_t *result) {
>> 	intmax_t s;
>> 	uintmax_t u;
>>
>> 	errno = 0;
>> 	s = strtoimax(nptr, endptr, base);
>>
>> 	if (errno == 0 && s >= 0 && s <= SIZE_MAX) {
>> 		*result = s;
>> 		return 1;
>> 	}
>>
>> #if SIZE_MAX > INTMAX_MAX
>> 	if (errno == ERANGE && s == INTMAX_MAX) {
>> 		errno = 0;
>> 		u = strtoumax(nptr, endptr, base);
>>
>> 		if (errno == 0 && u <= SIZE_MAX) {
>> 			*result = u;
>> 			return 1;
>> 		}
>> 	}
>> #endif
>>
>> 	if (errno == 0)
>> 		errno = ERANGE;
>>
>> 	return 0;
>> }
>
>What is the point of trying strotoimax before using strotoumax?
>Just call strtotumax and convert the result to size_t.

What's wrong with strtoul?

[toc] | [prev] | [next] | [standalone]


#168600

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2022-12-19 12:07 -0800
Message-ID<871qovrwc2.fsf@nosuchdomain.example.com>
In reply to#168595
scott@slp53.sl.home (Scott Lurndal) writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
[...]
>>What is the point of trying strotoimax before using strotoumax?
>>Just call strtotumax and convert the result to size_t.
>
> What's wrong with strtoul?

size_t can be wider than unsigned long.  On modern Windows, for example,
unsigned long is 32 bits and size_t is 64 bits.

strtoull could also work (and as far as I know there are no current
implementations with uintmax_t wider than unsigned long long), but
strtoumax (which I misspelled above) makes the point more clearly.


-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#168601

Fromscott@slp53.sl.home (Scott Lurndal)
Date2022-12-19 20:31 +0000
Message-ID<SS3oL.38678$t5W7.21628@fx13.iad>
In reply to#168600
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>scott@slp53.sl.home (Scott Lurndal) writes:
>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>[...]
>>>What is the point of trying strotoimax before using strotoumax?
>>>Just call strtotumax and convert the result to size_t.
>>
>> What's wrong with strtoul?
>
>size_t can be wider than unsigned long.  On modern Windows, for example,
>unsigned long is 32 bits and size_t is 64 bits.

Yes, I meant strtoull, which I use extensively.

[toc] | [prev] | [next] | [standalone]


#168603

FromTony Oliver <guinness.tony@gmail.com>
Date2022-12-19 16:33 -0800
Message-ID<a6c8f08f-5821-4aba-b27d-5e68eb9ba3d7n@googlegroups.com>
In reply to#168595
On Monday, 19 December 2022 at 18:40:20 UTC, Scott Lurndal wrote:
> Keith Thompson <Keith.S.T...@gmail.com> writes: 
> >Oğuz <oguzism...@gmail.com> writes: 
> >> I wrote the function below for converting a string to size_t without 
> >> manually calculating its value digit by digit. It first converts the 
> >> string to intmax_t, and if the conversion fails due to a range error 
> >> and SIZE_MAX doesn't fit into an intmax_t, it tries again with 
> >> uintmax_t. In both cases, if the result is less than zero it 
> >> fails. And on success it populates *result with the result. 
> >> 
> >> It works on my machine and a couple others I tried, but I'm not sure 
> >> if it's good C, or a good idea at all. What do you think about it? 
> >> 
> >> int 
> >> strtosize(const char *nptr, char **endptr, int base, size_t *result) { 
> >> intmax_t s; 
> >> uintmax_t u; 
> >> 
> >> errno = 0; 
> >> s = strtoimax(nptr, endptr, base); 
> >> 
> >> if (errno == 0 && s >= 0 && s <= SIZE_MAX) { 
> >> *result = s; 
> >> return 1; 
> >> } 
> >> 
> >> #if SIZE_MAX > INTMAX_MAX 
> >> if (errno == ERANGE && s == INTMAX_MAX) { 
> >> errno = 0; 
> >> u = strtoumax(nptr, endptr, base); 
> >> 
> >> if (errno == 0 && u <= SIZE_MAX) { 
> >> *result = u; 
> >> return 1; 
> >> } 
> >> } 
> >> #endif 
> >> 
> >> if (errno == 0) 
> >> errno = ERANGE; 
> >> 
> >> return 0; 
> >> } 
> > 
> >What is the point of trying strotoimax before using strotoumax? 
> >Just call strtotumax and convert the result to size_t.
> What's wrong with strtoul?

Because sizeof( unsigned int ) might be less than sizeof ( uintmax_t ).

[toc] | [prev] | [next] | [standalone]


#168597

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2022-12-19 11:20 -0800
Message-ID<867cyn19qw.fsf@linuxsc.com>
In reply to#168593
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> O?uz <oguzismailuysal@gmail.com> writes:
>
>> I wrote the function below for converting a string to size_t without
>> manually calculating its value digit by digit.  It first converts the
>> string to intmax_t, and if the conversion fails due to a range error
>> and SIZE_MAX doesn't fit into an intmax_t, it tries again with
>> uintmax_t.  In both cases, if the result is less than zero it
>> fails.  And on success it populates *result with the result.
>>
>> It works on my machine and a couple others I tried, but I'm not sure
>> if it's good C, or a good idea at all.  What do you think about it?
>>
>> int
>> strtosize(const char *nptr, char **endptr, int base, size_t *result) {
>> 	intmax_t s;
>> 	uintmax_t u;
>>
>> 	errno = 0;
>> 	s = strtoimax(nptr, endptr, base);
>>
>> 	if (errno == 0 && s >= 0 && s <= SIZE_MAX) {
>> 		*result = s;
>> 		return 1;
>> 	}
>>
>> #if SIZE_MAX > INTMAX_MAX
>> 	if (errno == ERANGE && s == INTMAX_MAX) {
>> 		errno = 0;
>> 		u = strtoumax(nptr, endptr, base);
>>
>> 		if (errno == 0 && u <= SIZE_MAX) {
>> 			*result = u;
>> 			return 1;
>> 		}
>> 	}
>> #endif
>>
>> 	if (errno == 0)
>> 		errno = ERANGE;
>>
>> 	return 0;
>> }
>
> What is the point of trying strotoimax before using strotoumax?
> Just call strtotumax and convert the result to size_t.
>
> The checks are probably unnecessary.  As of the current C standard,
> SIZE_MAX cannot be bigger than UINT_MAX.  (C23 will allow for
> the possibility that SIZE_MAX > UINT_MAX, but implementations are
> unlikely to take advantage of that -- which means your checking
> code will at best be difficult to test.)

I think you mean UINTMAX_MAX rather than UINT_MAX.

[toc] | [prev] | [next] | [standalone]


#168602

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2022-12-19 22:16 +0000
Message-ID<87v8m7vy2r.fsf@bsb.me.uk>
In reply to#168591
Oğuz <oguzismailuysal@gmail.com> writes:

> I wrote the function below for converting a string to size_t without
> manually calculating its value digit by digit. It first converts the
> string to intmax_t, and if the conversion fails due to a range error
> and SIZE_MAX doesn't fit into an intmax_t, it tries again with
> uintmax_t. In both cases, if the result is less than zero it
> fails. And on success it populates *result with the result.
>
> It works on my machine and a couple others I tried, but I'm not sure
> if it's good C, or a good idea at all. What do you think about it?
>
> int
> strtosize(const char *nptr, char **endptr, int base, size_t *result) {

This name encroaches on the implementation's reserved name space.  Also,
I would consider mirroring the return value and semantics of the other
standard strtoXXX functions.  It's not a great interface to mimic, but
it is what readers are likely to expect.

> 	intmax_t s;
> 	uintmax_t u;
>
> 	errno = 0;
> 	s = strtoimax(nptr, endptr, base);
>
> 	if (errno == 0 && s >= 0 && s <= SIZE_MAX) {

This test may not do what you want.  When the string contains junk (for
example "#") s will be 0 and errno will not have been changed.

If this matters to you, you need to pass your own non-zero "end" pointer
to strtoimax and check that:

  char *ep;
  intmax_t s = strtoimax(nptr, &ep, base);

  if (errno == 0 && ep > nptr && s >= 0 && s <= SIZE_MAX) {
        *result = u;
        if (endptr) *endptr = ep;
	return 1;
  }

I'm late to the party so I'm only making these tangential remarks...

-- 
Ben.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web