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


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

Dymamic arrays: memory management and naming

Started byAnton Shepelev <anton.txt@gmail.moc>
First post2023-09-09 13:23 +0300
Last post2023-09-26 00:07 +0000
Articles 20 on this page of 50 — 11 participants

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


Contents

  Dymamic arrays: memory management and naming Anton Shepelev <anton.txt@gmail.moc> - 2023-09-09 13:23 +0300
    Re: Dymamic arrays: memory management and naming Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-09 03:56 -0700
    Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-09 15:06 +0000
    Re: Dymamic arrays: memory management and naming scott@slp53.sl.home (Scott Lurndal) - 2023-09-09 15:44 +0000
    Re: Dymamic arrays: memory management and naming Spiros Bousbouras <spibou@gmail.com> - 2023-09-10 17:57 +0000
      Re: Dymamic arrays: memory management and naming Anton Shepelev <anton.txt@gmail.moc> - 2023-09-10 23:49 +0300
        Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-10 21:25 +0000
    Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-12 16:07 -0700
      Re: Dymamic arrays: memory management and naming Anton Shepelev <anton.txt@gmail.moc> - 2023-09-17 00:44 +0300
    Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-17 16:51 -0700
      Re: Dymamic arrays: memory management and naming Anton Shepelev <anton.txt@gmail.moc> - 2023-09-19 01:10 +0300
        Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-19 07:58 -0700
        Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-19 10:33 -0700
          Re: Dymamic arrays: memory management and naming Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-09-19 15:08 -0700
            Re: Dymamic arrays: memory management and naming "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-09-19 15:35 -0700
            Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-19 22:49 +0000
              Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-19 22:30 -0700
                Re: Dymamic arrays: memory management and naming Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-09-20 02:46 -0700
                  Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-20 07:06 -0700
                Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-20 21:03 +0000
                  Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-25 14:08 -0700
                    Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-25 21:27 +0000
            Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-19 22:17 -0700
          Re: Dymamic arrays: memory management and naming Anton Shepelev <anton.txt@gmail.moc> - 2023-09-24 00:39 +0300
            Re: Dymamic arrays: memory management and naming Blue-Maned_Hawk <bluemanedhawk@invalid.invalid> - 2023-09-23 21:48 +0000
            Re: Dymamic arrays: memory management and naming James Kuyper <jameskuyper@alumni.caltech.edu> - 2023-09-24 00:15 -0400
            Re: Dymamic arrays: memory management and naming Spiros Bousbouras <spibou@gmail.com> - 2023-09-24 11:48 +0000
              Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-24 16:08 +0000
                Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-25 13:21 -0700
                  Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-25 21:06 +0000
                    Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-25 18:43 -0700
                Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-25 23:14 +0000
                  Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-25 19:00 -0700
                    Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-26 02:38 +0000
                      Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-25 23:42 -0700
                    Re: Dymamic arrays: memory management and naming Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-09-25 19:38 -0700
                      Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-25 23:41 -0700
                        Re: Dymamic arrays: memory management and naming Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-09-26 02:42 -0700
                          Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-10-03 03:29 -0700
              Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-24 16:11 +0000
              Re: Dymamic arrays: memory management and naming James Kuyper <jameskuyper@alumni.caltech.edu> - 2023-09-24 12:28 -0400
                Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-24 17:10 +0000
                  Re: Dymamic arrays: memory management and naming James Kuyper <jameskuyper@alumni.caltech.edu> - 2023-09-24 13:56 -0400
              Re: Dymamic arrays: memory management and naming Phil Carmody <pc+usenet@asdf.org> - 2023-09-30 13:50 +0300
                Re: Dymamic arrays: memory management and naming Spiros Bousbouras <spibou@gmail.com> - 2023-10-01 17:43 +0000
            Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-25 09:21 -0700
              Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-25 18:06 +0000
                Re: Dymamic arrays: memory management and naming Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-25 15:24 -0700
                  Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-25 23:49 +0000
                  Re: Dymamic arrays: memory management and naming Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-26 00:07 +0000

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#176389

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-09-25 14:08 -0700
Message-ID<865y3yj70m.fsf@linuxsc.com>
In reply to#176098
Kaz Kylheku <864-117-4973@kylheku.com> writes:

> On 2023-09-20, Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>
>> Kaz Kylheku <864-117-4973@kylheku.com> writes:
>>
>>> On 2023-09-19, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
>>>
>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>> [...]
>>>>
>>>>> Note by the way that sizeof (max_align_t) might not be the same
>>>>> as _Alignof (max_align_t).
>>>>
>>>> Indeed.  I was curious about this, so I wrote a small test program that
>>>> shows that _Alignof (max_align_t) is 16, but sizeof (max_align_t) is 32
>>>> on the implementation I'm using.
>>>>
>>>> I'm using gcc, which defines max_align_t as a struct containing a long
>>>> long, a long double, and optionally a __float128.  It could have reduced
>>>> the size by making it a union rather than a struct, but there's rarely
>>>> (?) any reason to create objects of type max_align_t.
>>>
>>> Yes there is!
>>>
>>>   union {
>>>     foo_t x;
>>>     bar_t y;
>>>
>>>     // please give my own union maximum alignment --- without undue bloat
>>>
>>>     max_align_t align;
>>>   }
>>>
>>> A max_align_t that can only be used as _Alignof(max_align_t) is useless;
>>> it might as well be a #define ALIGN_MAX 16 constant in some header
>>> like <limits.h>.
>>
>> You need to think harder.
>
> I'm "thinking broader" instead, maybe?

No, you aren't.  First you gave faulty reasoning for needing to
declare something that has type max_align_t.  When that reasoning
was shown to be wrong you fell back to an imaginary world to say
something would be nice to have when the something provides no
greater expressive power than what is there already.  It's great
to have new ideas, but not all new ideas are good ideas.  There
is no need for what you propose, and thus adding it to C would
have negative value.

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


#176391

FromKaz Kylheku <864-117-4973@kylheku.com>
Date2023-09-25 21:27 +0000
Message-ID<20230925141208.949@kylheku.com>
In reply to#176389
On 2023-09-25, Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
> Kaz Kylheku <864-117-4973@kylheku.com> writes:
>
>> On 2023-09-20, Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>>
>>> Kaz Kylheku <864-117-4973@kylheku.com> writes:
>>>
>>>> On 2023-09-19, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
>>>>
>>>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>>> [...]
>>>>>
>>>>>> Note by the way that sizeof (max_align_t) might not be the same
>>>>>> as _Alignof (max_align_t).
>>>>>
>>>>> Indeed.  I was curious about this, so I wrote a small test program that
>>>>> shows that _Alignof (max_align_t) is 16, but sizeof (max_align_t) is 32
>>>>> on the implementation I'm using.
>>>>>
>>>>> I'm using gcc, which defines max_align_t as a struct containing a long
>>>>> long, a long double, and optionally a __float128.  It could have reduced
>>>>> the size by making it a union rather than a struct, but there's rarely
>>>>> (?) any reason to create objects of type max_align_t.
>>>>
>>>> Yes there is!
>>>>
>>>>   union {
>>>>     foo_t x;
>>>>     bar_t y;
>>>>
>>>>     // please give my own union maximum alignment --- without undue bloat
>>>>
>>>>     max_align_t align;
>>>>   }
>>>>
>>>> A max_align_t that can only be used as _Alignof(max_align_t) is useless;
>>>> it might as well be a #define ALIGN_MAX 16 constant in some header
>>>> like <limits.h>.
>>>
>>> You need to think harder.
>>
>> I'm "thinking broader" instead, maybe?
>
> No, you aren't.  First you gave faulty reasoning for needing to
> declare something that has type max_align_t.  When that reasoning
> was shown to be wrong you fell back to an imaginary world to say
> something would be nice to have when the something provides no
> greater expressive power than what is there already.

That sounds tautological; nothing provides greater expressive
power than that power which it has already.

> It's great
> to have new ideas, but not all new ideas are good ideas.  There

I'm pretty sure that sticking a dummy member into a union so that it has
at least that member's alignment isn't a new idea, let alone my idea.

> is no need for what you propose, and thus adding it to C would
> have negative value.

Can you clarify what it is you think that I proposed?

I believe that it consisted entirely of the idea that max_align_t would
be improved if it were required to have a size that does not exceed its
alignment.

