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