lainchan / λ

C hacks thread.

Anonymous · 2015-03-25 21:00
Post some cool tricks in C or Makefiles
Anonymous · 2015-03-27 00:00
i had this clever C makro that allowed me to define inline functions in versions of c that don't have them. i lost it :(
Anonymous · 2015-04-24 05:57
x = 5; while (x → 0) { printf("%i\n", x); }
Anonymous · 2015-04-24 14:17
>>5617 for (int i = 10; 0 ←10;) { printf("%d", i); }
Anonymous · 2015-04-24 16:07
this is only semi-realted, but those are some really cool ways to completely destroy c++ compilers, and since some of them are using the preprocessor which is present in C too, some count as cool C tricks in my book http://codegolf.stackexchange.com/questions/1956/generate-the-longest-error-message-in-c >Create a file a.cpp with this content : #include __FILE__ p; >Compile as : g++ a.cpp >and get amazing 21300 lines error messages
Anonymous · 2015-04-24 20:24
X Macros are pretty cool I think. http://www.embedded.com/design/programming-languages-and-tools/4403953/C-language-coding-errors-with-X-macros-Part-1
Anonymous · 2015-04-26 23:08
>>5248 I'd like to request a "cool trick" related to C: How do you guys use search engines to find resources on a problem you're having with C, and not a slew of >C++, C#, Objective C, etc. recommendations that may or may not apply to C proper at all? Or, what do you use in lieu of your favorite search engine to get help?
Anonymous · 2015-04-27 19:12
>>5667 Stuff your query with boolean operators, e.g. NOT. <your query> NOT C++ NOT plusplus NOT Sharp NOT Objective-C.
Anonymous · 2015-04-28 08:32
>>5620 $ gcc bwuh.c -o bwuh -std=c99 bwuh.c: In function ‘main’: bwuh.c:4:25: error: lvalue required as decrement operand for (int i = 10; 0 ← 10;)
Anonymous · 2015-05-07 18:15
Not much of a trick but good for tripping up people with a shallow understanding of the language. int a[6] = { 1,2,3,4,5,6}; printf("%d\n", 4[a] ) ;
Anonymous · 2015-05-09 10:22
Deal with boundary conditions such as circular buffers with the modulus operator instead of if-else statements. int buf_size = 10; int buf[buf_size]; int buf_next = 0; int i; for (i = 0; i < 1000; i++) { buf[buf_next++] = i; buf_next %= buf_size; printf("%d -> %d\n", buf_next, buf[buf_next]); }
Anonymous · 2015-05-10 18:47
Something to watch out for when reviewing code, especially the second one. /* Realloc can act like malloc. */ p = realloc(NULL, 10); /* And free. */ realloc(p, 0);[/code]
Anonymous · 2015-05-10 18:48
Something to watch out for when reviewing code, especially the second one. /* Realloc can act like malloc. */ p = realloc(NULL, 10); /* And free. */ realloc(p, 0);
Anonymous · 2015-05-13 00:33
>>5617 Nigga this just doesn't work.
Anonymous · 2015-05-13 01:10
All for parameters are optional [code]for(;;) puts ("infinite loop!");
Anonymous · 2015-05-13 02:15
>>5698 The website fuarrrks it up. < –
Anonymous · 2015-05-25 17:35
Instead of creating a new thread I think I'll post here. Currently I'm working myself throught 'The C Programming Language' and got to the part with getchar() and stuff. One exercise was verifying wether c = (getchar() != EOF); was 1 or 0. int c; c = (getchar() != EOF); putchar(c); printf("\n"); So, when it's waiting for my input I have 2 scenarios. 1. I enter anything but EOF (ctrl + d) and i get something that looks like a unicode box thing: 00 01 Is that the 1 I'm searching for? 2. I enter EOF and I get a blank line my question is: Is that what I'm looking for? I think yes but it is really anticlimatic or well atleast not the output I have expected. Especially that Unicode box thingy
Anonymous · 2015-05-25 18:30
>>6216 You're printing out the unicode character that corresponds to the value of the expression: getchar() != EOF That expression returns either 0 or 1, but not the character '0' or '1'. You're printing out the unicode "start of heading" character and the null character. See http://unicode-table.com/en/ Use printf("%d", c); instead of putchar(c);
Anonymous · 2015-05-26 12:36
>>6219 Ah, I get it. Thanks
Anonymous · 2015-05-27 07:14
>>5248 This is pretty cool: http://www.cs.rit.edu/~ats/books/ooc.pdf
Anonymous · 2015-05-27 17:42
Here's a few neat ones: lvalue ternary int a, b; (a > 10? a : b) = a * b; array tricks: // i[x] == *(i + x) == *(x + i) == x[i] 128[i] == i[128] // true // true if strings are represented by same addr "lainchan"[2] == 'i' == 2["lainchan"] c flexible struct hack: typedef struct { int id; double data[1]; } TS; // … size_t const dataSize = 256; TS *ts = malloc(sizeof(TS) + (dataSize - 1)*sizeof(TS.data[0])); ts->data[128] = 1337.0; try this one on for size Present Day, Present Time! AHAHAHAHAHA!: main(){for(int n[]={3,1,2,0,4},i=0;i<5;i++)printf((char*)&(i[n][((int*)"an \0lai\0nch\0hi \0:D\n")]));} I have more tricks if you want them :)
Anonymous · 2015-05-28 03:11
>>5884 Why would anyone do that
Anonymous · 2015-06-14 18:41
>>6009 It does. The arrow is minus-minus-right_waka; here is a complete snippet of code that compiles with gcc: http://pastebin.com/DW4DanRx lit >>6016 I assumed it was the same as mine; that is, left_waka-minus-minus. That definitely doesn't compile. If there's only one minus, is compiles but doesn't do anything useful. What exactly are you trying to get at?
Anonymous · 2015-06-14 19:02
http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man9/style.9?query=style&sec=9 && http://www.openbsd.org/lyrics.html#54
Anonymous · 2015-06-19 01:44
>or Makefiles Here's one I stole from cmus (who stole it from Linux). ifeq ($(verbose),y) quiet = else quiet = quiet_ endif cmd = @$(if $($(quiet)cmd_$(1)),echo ' $(call $(quiet)cmd_$(1),$(2))' &&) $(call cmd_$(1),$(2)) quiet_cmd_cc = CC $@ cmd_cc = $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $< quiet_cmd_ld = LD $@ cmd_ld = $(LD) $(LDFLAGS) -o $@ $^ $(1) %.o: %.c $(call cmd,cc) foobar: foo.o bar.o $(call cmd,ld,-lm) This produces prettier output (unless you set verbose=y on the command line): CC foo.o CC bar.o LD foobar This is what I use to automatically generate prerequisites ($(objects) is a list of .o files): dependencies = $(addprefix ., $(addsuffix .d, $(basename $(objects)))) quiet_cmd_dep = DEP $@ cmd_dep = echo "$@ `$(CC) $(CFLAGS) -MM $(CPPFLAGS) $<`" > $@ .%.d: %.c $(call cmd,dep) ifneq ($(dependencies),) -include $(dependencies) endif All of this goes in lib.mk, which is included by the makefile after defining $(objects), etc.
Anonymous · 2015-06-19 10:17
>>6278 (a > 10? a : b) = a * b; In which compiler is that supposed to work?
Anonymous · 2015-06-20 01:19
yuuko posted this in lainchan irc last night 00:23:14 <@yuuko> darkengine: https://kurofuku.me/u/cons.c #include <stdio.h> typedef struct cell cell; struct cell { char *s; cell *next; }; #define cons(x, y) (cell[]) {{x, y}} int main() { cell *list = cons("this", cons("is", cons("a", cons("compile-time", cons("linked", cons("list", NULL)))))), *l = list; do { puts(l->s); } while (l = l->next); }
Anonymous · 2015-06-21 01:17
This thread is great. Where do you learn this stuff?
Anonymous · 2015-08-15 04:21
This isn't solely the domain of C, but there is a new genre of music called bytebeat. /* Play it like this: ./crowd | aplay */ main(t){for(;;t++)putchar(((t<<1)^((t<<1)+(t>>7)&t>>12))|t>>(4-(1^7&(t>>19)))|t>>7);} http://canonical.org/~kragen/bytebeat/
Anonymous · 2015-08-15 11:40
Sort of related. A compiler, implements most of K&R C, can compile itself, generates i386 linux executables. The source code is 617 lines, 4748 bytes in total. When compiling it pass -m32 to gcc if you are on a 64 bit box. Homepage: http://bellard.org/otcc/
Anonymous · 2015-08-15 15:10
>>8560 http://wurstcaptures.untergrund.net/music/ >>6860 pain, internet, friends, more pain i'd say? >>6809 i'm a little confused by this too $ gcc lvalue-test.c -o lvalue-test lvalue-test.c: In function ‘main’: lvalue-test.c:6:19: error: lvalue required as left operand of assignment (a > 10? a : b) = a * b;
Anonymous · 2015-08-15 15:15
>>6291 you don't. also they failed to post explanation which is the interesting part foo[1] is the same as *(foo+1) 1[foo] is the same as *(1+foo)
Anonymous · 2015-08-19 15:01
>>5946 It can do those things but people who use it that way should be sentenced do death.
Anonymous · 2015-08-19 15:38
>>8647 I'm not an experienced C programmer, but how is that bad? It seems to be a very useful application of the function that removes the need for free and malloc. It's the same thing with printf, which isn't needed when you can simply use fprintf.
Anonymous · 2015-08-19 20:25
>>6278 >I have more tricks if you want them :) sure, please go ahead. >// true if strings are represented by same addr "lainchan"[2] == 'i' == 2["lainchan"] why do is the strings being the same address a requirement?
Anonymous · 2015-08-19 20:26
>>6278 s/do //
Anonymous · 2015-09-03 21:54
>>8578 Heh, I knew this trick for a while but never realized that that's why it works. Neat.
Anonymous · 2015-09-04 03:48
>>8653 A[I] == value at address (A+I) I[A] == value at address (I+A) Only if the strings are at same address A+I = I+A
Anonymous · 2015-09-04 04:52
Can I use this as a C general? Is openbsd source code good to use for reading "quality code" or are there better options?
Anonymous · 2015-09-04 05:29
>>9080 >Can I use this as a C general? This is pretty much the C general already. >Is openbsd source code good to use for reading "quality code" or are there better options? GNU source is pretty good and can be a nice way to learn some nice tricks and techniques, like how GNU true is also GNU false. On the other hand, OpenBSD does have very good documentation. Both rely on some nonstandard behavior or custom libraries for some of what they do.
Anonymous · 2015-09-10 14:31
>>5667 OCD Pirate's collection of C OCD Pirate's collection of C++
Anonymous · 2015-09-10 16:05
>>9074 You are comparing what is stored at offsets relative to thei the strings' beginnings, not the addresses of the strings. If the strings store the same char at the indexed positions, you will extract the same character in both cases, in this case, 'i'. The statement is false for other reasons though... But "\x03\x02\x01\x00"[2] == '\x01' == 2["\x03\x02\x01\x00"] is true!
Anonymous · 2015-09-16 21:50
>>8648 It's sorta "principle of least astonishment" and "programs should be written to be read by programmers and incidentally run by machines". If I have to maintain code written by some smartass that uses these kind of clever tricks, (s)he better have a good reason to write it like this, which, outside of maybe embedded, I cannot think of.
Anonymous · 2015-09-21 22:22
https://graphics.stanford.edu/~seander/bithacks.html this webpage is full of C wizard fuarrrkeries
Anonymous · 2015-09-22 01:29
>>6638 >http://pastebin.com/DW4DanRx lit >while (x --> 0) >while ((x--) > 0) Does this really count as a trick?
Anonymous · 2015-09-22 02:37
Speaking of hacks, is there a way tell GCC to dereference pointers automatically and treat the . operator as "(*(*(*...)))." where applicable? GDB has no problem doing this.
Anonymous · 2015-11-24 04:02
>>9672 That sounds like a job for m4.
Anonymous · 2015-11-24 06:36
a sick Makefile trick sudo apt install cmake
Anonymous · 2015-11-24 09:29
>>5617 >>5620 That arrow sign, I haven't seen it in any book on C. Is it shorthand for somehting?
Anonymous · 2015-11-24 10:05
>>12333 Like a C compiler, the site aggressively modified the final post. It is --> and <--.
Anonymous · 2015-11-24 16:26
Q: Why is it called C? A: Because "This won't work in neihther C++ nor C#. See, I told you so!"
Anonymous · 2015-11-26 06:21
>>12338 Q: Why is it called C++? A: You take C, add to it, and use the old one.
Anonymous · 2015-11-26 15:01
>>12335 Isn't i --> 0 the same as i-- >0?
Anonymous · 2015-11-26 17:56
>>12378 Yes, to the compiler