However, that literal idea has flaws, because what if there is no such
type? Say max alignment is four bytes, on a machine that doesn't have a
four byte type, only one or eight. max_align_t will have to be eight,
which will make the union larger than necessary. (This is why in the
code comment I wrote "without undue bloat": if bloat is due, it's due.)

The example given by Keith of how GCC defined max_align_t, however,
gratuitously makes the type larger by simply aggregating various types
via struct.  The underlying platform does have types whose size is equal
to the alignment of that max_align_t.

If a reasonable requirement could be articulated to discourage that, it
would be good.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca
NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

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


#176049

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-09-19 22:17 -0700
Message-ID<86fs39l8xp.fsf@linuxsc.com>
In reply to#176041
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> [...]
>
>> Note by the way that sizeof (max_align_t) might not be the same
>> as _Alignof (max_align_t).
>
> Indeed.  I was curious about this, so I wrote a small test program that
> shows that _Alignof (max_align_t) is 16, but sizeof (max_align_t) is 32
> on the implementation I'm using.

That's just what I did. :)

> I'm using gcc, which defines max_align_t as a struct containing a long
> long, a long double, and optionally a __float128.  It could have reduced
> the size by making it a union rather than a struct, but there's rarely
> (?) any reason to create objects of type max_align_t.

AFAICT there is never any reason to use max_align_t as the
type in any declaration, excepting perhaps for probing the
environment like the little test programs mentioned.

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


#176275

FromAnton Shepelev <anton.txt@gmail.moc>
Date2023-09-24 00:39 +0300
Message-ID<20230924003915.51bb21339ab1c551eba59162@gmail.moc>
In reply to#176035
Tim Rentsch:

> One further thought...
>
> As of C11, there is a type max_align_t, defined in
> <stddef.h>, whose alignment is the maximum alignment
> supported by the implementation.  The grain size for
> allocation should be a multiple of
>
>     _Alignof (max_align_t)

When did C abandon its style of lower case, underscore-
separated identifiers?  Why not `alignof' or at least
`_alignof'?

> so this alignment can be supported.  Also, the amount of
> space you use for your "pre-array" metadata should be
> chosen to be a multiple of _Alignof (max_align_t),
> otherwise the array alignments might be off in some cases.

Yes, I have discussed this issue here before, and
implemented a (I think Ben's) suggestion to calculate the
negative offset as the size of the metadata structure
rounded up to a power of two, which should ensure correct
alignment in most cases.

Futhermore, some systems seem not to require alignment,
e.g.:

   #include <stdio.h>
   #include <stdlib.h>

   void print_as( char const * data )
   {  for( int i = 0; i < 2; i += 1 )
      {  printf( "%i ", *((short*)(data+i*2)) );  }
      printf("\n");
   }

   int main()
   {  char* const data = malloc(5);
      for( int i = 0; i < 5; i += 1 )
      {  data[i] = (char)i%2;  }

      print_as( data   );
      print_as( data+1 );

      return 0;
   }

On my shell server, this progrma works, printing:

   256 256
   1 1

-- 
()  ascii ribbon campaign -- against html e-mail
/\  www.asciiribbon.org   -- against proprietary attachments

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


#176278

FromBlue-Maned_Hawk <bluemanedhawk@invalid.invalid>
Date2023-09-23 21:48 +0000
Message-ID<pan$36016$569dd459$1577a2d7$cbc9fd07@invalid.invalid>
In reply to#176275
Anton Shepelev wrote:

> When did C abandon its style of lower case, underscore- separated
> identifiers?  Why not `alignof' or at least `_alignof'?

It's the only option that they had.  The standard reserves names beginning 
with two underscores and names beginning with an underscore followed by a 
_capital_ letter, and they don't want to introduce names outside of those 
spaces.  That being said, they introduced headers for the names they 
_really_ wanted to use, such as your mentioned alignof, and in C23 those 
extra names have been added to the language proper and some new names have 
skipped the namespaces, such as the "new" typeof keyword.



-- 
Blue-Maned_Hawk│shortens to Hawk│/
blu.mɛin.dʰak/│he/him/his/himself/
Mr. bluemanedhawk.github.io
I've always pronounced them /ʔæ.lɪg.nɑf/ and /ʔæ.lɪg.næz/.

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


#176291

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2023-09-24 00:15 -0400
Message-ID<ueod5m$171uk$1@dont-email.me>
In reply to#176275
On 9/23/23 17:39, Anton Shepelev wrote:
...
> When did C abandon its style of lower case, underscore-
> separated identifiers? ...

In C99. It was realized that whenever a new keyword was added, it should
be taken from the space of names that were reserved to the
implementation; otherwise, it could break previously legal user code
that used that identifier for some different, perfectly legal purpose.
That's why new keywords in that version of the standard included _Bool,
_Complex, and _Imaginary. All keywords introduced since that time have
generally obeyed that convention.

> ... Why not `alignof' or at least
> `_alignof'?

Because both"alignof" and "_alignof" are from the name space reserved
for users, and therefore might be in use in existing code.

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


#176302

FromSpiros Bousbouras <spibou@gmail.com>
Date2023-09-24 11:48 +0000
Message-ID<KZf6tlV2s29qC6sCU@bongo-ra.co>
In reply to#176275
On Sun, 24 Sep 2023 00:39:15 +0300
Anton Shepelev <anton.txt@gmail.moc> wrote:
> Futhermore, some systems seem not to require alignment,
> e.g.:
> 
>    #include <stdio.h>
>    #include <stdlib.h>
> 
>    void print_as( char const * data )
>    {  for( int i = 0; i < 2; i += 1 )
>       {  printf( "%i ", *((short*)(data+i*2)) );  }

%hi  would be more precise than  %i .At the very least it saves the reader
the trouble of trying to collect from the various points in the standard
the information to decide whether just  %i  is also guaranteed to work.

>       printf("\n");
>    }
> 
>    int main()
>    {  char* const data = malloc(5);
>       for( int i = 0; i < 5; i += 1 )
>       {  data[i] = (char)i%2;  }

(char)i  will be promoted to something else (most likely  int)  before the
%  operation takes place so the cast is pointless. Even if you had written
(char)(i%2) , given the values involved I don't see the point.

>       print_as( data   );
>       print_as( data+1 );
> 
>       return 0;
>    }
> 
> On my shell server, this progrma works, printing:
> 
>    256 256
>    1 1

"works" depends on assumptions about the system where you ran this. I can
guess what those assumptions are but it's best to state them explicitly.

-- 
Offsets are structures. Structures are offsets.
  Charles Melice
  http://al.howardknight.net/?ID=169555586400

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


#176308

FromKaz Kylheku <864-117-4973@kylheku.com>
Date2023-09-24 16:08 +0000
Message-ID<20230924081911.947@kylheku.com>
In reply to#176302
On 2023-09-24, Spiros Bousbouras <spibou@gmail.com> wrote:
> On Sun, 24 Sep 2023 00:39:15 +0300
> Anton Shepelev <anton.txt@gmail.moc> wrote:
>> Futhermore, some systems seem not to require alignment,
>> e.g.:
>> 
>>    #include <stdio.h>
>>    #include <stdlib.h>
>> 
>>    void print_as( char const * data )
>>    {  for( int i = 0; i < 2; i += 1 )
>>       {  printf( "%i ", *((short*)(data+i*2)) );  }
>
> %hi  would be more precise than  %i .At the very least it saves the reader
> the trouble of trying to collect from the various points in the standard
> the information to decide whether just  %i  is also guaranteed to work.

People reviewing C code should know the utter basics, like that short
promotes to int. This is not an unreasonable expectation.

If the code creates an opportunity to get a refresher in a forgotten
matter in a fundamental language area, that's a good thing.

There is no reason to use a the h modifier with the signed conversion
specifiers d and i, if the argument is (before promotion) of type
short. In that situation it obviously does nothing.

All that the h does is insert an downcast. %hi is like %i except
that internally it convert the value to short, which can be imagined to
occur by a (short) cast.

That either does nothing (the value is in range of short due to having
been promoted out of short) or else produces an implementation-defined
result. Why bring that into the picture? That could become a problem
if the code is changed, and someone forgets to remove the h.

h only makes sense if you're passing a signed argument and want it
printed as unsigned. Say we have 16 bit short and 32 bit int.
Then "%u"/(short) -1 will print as 429496725, whereas "%hu"/(short) -1
will obtain the desired 65535.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca
NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

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


#176387

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-09-25 13:21 -0700
Message-ID<86a5taj96a.fsf@linuxsc.com>
In reply to#176308
Kaz Kylheku <864-117-4973@kylheku.com> writes:

> People reviewing C code should know the utter basics, like that short
> promotes to int.  This is not an unreasonable expectation.

Amusing, in light of what follows.

> [...]
>
> h only makes sense if you're passing a signed argument and want it
> printed as unsigned.  Say we have 16 bit short and 32 bit int.
> Then "%u"/(short) -1 will print as 429496725, whereas "%hu"/(short) -1
> will obtain the desired 65535.

Both of those have undefined behavior.

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


#176388

FromKaz Kylheku <864-117-4973@kylheku.com>
Date2023-09-25 21:06 +0000
Message-ID<20230925134735.419@kylheku.com>
In reply to#176387
On 2023-09-25, Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
> Kaz Kylheku <864-117-4973@kylheku.com> writes:
>
>> People reviewing C code should know the utter basics, like that short
>> promotes to int.  This is not an unreasonable expectation.
>
> Amusing, in light of what follows.
>
>> [...]
>>
>> h only makes sense if you're passing a signed argument and want it
>> printed as unsigned.  Say we have 16 bit short and 32 bit int.
>> Then "%u"/(short) -1 will print as 429496725, whereas "%hu"/(short) -1
>> will obtain the desired 65535.
>
> Both of those have undefined behavior.

Not both; the second one is okay.

(I should definitely not have asserted that the wrong example will print
a certain output, though it is an example of surprising output that
occurs in practice on common platforms.)

N3096 states, and C99 had a similar wording:

  h   Specifies that a following b, d, i, o, u, x, or X conversion
      specifier applies to a short int or unsigned short int argument.

When the h is present, punning is allowed between signed and unsigned.

There is no wording which restricts by subset: that b, o, u, x and X
take an unsigned short, and only d and i take a short.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca
NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

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


#176408

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-09-25 18:43 -0700
Message-ID<86wmwdiu9w.fsf@linuxsc.com>
In reply to#176388
Kaz Kylheku <864-117-4973@kylheku.com> writes:

> On 2023-09-25, Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>
>> Kaz Kylheku <864-117-4973@kylheku.com> writes:
>>
>>> People reviewing C code should know the utter basics, like that short
>>> promotes to int.  This is not an unreasonable expectation.
>>
>> Amusing, in light of what follows.
>>
>>> [...]
>>>
>>> h only makes sense if you're passing a signed argument and want it
>>> printed as unsigned.  Say we have 16 bit short and 32 bit int.
>>> Then "%u"/(short) -1 will print as 429496725, whereas "%hu"/(short) -1
>>> will obtain the desired 65535.
>>
>> Both of those have undefined behavior.
>
> Not both;  the second one is okay.

That is right.  The wording in C11 is not completely clear on
the question;  however, wording in the C23 draft clarifies the
issue, and establishes that the behavior in this particular
case is well-defined.

It's still a bad idea IMO to use %hu with an argument that
has (before promotion) a signed type, but that's a style
issue, and doesn't change the definedness of this case.

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


#176401

FromKaz Kylheku <864-117-4973@kylheku.com>
Date2023-09-25 23:14 +0000
Message-ID<20230925155845.139@kylheku.com>
In reply to#176308
On 2023-09-24, Kaz Kylheku <864-117-4973@kylheku.com> wrote:
> h only makes sense if you're passing a signed argument and want it
> printed as unsigned. Say we have 16 bit short and 32 bit int.
> Then "%u"/(short) -1 will print as 429496725, whereas "%hu"/(short) -1
> will obtain the desired 65535.

There is something I had neglected to mention: the use of h for portability

If we have "%u" paired with an unsigned short, argument we have
a mismatch on a large number of platforms, where unsigned short promotes
to int. The %u specifier wants unsigned int.

%hu will take care of it somehow. It knows which way the unsigned
short argument has promoted, and recover the value.

The h modifier makes the conversion specifier compatible with either
a short or unsigned short argument. That means that on platforms where
they promote the same way, it expects an actual type of int.
On platforms where they don't it has to do something like, oh,
in the case of the unsigned specifier, assume that the argument
was converted from an unsigned short, and treat the bits accordingly.

If we want specifically %u for decimal output, and we know that
unsigned short promotes to int, we can get away with %d.

That's not correct if unsigned short isn't promoting to int, and
not applicable if we want %x/%X, %o or %b.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca
NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

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


#176410

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-09-25 19:00 -0700
Message-ID<86sf71itgt.fsf@linuxsc.com>
In reply to#176401
Kaz Kylheku <864-117-4973@kylheku.com> writes:

> On 2023-09-24, Kaz Kylheku <864-117-4973@kylheku.com> wrote:
>
>> h only makes sense if you're passing a signed argument and want it
>> printed as unsigned.  Say we have 16 bit short and 32 bit int.
>> Then "%u"/(short) -1 will print as 429496725, whereas "%hu"/(short) -1
>> will obtain the desired 65535.
>
> There is something I had neglected to mention:  the use of h for portability
>
> If we have "%u" paired with an unsigned short, argument we have
> a mismatch on a large number of platforms, where unsigned short promotes
> to int.  The %u specifier wants unsigned int.

A %u conversion specification is always okay for an unsigned
short argument, regardless of whether the argument promotes to
int or to unsigned int.  Reading an integer-typed variadic
argument with the corresponding type of the other signedness
is allowed when the argument value is representable in both
types, which it always will be in this case even if unsigned
short promotes to int.

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


#176411

FromKaz Kylheku <864-117-4973@kylheku.com>
Date2023-09-26 02:38 +0000
Message-ID<20230925190228.732@kylheku.com>
In reply to#176410
On 2023-09-26, Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
> Kaz Kylheku <864-117-4973@kylheku.com> writes:
>
>> On 2023-09-24, Kaz Kylheku <864-117-4973@kylheku.com> wrote:
>>
>>> h only makes sense if you're passing a signed argument and want it
>>> printed as unsigned.  Say we have 16 bit short and 32 bit int.
>>> Then "%u"/(short) -1 will print as 429496725, whereas "%hu"/(short) -1
>>> will obtain the desired 65535.
>>
>> There is something I had neglected to mention:  the use of h for portability
>>
>> If we have "%u" paired with an unsigned short, argument we have
>> a mismatch on a large number of platforms, where unsigned short promotes
>> to int.  The %u specifier wants unsigned int.
>
> A %u conversion specification is always okay for an unsigned
> short argument, regardless of whether the argument promotes to
> int or to unsigned int.

> Reading an integer-typed variadic
> argument with the corresponding type of the other signedness
> is allowed when the argument value is representable in both
> types, which it always will be in this case even if unsigned
> short promotes to int.

OK, I see how that is derived. printf is now described as if using
va_arg to extract the promoted type of the conversion specifier's type,
and then converting the promoted type to the the specifier's type (which
can hardly be done in any other way).

C99 didn't have this, only "If any argument is not the correct type for
the corresponding conversion specification, the behavior is undefined."

(Even though it already featured the signed/unsigned flexibility
measure in va_arg!)

If %u is implemented in C99 using va_arg, it will be well defined
for an unsigned short argument. For it not to be well-defined, it would
have to use some other mechanism than va_arg, which is more fragile.
But that makes next to no sense; this is a defect fix, really.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca
NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

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


#176418

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-09-25 23:42 -0700
Message-ID<86jzsdigek.fsf@linuxsc.com>
In reply to#176411
Kaz Kylheku <864-117-4973@kylheku.com> writes:

> On 2023-09-26, Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
>
>> Kaz Kylheku <864-117-4973@kylheku.com> writes:
>>
>>> On 2023-09-24, Kaz Kylheku <864-117-4973@kylheku.com> wrote:
>>>
>>>> h only makes sense if you're passing a signed argument and want it
>>>> printed as unsigned.  Say we have 16 bit short and 32 bit int.
>>>> Then "%u"/(short) -1 will print as 429496725, whereas "%hu"/(short) -1
>>>> will obtain the desired 65535.
>>>
>>> There is something I had neglected to mention:  the use of h for
>>> portability
>>>
>>> If we have "%u" paired with an unsigned short, argument we have a
>>> mismatch on a large number of platforms, where unsigned short
>>> promotes to int.  The %u specifier wants unsigned int.
>>
>> A %u conversion specification is always okay for an unsigned
>> short argument, regardless of whether the argument promotes to
>> int or to unsigned int.
>>
>> Reading an integer-typed variadic
>> argument with the corresponding type of the other signedness
>> is allowed when the argument value is representable in both
>> types, which it always will be in this case even if unsigned
>> short promotes to int.
>
> OK, I see how that is derived.  printf is now described as if using
> va_arg to extract the promoted type of the conversion specifier's
> type, and then converting the promoted type to the the specifier's
> type (which can hardly be done in any other way).
>
> C99 didn't have this, only "If any argument is not the correct type
> for the corresponding conversion specification, the behavior is
> undefined."

Please see my response to the parallel post by Keith Thompson.

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


#176412

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2023-09-25 19:38 -0700
Message-ID<87msx9u09c.fsf@nosuchdomain.example.com>
In reply to#176410
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Kaz Kylheku <864-117-4973@kylheku.com> writes:
>> On 2023-09-24, Kaz Kylheku <864-117-4973@kylheku.com> wrote:
>>> h only makes sense if you're passing a signed argument and want it
>>> printed as unsigned.  Say we have 16 bit short and 32 bit int.
>>> Then "%u"/(short) -1 will print as 429496725, whereas "%hu"/(short) -1
>>> will obtain the desired 65535.
>>
>> There is something I had neglected to mention:  the use of h for portability
>>
>> If we have "%u" paired with an unsigned short, argument we have
>> a mismatch on a large number of platforms, where unsigned short promotes
>> to int.  The %u specifier wants unsigned int.
>
> A %u conversion specification is always okay for an unsigned
> short argument, regardless of whether the argument promotes to
> int or to unsigned int.  Reading an integer-typed variadic
> argument with the corresponding type of the other signedness
> is allowed when the argument value is representable in both
> types, which it always will be in this case even if unsigned
> short promotes to int.

Agreed, but unfortunately the standard doesn't quite say that in
normative text -- until C23, as I discovered while writing this.

In C17 and earlier, 7.21.6.1p9 (The fprintf function) says:
    If any argument is not the correct type for the corresponding
    conversion specification, the behavior is undefined.

(The word "the" implies that there is only one "correct type".)

6.2.5p9 (Types) says:
    The range of nonnegative values of a signed integer type is a
    subrange of the corresponding unsigned integer type, and the
    representation of the same value in each type is the same.
with a footnote:
    The same representation and alignment requirements are meant to
    imply interchangeability as arguments to functions, return values
    from functions, and members of unions.
but of course footnotes are non-normative.

I can imagine a (contrived) conforming implementation that passes
int arguments in one set of CPU registers and unsigned int arguments
in another set of CPU registers, so that `printf("%u\n", 42);`
would very probably *not* print "42".  Such an implementation
would violate the intent of that footnote, but would not as far
as I can tell violate any normative requirement.  (In real life,
I'm sure no such implementation exists.)

But C23 (N3096 draft) changes the description for fprintf:
    fprintf shall behave as if it uses va_arg with a type argument
    naming the type resulting from applying the default argument
    promotions to the type corresponding to the conversion
    specification and then converting the result of the va_arg
    expansion to the type corresponding to the conversion
    specification.

and the description of the va_arg() macro explicitly allows the type
of the first argument and the type given by the second argument
to be corresponding signed and unsigned types, if the value is
representable in both types.  (This goes back to C99.)

Prior to C23, though the <stdarg.h> macros are the obvious way to
implement the *printf() functions, the standard didn't require it
to behave that way.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

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


#176417

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-09-25 23:41 -0700
Message-ID<86o7hpiggw.fsf@linuxsc.com>
In reply to#176412
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Kaz Kylheku <864-117-4973@kylheku.com> writes:
>>
>>> On 2023-09-24, Kaz Kylheku <864-117-4973@kylheku.com> wrote:
>>>
>>>> h only makes sense if you're passing a signed argument and want
>>>> it printed as unsigned.  Say we have 16 bit short and 32 bit int.
>>>> Then "%u"/(short) -1 will print as 429496725, whereas
>>>> "%hu"/(short) -1 will obtain the desired 65535.
>>>
>>> There is something I had neglected to mention:  the use of h for
>>> portability
>>>
>>> If we have "%u" paired with an unsigned short, argument we have a
>>> mismatch on a large number of platforms, where unsigned short
>>> promotes to int.  The %u specifier wants unsigned int.
>>
>> A %u conversion specification is always okay for an unsigned
>> short argument, regardless of whether the argument promotes to
>> int or to unsigned int.  Reading an integer-typed variadic
>> argument with the corresponding type of the other signedness
>> is allowed when the argument value is representable in both
>> types, which it always will be in this case even if unsigned
>> short promotes to int.
>
> Agreed, but unfortunately the standard doesn't quite say that in
> normative text -- until C23, as I discovered while writing this.
> [...]

My position is that this rule was intended since at least C99
(and perhaps earlier) but was not expressed at unambiguously as
one might like.

Also I believe there is support for this view if one consults
various historical documents done by the ISO C committee.

Also I think it is rather pointless to debate whether the C
standard does or does not "say that in normative text" when
the normative text that is there lends itself to different
interpretations.  We all agree on what words are used;  what
the words mean in this case is more a subjective reaction
than an objective fact.  And is pretty much beside the point
since what was intended and what was understood is the same
for most of the people who are familiar with the C standard.

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


#176433

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2023-09-26 02:42 -0700
Message-ID<87fs31tgnj.fsf@nosuchdomain.example.com>
In reply to#176417
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>> Kaz Kylheku <864-117-4973@kylheku.com> writes:
>>>> On 2023-09-24, Kaz Kylheku <864-117-4973@kylheku.com> wrote:
>>>>> h only makes sense if you're passing a signed argument and want
>>>>> it printed as unsigned.  Say we have 16 bit short and 32 bit int.
>>>>> Then "%u"/(short) -1 will print as 429496725, whereas
>>>>> "%hu"/(short) -1 will obtain the desired 65535.
>>>>
>>>> There is something I had neglected to mention:  the use of h for
>>>> portability
>>>>
>>>> If we have "%u" paired with an unsigned short, argument we have a
>>>> mismatch on a large number of platforms, where unsigned short
>>>> promotes to int.  The %u specifier wants unsigned int.
>>>
>>> A %u conversion specification is always okay for an unsigned
>>> short argument, regardless of whether the argument promotes to
>>> int or to unsigned int.  Reading an integer-typed variadic
>>> argument with the corresponding type of the other signedness
>>> is allowed when the argument value is representable in both
>>> types, which it always will be in this case even if unsigned
>>> short promotes to int.
>>
>> Agreed, but unfortunately the standard doesn't quite say that in
>> normative text -- until C23, as I discovered while writing this.
>> [...]
>
> My position is that this rule was intended since at least C99
> (and perhaps earlier) but was not expressed at unambiguously as
> one might like.

It was not expressed in normative text, ambiguously or otherwise.

> Also I believe there is support for this view if one consults
> various historical documents done by the ISO C committee.

You wouldn't have specific citations, would you?

In any case, the language is defined by the standard, not by
historical documents with wording that never made it into the
standard.  No implementer or programmer should have to consult
"historical documents" to determine what the standard requires.

> Also I think it is rather pointless to debate whether the C
> standard does or does not "say that in normative text" when
> the normative text that is there lends itself to different
> interpretations.  We all agree on what words are used;  what
> the words mean in this case is more a subjective reaction
> than an objective fact.  And is pretty much beside the point
> since what was intended and what was understood is the same
> for most of the people who are familiar with the C standard.

You consider it pointless.  I don't.  I find both the intent behind
the standard and what the standard says interesting.  In this case,
they were two different things, and I consider that to be a flaw
in the standard.  I'm glad the flaw is being corrected in C23.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

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


#177181

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2023-10-03 03:29 -0700
Message-ID<86sf6sc82x.fsf@linuxsc.com>
In reply to#176433
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>
>>> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>>>
>>>> Kaz Kylheku <864-117-4973@kylheku.com> writes:
>>>>
>>>>> On 2023-09-24, Kaz Kylheku <864-117-4973@kylheku.com> wrote:
>>>>>
>>>>>> h only makes sense if you're passing a signed argument and want
>>>>>> it printed as unsigned.  Say we have 16 bit short and 32 bit int.
>>>>>> Then "%u"/(short) -1 will print as 429496725, whereas
>>>>>> "%hu"/(short) -1 will obtain the desired 65535.
>>>>>
>>>>> There is something I had neglected to mention:  the use of h for
>>>>> portability
>>>>>
>>>>> If we have "%u" paired with an unsigned short, argument we have a
>>>>> mismatch on a large number of platforms, where unsigned short
>>>>> promotes to int.  The %u specifier wants unsigned int.
>>>>
>>>> A %u conversion specification is always okay for an unsigned
>>>> short argument, regardless of whether the argument promotes to
>>>> int or to unsigned int.  Reading an integer-typed variadic
>>>> argument with the corresponding type of the other signedness
>>>> is allowed when the argument value is representable in both
>>>> types, which it always will be in this case even if unsigned
>>>> short promotes to int.
>>>
>>> Agreed, but unfortunately the standard doesn't quite say that in
>>> normative text -- until C23, as I discovered while writing this.
>>> [...]
>>
>> My position is that this rule was intended since at least C99
>> (and perhaps earlier) but was not expressed at unambiguously as
>> one might like.
>
> It was not expressed in normative text, ambiguously or otherwise.
>
>> Also I believe there is support for this view if one consults
>> various historical documents done by the ISO C committee.
>
> You wouldn't have specific citations, would you?
>
> In any case, the language is defined by the standard, not by
> historical documents with wording that never made it into the
> standard.  No implementer or programmer should have to consult
> "historical documents" to determine what the standard requires.
>
>> Also I think it is rather pointless to debate whether the C
>> standard does or does not "say that in normative text" when
>> the normative text that is there lends itself to different
>> interpretations.  We all agree on what words are used;  what
>> the words mean in this case is more a subjective reaction
>> than an objective fact.  And is pretty much beside the point
>> since what was intended and what was understood is the same
>> for most of the people who are familiar with the C standard.
>
> You consider it pointless.  I don't.  I find both the intent behind
> the standard and what the standard says interesting.  In this case,
> they were two different things, and I consider that to be a flaw
> in the standard.  I'm glad the flaw is being corrected in C23.

I repeat my previous statements.

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


#176309

FromKaz Kylheku <864-117-4973@kylheku.com>
Date2023-09-24 16:11 +0000
Message-ID<20230924090859.714@kylheku.com>
In reply to#176302
On 2023-09-24, Spiros Bousbouras <spibou@gmail.com> wrote:
>>       {  data[i] = (char)i%2;  }
>
> (char)i  will be promoted to something else (most likely  int)  before the
> %  operation takes place so the cast is pointless. Even if you had written
> (char)(i%2) , given the values involved I don't see the point.

It has exactly the same point as your suggestion to use %hi instead of %i.

It feels more precise, by following an imaginary type system in which
imprecise features like promotions don't exist.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca
NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

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


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

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


csiph-web