Author Topic: New C23 working draft  (Read 4612 times)

0 Members and 1 Guest are viewing this topic.

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4035
  • Country: nz
Re: New C23 working draft
« Reply #50 on: June 17, 2022, 10:27:31 am »
This problem doesn't exist in Microsoft QBasic, Visual BASIC, etc; both operations are = and ambiguity is resolved by assignment not being permitted in expression context and an expression alone (other than function calls) not being a statement.

Not much of value is lost that way, you don't see that sort of C code anyway:

I disagree. When I moved from BCPL to C I *really* missed the ability to put a block with a series of statements/loops/local variables etc anywhere a subexpression can go.
 

Offline magic

  • Super Contributor
  • ***
  • Posts: 6779
  • Country: pl
Re: New C23 working draft
« Reply #51 on: June 17, 2022, 01:20:39 pm »
That's a completely different issue, and not really incompatible with C.

Indeed, in C++, you can do just that by defining and immediately calling an anonymous function, although the syntax is more awkward than it needs to be.

Code: [Select]
int main() {
        return []() {return 123;} ();
}
 

Online DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5907
  • Country: es
Re: New C23 working draft
« Reply #52 on: June 17, 2022, 02:05:31 pm »
What's the benefit of using 2's complement? Just makes everything harder:

Decimal   8-bit 2's notation
−42      1101 0110
  42     0010 1010

I doubt many hardware supports that. The MSB bit as sign indicator is way more simple.
Can't understand the logic here, or I got completely lost.
« Last Edit: June 17, 2022, 02:08:26 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline magic

  • Super Contributor
  • ***
  • Posts: 6779
  • Country: pl
Re: New C23 working draft
« Reply #53 on: June 17, 2022, 02:19:07 pm »
Simple parts of the hardware are made even simpler: signed addition and subtraction are exactly the same as unsigned, no hardware duplication, fewer instructions. OTOH, I suppose multiplication gets harder, but it is hard anyway.

Inverting the sign is easy if you have already implemented subtraction.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
Re: New C23 working draft
« Reply #54 on: June 17, 2022, 02:35:38 pm »
how hard is this to implement ?

For someone who suffers from severe case of Dunning-Kruger's, problems seem much easier than they actually are.

Trust me, C is fine. It's just not for you. But professionals need professional tools, not sugar coated shiny toys or training wheels. Professionals are also totally fine specifying if they mean assignment or comparison, it carries zero mental load; the opposite would be a total disaster.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
Re: New C23 working draft
« Reply #55 on: June 17, 2022, 02:39:45 pm »
What's the benefit of using 2's complement? Just makes everything harder:

Decimal   8-bit 2's notation
−42      1101 0110
  42     0010 1010

I doubt many hardware supports that. The MSB bit as sign indicator is way more simple.
Can't understand the logic here, or I got completely lost.

Are you joking or serious? All hardware for the last 30-40 years or so exclusively use 2's complement. That's exactly why the C standard now allows you to assume this is always the case. Earlier, everyone assumed that anyway because sign-and-magnitude hardware has always been extremely rare and esoteric.

The reason is simplicity of hardware: same old adder logic can just add/subtract numbers without special handling of the sign.

For the very same reason, it's kind of easy for human, too: the 2's complement number system forms a full circle, where wrapping occurs from most positive to most negative number. But doing direct conversions from negative decimal to 2's complement binary indeed requires some extra steps which may seem confusing for a human at first. I have utilized this property to deal with actual physical angles which also wrap around mechanically: if the full numerical range equals 360 degrees, you can just interpret the number as unsigned (0 - 360 deg) or signed (-180 - +180 deg). The latter interpretation only works if you use 2's complement: there is only one instance of zero, and numbers grow in the same direction. With sign-and-magnitude, you have two zeroes and around the zero, the direction is swapped! How painful; the only thing that seems a tad easier is manual human conversion of arbitrary negative numbers.
« Last Edit: June 17, 2022, 03:04:31 pm by Siwastaja »
 
The following users thanked this post: newbrain

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 151
  • Country: us
Re: New C23 working draft
« Reply #56 on: June 17, 2022, 02:50:04 pm »
That's a completely different issue, and not really incompatible with C.

Indeed, in C++, you can do just that by defining and immediately calling an anonymous function, although the syntax is more awkward than it needs to be.

Code: [Select]
int main() {
        return []() {return 123;} ();
}

It is awkward becuse you cluttered it with a superfluous pair of `()`. When lambda has no parameters the `()` can be omitted

Code: [Select]
int main()
{
  return []{return 123;}();
}

Done. All awkwardness gone without a trace :)

P.S. On a serious note, the fact that it is permissible to drop the whole `()` in what is in essense a function definition is immensely awkward by itself.
« Last Edit: June 17, 2022, 02:55:39 pm by TheCalligrapher »
 
The following users thanked this post: newbrain, SiliconWizard

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14471
  • Country: fr
Re: New C23 working draft
« Reply #57 on: June 17, 2022, 06:09:20 pm »
What's the benefit of using 2's complement? Just makes everything harder:

Decimal   8-bit 2's notation
−42      1101 0110
  42     0010 1010

I doubt many hardware supports that. The MSB bit as sign indicator is way more simple.
Can't understand the logic here, or I got completely lost.

Are you joking or serious? All hardware for the last 30-40 years or so exclusively use 2's complement. That's exactly why the C standard now allows you to assume this is always the case. Earlier, everyone assumed that anyway because sign-and-magnitude hardware has always been extremely rare and esoteric.(...)

I was just wondering the same. :popcorn:

The obvious benefit of 2's complement is that you can use a simple adder to add two signed integers. The exact same adder as for unsigned operations.
You'd assume that this was obvious for most people these days. Apparently not.

 

Online DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5907
  • Country: es
Re: New C23 working draft
« Reply #58 on: June 17, 2022, 09:12:18 pm »
Yeah I realized the hardware part shortly after...
But the representation is weird from the human side.
Also I expected most of the ALUs to natively handle "classic" representation after 40 years lol.
That's just weird to make such changes now.
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline magic

  • Super Contributor
  • ***
  • Posts: 6779
  • Country: pl
Re: New C23 working draft
« Reply #59 on: June 17, 2022, 10:17:25 pm »
It is awkward becuse you cluttered it with a superfluous pair of `()`. When lambda has no parameters the `()` can be omitted
LOL, I didn't know about it. But it's still a few more characters than strictly necessary to implement code blocks as expressions.

Done. All awkwardness gone without a trace :)
Just wait till the "block expression" needs to access some of the local variables of the containing function :popcorn:
 

Online Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6260
  • Country: fi
    • My home page and email address
Re: New C23 working draft
« Reply #60 on: June 17, 2022, 10:43:39 pm »
But the representation is weird from the human side.
Is it?

I think it is just the name that veers people into thinking it is unintuitive or weird.  Mathematically, if you have \$N\$ bits, \$a_0\$ through \$a_{N-1}\$, they correspond to a signed integer value \$v\$,
$$v = -a_{N-1} 2^{N-1} + \sum_{i=0}^{N-2} a_i 2^i$$
with negative values in two's complement form.  We call bit \$a_{N-1}\$ the sign bit, but mathematically it corresponds to value \$-2^{N-1}\$.  All the rest of the bits have positive value (\$a_i\$ corresponding to positive value \$2^i\$).

I find this form rather easy to grasp intuitively.  All you need to do is consider the most significant bit to have negative value if the bit pattern is a signed integer with two's complement form, and positive value if the bit pattern is an unsigned integer; then just sum the values corresponding to the bits set in the pattern to obtain the numerical value.  For the inverse (numerical value to bit pattern), do the most significant bit first.
 

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4035
  • Country: nz
Re: New C23 working draft
« Reply #61 on: June 18, 2022, 12:26:59 am »
What's the benefit of using 2's complement? Just makes everything harder:

Decimal   8-bit 2's notation
−42      1101 0110
  42     0010 1010

Code: [Select]
42  0010 1010

-42 1101 0101  1's complement. This at least is somewhat easy to work with.
-42 1101 0110  add 1 to get 2's complement. Best Add, subtract, and multiply are the same for signed and unsigned

-42 1010 1010  sign-magnitude. ugh. Far more complex to make an ALU.

Quote
I doubt many hardware supports that. The MSB bit as sign indicator is way more simple.

Basically all integer hardware since 1970ish.
 

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4035
  • Country: nz
Re: New C23 working draft
« Reply #62 on: June 18, 2022, 12:29:19 am »
Simple parts of the hardware are made even simpler: signed addition and subtraction are exactly the same as unsigned, no hardware duplication, fewer instructions. OTOH, I suppose multiplication gets harder, but it is hard anyway.

In an NxN multiplication, the lower N bits of the result are the same no matter whether N is 2-s complement or unsigned.  Only a full 2N bit result needs different versions.
 
The following users thanked this post: newbrain, SiliconWizard, Nominal Animal

