NHacker Next
  • new
  • past
  • show
  • ask
  • show
  • jobs
  • submit
Side-Effectful Expressions in C (2023) (blog.xoria.org)
commandlinefan 1 days ago [-]
Maybe I'm just Stockholm syndrome-d into the C programming language, but none of the examples here are terribly compelling to me - I love articles about C's weirdness, but I don't really think his before and after comparisons make a case for a replacement for C.
up2isomorphism 24 hours ago [-]
Yeah, just because you can grab from your refrigerator a piece of raw meat and put it in a cup of milk in 10 secs and it tastes bad doesn’t mean the refrigerator should be blamed because of this.
volemo 22 hours ago [-]
Yeah, but if the refrigerator is built in a way that makes it very easy to grab some refrigerant when you want to pour yourself a glass of milk (to the point that one has to be careful and skilled to safely drink milk), maybe we should get a new refrigerator.
teo_zero 13 hours ago [-]
It might sound easy to fix just a little detail that disturbs you and keep the rest as it is, but it's rarely feasible.

If we ban side effects from expressions, we must change the "for" syntax too, because the third "argument" currently is an expression. It should be a statement instead. Let's see...

  for (int i=0; i<n; ++i) // old
  for (int i=0; i<n; i+=1;) // new
What about the typical 2-variable loop?

  for (int i=0,j=n; i<j; ++i,--j) // old
  for (int i=0,j=n; i<j; {i+=1;j-=1;}) // maybe?
Or we simply forbid all this and force the increment and decrement in the body:

  for (int i=0,j=n; i<j; ;) {
    ...
    i+=1;
    j-=1;
  }
This is throwing the baby out with the bathwater!

And finally, if the third argument is a statement, would a break or continue be accepted there as well? A nested for? Sure, these are examples of abusing the syntax, but so is using x and ++x in the same expression.

My conclusion is that some constructs are so powerful that they can both simplify our code and make it unreadable. The choice how to use them is ours.

amavect 4 hours ago [-]
The author agrees with you. In the final paragraph, the author says that they allow ++ and -- when not using the value, as such use poses no harm.

Also, you can use a comma with += and -=,

  for (int i=0, j=n; i<j; i+=1, j-=1)
but keep in mind the decrement must usually happen before the loop body (post-increment reverses to pre-decrement).

  for (int i=0, j=n; i<j; i+=1) { j-=1; ... }
  for (int i=0, j=n; i<j; i++) { j--; ... }
amavect 22 hours ago [-]
For fun, my attempt to rewrite the functions. Eliminate ++ and pointer arithmetic by introducing a counter. Obviously less terse.

  void *my_memcpy(void *dst, const void *src, size_t n)
  {
   const uint8_t *s = src;
   uint8_t *d = dst;
   for (size_t i = 0; i < n; i += 1) d[i] = s[i];
   return dst;
  }

  int powi(int x, int y)
  {
   int result = 1;
   for (int i = 0; i < y; i += 1) result *= x;
   return result;
  }
For itoa, I experiment with the comma operator to show the post-increment on the same line, but visibly after. I also move the negation sign block to the absolute value block.

  void itoa(int n, char s[])
  {
   int i = 0;
   if (n < 0){
    n = -n;
    s[0] = '-', s += 1; // exclude from reverse
   }
   do{
    s[i] = n % 10 + '0', i += 1;
    n /= 10;
   }while(n > 0);
   s[i] = '\0';
   // reverse
   for(int j = 0, hi = i / 2; j < hi; j += 1) {
    i -= 1;
    char swap = s[j];
    s[j] = s[i];
    s[i] = swap;
   }
  }
Test code:

  #include <stdio.h>
  #include <stdint.h>
  // insert functions
  int main(void){
   char src[] = "hello";
   char dst[10];
   my_memcpy(dst, src, sizeof(src));
   printf("%s == hello\n", dst);
   printf("%d == 27\n", powi(3,3));
   itoa(-12345, dst);
   printf("%s == -12345\n", dst);
   itoa(0, dst);
   printf("%s == 0\n", dst);
  }
andrewla 1 days ago [-]
Really this is mainly about the ++ and -- operators. I think Go made the right call here and allows these only as statements, not as expressions. I will basically never use these in code I write and will remove it from code I maintain or review; the only value add is compactness which is very rarely a goal.

The other side effect expression here is the equals operator; once again, this should not be an expression but should just be a statement. Once again this is used (intentionally) mainly for compactness and unintentionally used to create messy bugs. I do find the "yoda" style checks to be aesthetically unpleasing so I'm party of the problem here.

Maybe it's time to add `-Wno-crement-expressions` and `-Wno-assignment-expressions`. `-Wparentheses` gets you part of the way to the second but even the legitimate uses are ugly to my eye.

1 days ago [-]
HackerThemAll 22 hours ago [-]
> Maybe it's time to add `-Wno-crement-expressions` and `-Wno-assignment-expressions`. `-Wparentheses`

Aren't there static analyzers in widespread use that would catch these?

nadavdebi 1 days ago [-]
[flagged]
Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact
Rendered at 19:48:17 GMT+0000 (Coordinated Universal Time) with Vercel.