Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Side-Effectful Expressions in C (2023) (xoria.org)
34 points by surprisetalk 12 hours ago | hide | past | favorite | 6 comments
 help



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.

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.

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.

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);
  }

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.


> 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?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: