3 ms·
> const float f = *data++; cursed code. people might say "oh that's normal idiomatic C", I don't care. I am glad Go does not allow code like this
by 38 2y ago
> const float f = *data++;
cursed code. people might say "oh that's normal idiomatic C", I don't care. I am glad Go does not allow code like this
- trealira 2y agoThe C language seems to really like reading/writing data and then modifying it, or modifying data and then reading/writing it, which can make for some dense one-liners full of side-effects. The pre- and post- increment and decrement operators, and the fact that assignments are expressions, seem to encourage it - especially in combination with the short-circuiting boolean operators. In old C, they would write code like the function below. This is based on a function from The C Programming Language, and it makes the assumption that bufp points to a buffer that's at least one byte long. /* Read a line into a lim-sized buffer at bufp, returning strlen(bufp) */ int getline(char *bufp, int lim) { int c; char *p = bufp; while (--lim > 0 && (c = getchar()) != EOF && (*p++ = c) != '\n') ; *p = '\0'; return p - bufp; } But nowadays, in modern C code, I think most people don't write such terse code. I guess it's because the only people who still code in C are those who have no choice, and so they prefer clarity over compactness.
- 38 2y agoI think the one liner was supposed to show how short and simple programming can be, but I think it ultimately has the opposite effect. It's basically a showcase of terrible programming idioms that you should never use.
- trealira 2y agoTo be fair, that's not actually in the book. I said it was based on a function from that book, but below is the version they actually write in the book; I apologize for unintentionally misleading you. I wrote the above function myself (based on this one below) to showcase the type of style I'm talking about. /* getline: read a line into s, return length */ int getline(char s[], int lim) { int c, i; for (i=O; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i) s[i] = c; if (c == '\n') { s[i] = c; ++i; } s[i] = '\0'; return i; } They specifically don't use pointer arithmetic or the post-increment operator, because at that point in the book, they haven't introduced those yet. However, that function I wrote isn't far off from the real Unix V7 version of fgets [0], which is a similar function to getline: char * fgets(s, n, iop) char *s; register FILE *iop; { register c; register char *cs; cs = s; while (--n>0 && (c = getc(iop))>=0) { *cs++ = c; if (c=='\n') break; } if (c<0 && cs==s) return(NULL); *cs++ = '\0'; return(s); } Like I said, the creators and first users of C seemed to really like expressions with side-effects, pointer arithmetic, and while-loops with empty bodies (though fgets doesn't have that). It's interesting how Go is different in this regard, considering Ken Thompson was a co-creator of both languages. [0]: https://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/libc/stdio/fgets.c https://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/lib...