Offline newbrainTopic starter

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: New C23 working draft
« Reply #63 on: June 18, 2022, 09:10:50 am »
Basically all integer hardware since 1970ish.
So much so that on the 6502 one needed to explicitly set the carry flag before subtractions (and clear it before addition, but that's normal).

I'm quite convinced  that addition was implemented as:
   Accumulator + operand + Carry bit
(as discussed in other posts, this works beautifully for signed and unsigned maths), and subtraction in the same way, simply flipping the bits of the operand:
   Accumulator + ~operand + Carry bit
The ~operand + Carry(1) is simply -operand.
In this way an extra adder to perform the negation, or a different circuit to perform subtraction, was spared.
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
Re: New C23 working draft
« Reply #64 on: June 18, 2022, 10:16:45 am »
But the representation is weird from the human side.
Is it?

I think it is just the name that veers people into thinking it is unintuitive or weird.  Mathematically, if you have \$N\$ bits, \$a_0\$ through \$a_{N-1}\$, they correspond to a signed integer value \$v\$,
$$v = -a_{N-1} 2^{N-1} + \sum_{i=0}^{N-2} a_i 2^i$$
with negative values in two's complement form.  We call bit \$a_{N-1}\$ the sign bit, but mathematically it corresponds to value \$-2^{N-1}\$.  All the rest of the bits have positive value (\$a_i\$ corresponding to positive value \$2^i\$).

I find this form rather easy to grasp intuitively.  All you need to do is consider the most significant bit to have negative value if the bit pattern is a signed integer with two's complement form, and positive value if the bit pattern is an unsigned integer; then just sum the values corresponding to the bits set in the pattern to obtain the numerical value.  For the inverse (numerical value to bit pattern), do the most significant bit first.

In other words, for those who struggle with mathematical notation, if you plot unsigned representation on X axis, and actual value (how big the number is: -42 is bigger than -43) of the number on Y axis, sign and magnitude system creates a weird triangle where the value first goes down, then stays at the same value for two steps, and then goes up. Two's complement number system is just a straight line, which wraps around in the middle, creating a sawtooth-like curve. But each step is of the same size and direction.

I find nothing intuitive about sign-and-magnitude: we humans kind-of use something like it, but struggle with it in everyday life, at least in Finnish we talk about negative temperatures with a specific term, and use terms like increase/decrease and get confused whether the actual temperature is going up or down. I would dare to say a significant % of people, in the lower end of IQ bell curve, struggle with the whole concept of negative numbers, and trying to put them in order (ask "which is bigger, -42 or -43", and you won't get 100% the same answer). But if we have systems where negative numbers are not needed (i.e., with enough offset), this is easier. For example, with Fahrenheit, you need negative numbers much more rarely than positive numbers.

Two's complement is basically nothing else than a fixed offset with wrapping. You just don't have a separate concept of "negative numbers" needing special/manual handling. This is why it's easier for machine, and it would be easier for human, too, if we started from scratch without traditional package we carry.
« Last Edit: June 18, 2022, 10:26:07 am by Siwastaja »
 
The following users thanked this post: Nominal Animal

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4035
  • Country: nz
Re: New C23 working draft
« Reply #65 on: June 18, 2022, 10:35:05 am »
Basically all integer hardware since 1970ish.
So much so that on the 6502 one needed to explicitly set the carry flag before subtractions (and clear it before addition, but that's normal).

I'm quite convinced  that addition was implemented as:
   Accumulator + operand + Carry bit
(as discussed in other posts, this works beautifully for signed and unsigned maths), and subtraction in the same way, simply flipping the bits of the operand:
   Accumulator + ~operand + Carry bit
The ~operand + Carry(1) is simply -operand.
In this way an extra adder to perform the negation, or a different circuit to perform subtraction, was spared.

There's nothing to be convinced of, that's exactly how it works.

That's how it works on everything -- just many CPUs have an XOR on the path between the carry flag and the adder, and between the carry out and the flags registers, to invert the carry if it's a subtract.

But the 6502 is not the only ISA where you SEC before a subtraction. ARM is the same. It's just that on ARM there are both SUB and SBC instructions so you don't see it unless you specifically look at the carry flag at the end of a multi-precision operation. If you subtracted the LSBs with SBC instead of SUB then you'd have to set the carry flag at the start, same as 6502.

Other ISAs that are like the 6502 and ARM include:

- MSP430

- PA-RISC

- PIC

- Power/PowerPC

- System/360
 
The following users thanked this post: newbrain

Offline tellurium

  • Regular Contributor
  • *
  • Posts: 229
  • Country: ua
Re: New C23 working draft
« Reply #66 on: July 11, 2022, 12:32:09 am »
What I personally missed in libc, is interfacing with *printf* family of functions. FILE is an opaque object, there is no standard API to make a custom FILE. I'd prefer to have a lower level printf API like this:

Code: [Select]
int xprintf(void (*x)(char, void *), void *param, const char *fmt, ...);
int vxprintf(void (*x)(char, void *), void *param, const char *fmt, va_list ap);

Where x(char, void *param) is a generic putchar-like function that outputs a given character, void *param is a user-specified pointer.

Also, printf specifiers for hex, base64, and json-string-escape formatting would be nice. Or maybe some way of specifying custom format specifier, like '%J' that expects a custom formatting function pointer.
Open source embedded network library https://mongoose.ws
TCP/IP stack + TLS1.3 + HTTP/WebSocket/MQTT in a single file
 
The following users thanked this post: Siwastaja


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf