Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-8081-120121-160161-

C programming tricks

Name: Anonymous 2007-09-15 22:06 ID:WCtjqT0N

While programming optimization that makes ones' code completely unreadable is often a bad thing, there are places for it, like that one inner loop of your code that takes up 98% of the program's running time.

What are you tricks for improving performance in C, other than the obvious inline assembly or the like?

Name: Anonymous 2007-09-15 22:17 ID:iUkfViGA

XML

Name: Anonymous 2007-09-15 22:23 ID:WCtjqT0N

>>2

Fortunately I'm not looking for buzzword compliance ;)

Name: Anonymous 2007-09-15 22:27 ID:FpeG2A+u

gprof

Name: Anonymous 2007-09-15 22:28 ID:/cLfUcQO

Don't use C, Use BBCode

Name: Anonymous 2007-09-15 22:56 ID:WCtjqT0N

>>4

I already have a make fprofiled option, it gives a few % boost.  I'm referring to tricks like replacing if statements with branchless code hacks, etc.

Name: Anonymous 2007-09-15 23:24 ID:1CE+B+uj


if (--booleanVariable) {
   // code if boolean is true
} else {
   code if false
}


the

Name: Anonymous 2007-09-15 23:42 ID:yYLsDmsL

I presume everyone here knows of Duff's Device.

Name: Anonymous 2007-09-15 23:49 ID:Yf6Se59C

>>1
the obvious inline assembly
Noob detected.

OMG ASSEMBLY MAKES EVERYTHING FASTER LLOLOOLLLOPLO

Name: Anonymous 2007-09-15 23:50 ID:Heaven


switch (count % 8)  /* count > 0 assumed */
 {
   case 0:        do {  *to = *from++;
   case 7:              *to = *from++;
   case 6:              *to = *from++;
   case 5:              *to = *from++;
   case 4:              *to = *from++;
   case 3:              *to = *from++;
   case 2:              *to = *from++;
   case 1:              *to = *from++;
                     } while ((count -= 8) > 0);
 }

Name: Anonymous 2007-09-15 23:52 ID:Heaven

Swap two variables without temporary variable

*x ^= *y;*y ^= *x;*x ^= *y;

Name: Anonymous 2007-09-16 0:09 ID:Heaven

AHAHAHAHAHAHAHAHAHAHAHAHAHAHA
FUCKING CLUELESS CPU NOOBS

>>10
YOU BETTER BE JOKING NIGGER. THAT AIN'T OPTIMIZATION AT ALL.
IT IS SHIT CODE

>>11

char **x, **y;

YOU FAIL, FURTHERMORE, http://en.wikipedia.org/wiki/Xor_swap#The_XCHG_instruction
These compilers are more likely to recognize and optimize a conventional (temporary-based) swap than to recognize the high-level language statements that correspond to a XOR swap.
FUCKING NOOB
FUCK

Name: Anonymous 2007-09-16 0:14 ID:O8wP71a+

>>12
OKAY YOU FUQIN ANGERED AN EXPERT PROGRAMMER
GODFUCKIGNDAMN
FIRST OF ALL, YOU DONT FUQIN KNOW WHAT A MAN PAGE IS
SECONDLY, THIS IS /prog/ DO NOT DEMAND USEFUL ANSWERS THE WAY YOU WANT THEM TO BE
THIRDLY PROGRAMMING IS ALL ABOUT PHILOSOPHY AND ``ABSTRACT BULLSHITE'' THAT YOU WILL NEVER COMPREHEND
AND FUQIN LASTLY, FUCK OFF WITH YOUR BULLSHYT
EVERYTHING HAS ALREADY BEEN ANSWERED IN
>>5,10,11

Name: Anonymous 2007-09-16 0:27 ID:Sy2QIfmT

Declare variables as static so the CPU doesnt have to set aside memory on the stack in each function call. Just be sure to reset it each time.

int foo(int a)
{
    static int variable;
// ....
    variable = 0;
}

Name: Anonymous 2007-09-16 0:29 ID:Sy2QIfmT

Another cool one I learnt in high school, if you're passing in aggregate types, its better to pass it in as reference so it doesn't have to get copied

int foo (struct foobar* myStruct)
{
    return 1;
}

struct foobar a;
foo(&a)

Name: Anonymous 2007-09-16 0:31 ID:Sy2QIfmT

Of course, as >>12 was hinting at, if you have critical code in a tight loop, it's better to use the inline assembly, which is guaranteed to make your code run faster.

for (int i=0; i<100; ++i)
__asm { mov rax, [i]
        xor rax, rax }


Name: Anonymous 2007-09-16 0:51 ID:3HUNABGp

>>12
YOU FAIL, FURTHERMORE, http://en.wikipedia.org/wiki/Xor_swap#The_XCHG_instruction

You further fail, for pointing out his fail, and not knowing that that usage is undefined in the first place.

Name: Anonymous 2007-09-16 2:12 ID:C1D+ypEB

>>9

Noob?  There's hundreds of kilobytes of assembly code in the program I'm working on, and it all has a very specific purpose (SIMD instructions for SAD/SATD/SSD/SSIM operations on large numbers of pixels).  Obviously, assembly for something that can't be SIMD-optimized is *usually* a waste of time.

Thanks for the suggestions, for those of you that made them :)

Name: Anonymous 2007-09-16 2:56 ID:S8KoCl51

>>16

Way to go n00b -- inline assembly is a great way to disable all compiler optimizations in the surrounding code.

Name: Anonymous 2007-09-16 3:11 ID:C1D+ypEB

>>19

I think he was kidding.  Better said, I hope he was...

Name: Anonymous 2007-09-16 3:12 ID:Heaven

>>17
and not knowing that that usage is undefined in the first place.
YOU FUCKING WANKER
I'LL JUST QUOTE ME:
char **x, **y;
YOU RETARDED MONKEYFUCK WANKER
SAGE FOR GREATER JUSTICE

Name: Anonymous 2007-09-16 4:05 ID:K21wDPMU

I just buy faster hardware?

Name: Anonymous 2007-09-16 4:14 ID:Krd3dptm

>>22 has been asleep the past four years.

Name: Anonymous 2007-09-16 4:20 ID:KYjd1u+e

i dun get it >>23-san!

Name: Anonymous 2007-09-16 4:20 ID:Heaven

>>23[rem]-san
test

Name: Anonymous 2007-09-16 4:21 ID:Heaven

eh
>>23[rem][rem]-san
test

Name: Anonymous 2007-09-16 4:21 ID:Heaven

eh
>>23-san
test

Name: Anonymous 2007-09-16 4:27 ID:C1D+ypEB

>>22

The problem with this is that faster hardware gives everyone an edge.  When you're competing against other video encoders from other companies and organizations, what matters is your speed and/or quality edge over theirs.  Since faster hardware speeds up everyone, it doesn't help one compete :)

Name: Anonymous 2007-09-16 5:07 ID:GBm9iKmz

>>1
OMG OPTIMIZED!

Let the compiler to the good job. It's bad enough already you're doing C; no need to make your life more miserable when there are several awesome OMG OPTIMIZED C compilers. Just compile with -momg-optimized.

Name: Anonymous 2007-09-16 5:15 ID:6UUG73P+

My trick is to express my intent to the C compiler in such a way that communicates my intent to any humans that might be reading (including myself in two weeks' time). Compilers are pretty fuckin' good these days, there's no need to do strength reduction by hand since you can always compile with at least -O1 on today's hardware...

But anyway, yeah, if you want to know whether an integer is odd, use (x % 2) == 1 rather than the implicit boolean equivalent. It's more readable and the compiler produces an equivalent sequence of instructions anyway.

Name: Anonymous 2007-09-16 5:17 ID:Heaven

>>12
XOR swap (a ^= b ^= a) produces undefined results due to a modify twice condition. You fai~l it...

Name: Anonymous 2007-09-16 5:33 ID:Heaven

>>31
FUCK YOU FUCKING FAG
XOR SWAP TWO SIGNED INTEGERS AND TELL ME WHAT HAPPENDS YOU FUCKING PIECE OF SHIT
UNDEFINED BEHAVIOR TOO
I KNOW ALL OF THIS
I LIVE INSIDE STANDARDS

Name: Anonymous 2007-09-16 5:35 ID:S8KoCl51

apply the ``const'' qualifier where appropriate -- the compiler will moan in satisfaction when it is able to engage more optimizations as it spurts out code

Name: Anonymous 2007-09-16 5:45 ID:M+Nq55G4

>>32
THIS IS /prog/
YOUR STANDARDS DO NOT APPLY HERE

Name: Anonymous 2007-09-16 6:01 ID:Sy2QIfmT

>>33
Yes, passing const references to objects really pleases the compiler like Lady Godiva.

Also, if you ever need to initialize an array to all zeros, use memset(array, 0, sizeof(array));
Some compilers can detect this call and replace it with a single rep stosd instruction (given array length which lies on 4 byte boundary)

Name: Anonymous 2007-09-16 6:49 ID:H7BcAxtZ

>>21
Even with **x, and **y, it's undefined.

Name: Anonymous 2007-09-16 7:04 ID:Heaven

>>32
(a ^= b ^= a)

The above has no sequence points, they get modified multiple times, the result of which is undefined.  Variables cannot be modified more than once between sequence points according to the C standard.

Relevant C standard text:
J.2 Undefined Behavior
Between two sequence points, an object is modified more than
once, or is modified and the prior value is read other than to
determine the value to be stored (6.5).

So apparently you don't live inside standards.  Just because it works on a few compilers doesn't mean it works on them all.

>>34
This is about C, which is 100% defined by the standard.  There are no other authoritative sources.  Except maybe.. "Learning C for DUMMIES!"

Name: Anonymous 2007-09-16 10:02 ID:xXOet/pd

for(int(*f[])(int)={&toupper,&tolower};*s=f[random()%2](*s++););

Name: Anonymous 2007-09-16 10:08 ID:H7BcAxtZ

>>38
and... syntax error

Name: Anonymous 2007-09-16 10:09 ID:Heaven

>>38
*s=f[rand() & 1](*s++);

random() does not belong to the std c and % is slow and ugly.

Name: Anonymous 2007-09-16 10:09 ID:Heaven

>>38
shorter:
for(;*s=(random()%2?toupper:tolower)(*s++););

>>38 would be nicer if you could just use a literal array instead of having to make a pointer to an array of function pointers. but you can't do that in c.

Name: Anonymous 2007-09-16 10:35 ID:Heaven

>>40
low bits of values returned by rand() aren't very random so if you're going to use rand() instead you shouldn't use just the lowest bit.
& is uglier than %, and just as slow.
if you really want speed, rand()/(INT_MAX/2) would be faster and would help with the problem of the low bits not being very random.
improved version:
for(;*s=(rand()/(INT_MAX/2)?toupper:tolower)(*s++););

Name: Anonymous 2007-09-16 11:14 ID:Heaven

Um, & is in no way shape or form as slow as modulus.  Modulus puts quite a bit more work on the cpu, comparatively, I also don't see where you're getting your speed gains either.  

Name: Anonymous 2007-09-16 11:28 ID:Heaven

>>42
division is pretty slow, while & is as fast as it can get
you fail

Name: Anonymous 2007-09-16 11:36 ID:Rc6EEZiP

>>43-44
BENCHMARKS MOTHERFUCKERS, DO YOU USE THEM?

Name: Anonymous 2007-09-16 11:55 ID:H9kKB81D

>>44
protip: let the compiler do the work for you, -funroll-loops

Name: Anonymous 2007-09-16 15:23 ID:xXOet/pd

>>44
integer division is pretty damn fast.
rand()&1 is a lot less random than rand()/(INT_MAX/2).

>>43
$ cat test1.c
#include <stdio.h>
#include <stdlib.h>

int main(){
 for(int i=0;++i<1000000;printf("%d\n",rand()%2));
 return 0;
}
$ cat test2.c
#include <stdio.h>
#include <stdlib.h>

int main(){
 for(int i=0;++i<1000000;printf("%d\n",rand()&1));
 return 0;
}
$ cat test3.c
$ cat test3.c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main(){
 for(int i=0;++i<1000000;printf("%d\n",rand()/(INT_MAX/2)));
 return 0;
}
$ gcc -std=c99 test1.c -o test1
$ gcc -std=c99 test2.c -o test2
$ gcc -O2 -std=c99 test3.c -o test3
$ time -h ./test1 > /dev/null
        0.73s real              0.63s user              0.00s sys
$ time -h ./test2 > /dev/null
        0.72s real              0.64s user              0.00s sys
$ time -h ./test3 > /dev/null
        0.72s real              0.63s user              0.00s sys

Name: Anonymous 2007-09-16 15:26 ID:Heaven

>>47
summary:
rand()%2 1000000 times: 1.36s
rand()&1 1000000 times: 1.36s
rand()/(INT_MAX/2) 1000000 times: 1.35s

Name: Anonymous 2007-09-16 15:54 ID:CAdtAOry

>>47
Nice benchmark for the printf function.

Name: Anonymous 2007-09-16 16:03 ID:Heaven

>>49
ok let's see you write a benchmark that shows how much slower %2 is than &1

Name: Anonymous 2007-09-16 16:04 ID:SDT0AFSf

fucking just download the ebook called "deep C secrets" i'm sure it'll help u in whatever C related programming course (besides the introductory bullshit) you're doing.

Name: Anonymous 2007-09-16 16:15 ID:SDT0AFSf

I think the codecomments forums have an optimization thread thats like 10 pages long at least - check that shit out as well.

Name: Anonymous 2007-09-16 16:19 ID:K21wDPMU

>>28
Oh... business. gb2/managing

Name: Anonymous 2007-09-16 17:08 ID:Krd3dptm

>>50
I'm not >>49, but I agree with him, although the results come out the same. printf() is extraordinarily slow, pushing any interesting results into the noise. Same can be said for rand(), although it's not as bad as printf(). Using time from the shell includes the startup time, so it reduces accuracy.

Here's the results I get with what I wrote:

C:\Devel\src>gcc t.c -std=c99 -o t.exe

C:\Devel\src>t
& 1: 15515 ticks
% 2: 25168 ticks

C:\Devel\src>gcc t.c -std=c99 -o t.exe -O2

C:\Devel\src>t
& 1: 2658 ticks
% 2: 2649 ticks


And here's the code. Note that it's still far from ideal, but at least the interesting bits are completely vanishing into the margin of error:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <limits.h>

#define ITER 10

int main(void)
{
  int tmp;     // prevent certain optimizers from eliminating the loops
  int stub[2];
  clock_t start_time, avg_time;

  // timing for & 1
  start_time = clock();
  for(int i=0; i < ITER; i++) {
    for(int j=0; j < INT_MAX; j++) {
      tmp = stub[j & 1];    // cheaper than zOMG rand()
    }
  }
  avg_time = (clock() - start_time) / ITER;

  printf("& 1: %i ticks\n", avg_time);
 
  // timing for % 2
  start_time = clock();
  for(int i=0; i < ITER; i++) {
    for(int j=0; j < INT_MAX; j++) {
      tmp = stub[j % 2];
    }
  }
  avg_time = (clock() - start_time) / ITER;

  printf("%% 2: %i ticks\n", avg_time);

  return 0;
}


So, it's clear the result is the same after optimization. Modulus is slower, but the optimizer changes %2 to & 1.

Name: Anonymous 2007-09-16 17:09 ID:Heaven

s/are completely/are not completely/

Name: Anonymous 2007-09-16 17:28 ID:CAdtAOry

>>54
That's better. Now also calculate the standard deviation for those 10 runs and use the t-test to determine if they are significantly different.

Name: Anonymous 2007-09-16 17:29 ID:9ndnYabT

>>54
C:\Devel\src>gcc t.c -std=c99 -o t.exe
C:\Devel\src>gcc
C:[b]Devel[/b]\
Devel

Name: Anonymous 2007-09-16 17:32 ID:C1D+ypEB

>>47

Integer division is 20-40 clocks on most CPUs, and up to 80 on the Pentium 4... I don't feel like getting out my technical manuals for the exact numbers.

The reason its "fast" is because when you divide by a constant value, the compiler tends to optimize the division into magic number multplication/bitshifting, to avoid an actual IDIV.

Name: Anonymous 2007-09-16 17:33 ID:Krd3dptm

Devel
eve
V

I put on my cape and smiley mask.

Name: Anonymous 2007-09-16 18:40 ID:qb4uIYsD

1. Use fprintf ("fast printf") instead of printf.
2. ++i is faster than both i++ and i = i + 1.
3. void main(void) is faster than int main(void) or int main(int, char **) since no value needs to be returned to the OS.
4. Swapping with exclusive-or (a^=b^=a^=b swaps a and b) is faster than using a temporary. This works for all types (including structures), but not on all compilers. Some compilers may also give you a harmless warning.
5. Static storage duration objects are faster than automatic storage duration objects because the CPU doesn't have to set aside storage on the stack every time a function is called. Make your loop indexes global so that you can use them everywhere:
int i;
void func(void) { for (i = 0; i < 10; i++) ; /* ... */ }
void func2(void) { for (i = 0; i < 20; i++) ; /* ... */ }
/* ... */

6. Compilers often give more memory to arrays than you asked for. Here's how to check how big an array actually is (memset returns a null pointer if the size you passed to it is bigger than the size of the array you passed to it):
int arr[256];
size_t realsize;
for (realsize = 0; realsize <= SIZE_MAX; ++realsize)
        if (!memset(arr, 0, realsize)) break;
/* now you know that arr actually has realsize / sizeof (int) elements */

If you combine this with #5, your program will be faster in the long run (but this usually doesn't work for short programs).

Name: Anonymous 2007-09-16 18:55 ID:Sy2QIfmT

>>60
EXPERT TROLL

Name: Anonymous 2007-09-16 18:55 ID:H9kKB81D

>>60
I fuckken LOLd my ass off @ 1.

Name: Anonymous 2007-09-16 19:10 ID:Heaven

>>60
Now this is a quality troll.

Name: Anonymous 2007-09-16 19:35 ID:xXOet/pd

>>60 is too obviously a troll.
>>42 is much better.

Name: Anonymous 2007-09-16 19:39 ID:C1D+ypEB

>>60

LOL.  That was amusing.

Name: Anonymous 2007-09-16 21:30 ID:M+Nq55G4

>>60 is EXPERT QUALITY, except one thing:
2. ++i is faster than both i++ and i = i + 1.
This is actually quite true sometimes. In certain circumstances, a loop in GCC using while (++i <= j) will produce incl, cmpl, and jle instructions; whereas while (i++ < j) will result in movl, incl, cmpl, and jl. In this case, preincrementing shaves one full CPU instruction per loop iteration.

Name: Anonymous 2007-09-16 21:57 ID:Heaven

>>66
-O3

Name: Anonymous 2007-09-16 22:11 ID:0cfV6Q0I

>>60

1. Use fprintf ("fast printf") instead of printf.

No. Here's an EXPERT PROGRAMMER QUALITY optimization :
fwrite("string",sizeof(char),sizeof("string"),stdout);

Name: Anonymous 2007-09-16 22:22 ID:Krd3dptm

>>66
Anybody who writes a while loop like that deserves to get beaten with a bat though.

Same with >>47. Ugh, what kind of for loops are those?

Name: Anonymous 2007-09-16 22:23 ID:0cfV6Q0I

ALSO,

4. Swapping with exclusive-or (a^=b^=a^=b swaps a and b) is faster than using a temporary. This works for all types (including structures), but not on all compilers. Some compilers may also give you a harmless warning.


http://en.wikipedia.org/wiki/Xor_swap#The_XCHG_instruction

Name: Anonymous 2007-09-16 22:59 ID:xXOet/pd

Ugh, what kind of for loops are those?
simple ones.

for(int c;c;printf(++c?" %02x ":"\n",c=getchar()));

for(char*r=s;*s;*r=!s++)if(*s!=c)*r++=*s;

Name: Anonymous 2007-09-16 23:18 ID:I0ZdD5JI

gets(buf);

Name: Anonymous 2007-09-16 23:58 ID:Krd3dptm

>>71
Absolutely disgusting.

Name: Anonymous 2007-09-17 4:40 ID:T7H3/2/F

>>71
that is not simple, a simple loop is
for(i = 0; i < range; i++)

or

for(;;)

Name: Anonymous 2007-09-17 4:43 ID:gf4kBNCr

PROTIP: BREAK IS CONSIDERED HARMFUL FOR NON-EXCEPTIONAL CIRCUMSTANCES

Name: Anonymous 2007-09-17 5:43 ID:p/yux4n8

>>75
Protip: no, it saves nested IF blocks and repeated while/for conditions.

Name: Anonymous 2007-09-17 5:45 ID:Heaven

>>75
you fail, i've heard that a lot from college/uni teachers/profs, what's with that? Fuck them. fucking noobs.

Name: Anonymous 2007-09-17 6:12 ID:Qi/+7bcj

>>75 yea use goto instead

Name: Anonymous 2007-09-17 7:47 ID:gf4kBNCr

>>76
What is the use of a loop that doesn't check when to finish?
while(!finished)
  finished = true;

for(;;)
  if(cond)
   break;

I've seen cases where usage of break is more elegant than using vars and while. Such cases are exceptional.

>>77
Guess where the theory behind computer science comes from? Oh, that's right, it doesn't come from the people that formalized cs theory, it comes from EXPERT PROGRAMMERS

>>78
I love GOTO roughly like a noodly spaghetti code.

Name: Anonymous 2007-09-17 8:35 ID:2gLnFHF5

>>68
Uh, sizeof("String") is four, or however big pointers are on your machine.

Name: Anonymous 2007-09-17 8:42 ID:p/yux4n8

>>79
Moar like:
while (condition1) {
    ...code...
    if (OMG_DISASTROUS_CONDITION) {
        break;
    }
    ...code...
}


simpler, easier to read and less error-prone (due to no condition repeated) than:

while (condition1 && !OMG_DISASTROUS_CONDITION) {
    ...code...
    if (!OMG_DISASTROUS_CONDITION) {
        ...code that's actually at the same conceputal level than the other block but appears indented...
    }
} //}} is alright, but nicer if it can be avoided

Name: Anonymous 2007-09-17 9:04 ID:Heaven

>>80
incorrect.
"literal strings" are arrays of N length.

Name: Anonymous 2007-09-17 9:06 ID:nNPi4cfO

clearly, the EXPERT PROGRAMMER wouldn't use c in the first place.
better to use java, to produce ENTEPRISE LEVEL, fully scalable, reductible, end-user optimized professional applications.

Name: Anonymous 2007-09-17 9:16 ID:Heaven

oh shit the buzzwords

Name: Anonymous 2007-09-17 13:13 ID:9N6k+w8V

>>79

There are some good reasons to use break.  Here's an example from the program I'm working on:

            for( i = 1; i < 2 && CHECK_MVRANGE(bmx, bmy); i++ )
            {
                static const int mod6[8] = {5,0,1,2,3,4,5,0};
                const int odir = mod6[dir+1];
                COST_MV_X3_DIR( hex2[odir+0][0], hex2[odir+0][1],
                                hex2[odir+1][0], hex2[odir+1][1],
                                hex2[odir+2][0], hex2[odir+2][1],
                                costs );
                dir = -2;
                COPY2_IF_LT( bcost, costs[0], dir, odir-1 );
                COPY2_IF_LT( bcost, costs[1], dir, odir   );
                COPY2_IF_LT( bcost, costs[2], dir, odir+1 );
                if( dir == -2 )
                    break;
                bmx += hex2[dir+1][0];
                bmy += hex2[dir+1][1];
            }


Note how some code has to be run *after* the break statement, so it can't as easily be dumped into the for statement.

Name: Anonymous 2007-09-17 13:14 ID:9N6k+w8V

And note that "i < 2" should be "i < some larger number", that was just a copy paste from some code I was testing.

Name: Anonymous 2007-09-17 17:43 ID:2TXRzsFz

>>83

REAL expert programmers would use a common lisp like cmucl or sbcl and write (proclaim (optimize (speed 3)))




Name: Anonymous 2007-09-17 20:23 ID:VO7oeWyD

SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME SCHEME

Name: Anonymous 2007-12-29 20:42

:0

Name: Anonymous 2007-12-29 22:23

>>89
What the fuck is wrong with you, you little shit.

Name: Anonymous 2007-12-29 23:05

>>90
Where the fuck is your question mark?

Name: Anonymous 2007-12-29 23:06

>>14

Why is that?  Is it because adding 8 to (subtracting 8 from, depending on your architecture) your stack pointer is more expensive than adding/subtracting 4?

Name: Anonymous 2007-12-30 0:08

>>91

You don't understand >>90.

Name: Anonymous 2007-12-30 0:11

>>93
Not without proper punctuation I don't.

Name: Anonymous 2007-12-30 1:07

>>92
You're responding to a three-month-old troll.

Name: Anonymous 2007-12-30 3:11

>>95
You're responding to a one-hour-old response to a troll.

Name: Anonymous 2007-12-30 3:51

>>14,92,95,96
I loled

Name: Anonymous 2007-12-30 4:07

>>39
So that's... INVALID Perl code?

Name: Anonymous 2007-12-30 4:49

>>98
valid perl, invalid C.

Name: Anonymous 2007-12-30 5:43

1. Use fprintf ("fast printf") instead of printf.
2. ++i is faster than both i++ and i = i + 1.
3. void main(void) is faster than int main(void) or int main(int, char **) since no value needs to be returned to the OS.
4. Swapping with exclusive-or (a^=b^=a^=b swaps a and b) is faster than using a temporary. This works for all types (including structures), but not on all compilers. Some compilers may also give you a harmless warning.
5. Static storage duration objects are faster than automatic storage duration objects because the CPU doesn't have to set aside storage on the stack every time a function is called. Make your loop indexes global so that you can use them everywhere:
int i;
void func(void) { for (i = 0; i < 10; i++) ; /* ... */ }
void func2(void) { for (i = 0; i < 20; i++) ; /* ... */ }
/* ... */

6. Compilers often give more memory to arrays than you asked for. Here's how to check how big an array actually is (memset returns a null pointer if the size you passed to it is bigger than the size of the array you passed to it):
int arr[256];
size_t realsize;
for (realsize = 0; realsize <= SIZE_MAX; ++realsize)
        if (!memset(arr, 0, realsize)) break;
/* now you know that arr actually has realsize / sizeof (int) elements */

If you combine this with #5, your program will be faster in the long run (but this usually doesn't work for short programs).

Name: Anonymous 2007-12-30 6:01

>>100
i lold. hard.

Name: Anonymous 2007-12-30 6:07

Also remember the remark, that is "rm", tool in your UNIX shell.

Name: Anonymous 2007-12-30 6:59

are we talking compilation optimization or code execution? because i don't really care how fast the compile is, in my case i've so far only written applications that compile in a few seconds or less

so what tips do you have for optimizing executable code when you compile with gcc and link with ld to the bsd libc?

Name: Anonymous 2007-12-30 7:33

strip -R.data binary

Name: Anonymous 2007-12-30 13:50

>>102
Don't forget to use -fr, which means fold previous remarks you've made with the new ones. Otherwise you'll erase your old comments! For example:

$ rm -fr ~/ This is my home directory

... will attach the remark "This is my home directory" to ~/, leaving any previous remarks intact.

Also, to view remarks you've made previously, try the -v option:

$ rm -v ~/.Xauthority

Name: Anonymous 2007-12-30 14:16

CFLAGS JUST KICKED IN YO

Name: Anonymous 2007-12-30 14:36

>>105
lol'd

Name: Anonymous 2007-12-30 18:27

>>103
try building with gcc -O3 -s -funroll-loops -fomit-frame-pointer -ffast-math -fno-strength-reduce -fno-exceptions

Name: Anonymous 2007-12-31 9:01

Name: Anonymous 2008-01-08 9:03

>>100
6. Compilers often give more memory to arrays than you asked for. Here's how to check how big an array actually is (memset returns a null pointer if the size you passed to it is bigger than the size of the array you passed to it):
O HI I UPGRADED UR ALGORITHM!
#include <stdlib.h>
#include <stdio.h>
char* main() {
  char* DATA = malloc(4097);
  printf("%u\n", *(unsigned int*)(DATA - 4));
  return DATA; /* ONLY PUSSEYS FREE THERE MEMORT; LET THE DOS DO IT!!! */
}

Name: Anonymous 2008-01-08 10:56

>>11
But which is faster? Three XOR instructions or three MOV's using a temporary register?

Name: Anonymous 2008-01-08 11:38

>>111
The MOVs, as they have less true dependencies, and possibly won't occupy an ALU.

Name: Anonymous 2008-01-08 11:40

>>112
XORs require less CPU cycles.
fucking sage

Name: Anonymous 2008-01-08 11:46

>>110
ogod i lold'

Name: Anonymous 2008-01-08 12:05

Yeah, C really should have included a swap operator.

Name: Anonymous 2008-01-08 12:15

>>115
It's impossible moron.

Name: Anonymous 2008-01-08 12:19


#define iswap(x,y) (do uintptr_t __x=x,x=y,y=__x; while(0))
#define pswap(p,s) (do void *__p=p,p=s,s=__p; while(0))
#define fswap(f,g) (do long double __f=f,f=g,g=__f; while(0))

Name: Anonymous 2008-01-08 12:20

>>117
That looks NP-complete to me... or kind of like Perl... but I think parsing Perl is NP-complete.

Name: Anonymous 2008-01-08 17:45

>>116
No

Name: Anonymous 2008-01-08 17:54

Condoms full of razors

Name: Anonymous 2008-01-08 18:32

To exchange two variables in LISP without using a third variable:

(SETQ X (PROG2 0 Y (SETQ Y X)))

Name: Anonymous 2008-01-08 18:42

>>121
(psetq x y y x)

Name: Anonymous 2008-01-08 19:15

>>118
Yes, but parsing Sepples is NP-hard

Name: Anonymous 2008-01-08 19:46

Name: Anonymous 2008-01-08 19:52

>>124
Actually, it's invalid C.
It invokes undefined behavior in the assignment and calls a function that is not standard without providing declaration and definition. (the non-standard function is random btw)

let's see the assignment:
*s=f[random()%2](*s++);
As you might know, in such assignment the compiler is free to evaluate the RHS or the LHS first.
If LHS is evaluated first and then RHS what happends?
That's right motherfucker. Undefined behavior.
Fucking C fag, gtfo /prog/ and read SICP.

Name: Anonymous 2008-01-08 19:54

>>122
noob, >>121-san's code is from HAKMEM

Name: Anonymous 2008-01-08 20:16

>>125
More precisely:

6.5p2
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression.  Furthermore, the prior value shall be read only to determine the value to be stored.

In the expression *s=f[random()%2](*s++), s has its value modified and its prior value read to determine the new value:

*s=f[random()%2](*s++)
                  ^^^
but its prior value is also read elsewhere:
*s=f[random()%2](*s++)
 ^

which violates the second sentence of the quoted paragraph.

Name: Anonymous 2008-01-09 0:15

>>127
the way you interpret that second sentence, if(i++) would be invalid because i is modified and it's prior value is read for a purpose other than determining the value to be stored. this is obviously not what the authors of the standard intended.

Name: Anonymous 2008-01-09 3:33

>>125,128
It's random() anyway so the point is doug moot. But most compilers defer postfix ops until the whole expression has been evaluated (I only wish it was in the standard)

Here's a tricky bit of code that is valid but most people won't think so:

int i=0;
i++ && i++ || i++ && i++


What's the value of i after the above fragment executes?

Name: Anonymous 2008-01-09 5:27

>>129
2?

Name: Anonymous 2008-01-09 5:29

>>129
4

Name: Anonymous 2008-01-09 5:33

>>128
A clearer statement of what I interpret the second sentence to mean is: if the prior value is read then this reading shall be used to determine the new value. For i++ I would say that the value of i is read once and used to determine both the new value of i and the value of the expression itself. This is OK with my interpretation.

Name: Anonymous 2008-01-09 5:57

I know I'm late but >>121-122 are faggots

expert programmer style:
(setf (values x y) (values y x))
or:
(rotatef x y)

Name: Anonymous 2008-01-09 5:59

>>129
3

>>130,131 are faggots

Name: Anonymous 2008-01-09 6:00

int i=0;
i++ && i++ || i++ && i++

This is why prefix notation is superior.

Name: Anonymous 2008-01-09 6:02

>>130,131
Wrong. This was a CS exam question that only 3 out of 102 students answered correctly.

Hint: sequence points.

Name: Anonymous 2008-01-09 6:02


int i = 0;
i++ && i++ || i++ && i++
^      ^      ^1     ^
0      Don't eval   2

Result: 3

Name: Anonymous 2008-01-09 6:03

>>134
win

Name: Anonymous 2008-01-09 6:03

>>136
That's why you would write it in lisp and then 'macroexpand it.

Name: Anonymous 2008-01-09 6:06

>>136
Only 3? Hahaha oh wow

Name: Anonymous 2008-01-09 6:30

>>140
Yeah, that was pretty pathetic, considering K&R and the C standard was required reading for the course. The class average on that exam was 57%.

http://img185.imageshack.us/img185/1508/112resgt8.png

Name: Anonymous 2008-01-09 6:52

>>136
o rly because that one was obvious.  I suppose reading K&R has its benefits, too bad I don't know what the hell a sequence point is though.

Name: Anonymous 2008-01-09 7:17

>>141
Is the answer 0?

Name: Anonymous 2008-01-09 8:02

>>143
NO. And I don't even program in C!

Name: Anonymous 2008-01-09 8:14

&& has higher priority than ||, so it's either 2 or 2, so 2.

In lisp, on the other hand, everything is true as long as it's not '(), so it would be 1 (boolean truth).



Am I right? I don't program in C either.

Name: Anonymous 2008-01-09 8:28

>>145
Incorrect.
It's 3.

i = 0
...
              i is 1, incremented
i++ && i++ || i++ && i++
^      ^      ^      ^
0,   ,/            i is 2, incremented
next skipped
i incremented
[code]

should be 3


New one:

[code]
i = 1
sizeof (i++) && i++ || i++

What is i?

Name: Anonymous 2008-01-09 8:33

The answer is: You can't know. Undefined. The C standard says nothing about what the result will be and the only way to know for sure what i will be after that line lies in how the specific compiler that compiles that piece of code handles it.

Name: Anonymous 2008-01-09 9:15

>>146
3 as well, assuming sizeof (i) != 0.

Name: 146 2008-01-09 9:48

>>147
Incorrect.

>>148
Incorrect.
sizeof cannot evaluate to 0.
1 to SIZE_MAX in fact.
Furthermore, sizeof does not evaluate it's operand.

The result will be 2.

Name: Anonymous 2008-01-09 10:45

no

Name: Anonymous 2008-01-09 11:18

>>149
Oh you little wizard you...

Name: Anonymous 2008-01-09 12:43

Furthermore, sizeof does not evaluate it's operand
Furthermore, sizeof does not evaluate it is operand
Syntax error >>149 (8): found verb, expected noun phrase

Name: Anonymous 2008-01-09 12:55

>>152
Holy fuck, which compiler parses English contractions?

Name: Anonymous 2008-01-09 15:04

>>153
ecc

Name: Anonymous 2008-01-09 16:16

>>154
What does the e stand for in ecc?

Name: Anonymous 2008-01-09 16:19

>>155
English.

Oh wait.

Name: Anonymous 2008-01-10 0:52

This is some C code I wrote this morning:

     int count = 0;
     int m = 0; /* Start with the first offset modifier. */
     for (m = 0; count<4 && m < 8; m++)
     {
          if (!m%2) count = 1; /* The count is for one of the four directions. */
          int xo = 0,yo = 0,i = 1; /* Offsets and incrementer. */
          for (;(x+xo>=0) && (x+xo<WIDTH)   /* Make sure we've not */
             && (y+yo>=0) && (y+yo<HEIGHT)  /* gone off the grid.  */
             && grid[x+xo][y+yo]==pl; /* Every single one needs to be ==pl. */
               i++, xo=i*mod[m].x, yo=i*mod[m].y, /* Update offsets. */
               count++);/* Increase count. */
     }

Name: Anonymous 2008-01-10 0:56

count++);/* Increase count. */

Name: Anonymous 2008-01-10 2:09

>>158
What's the matter? Haven't seen well commented C code before?

Name: Anonymous 2008-01-10 3:11

&& grid[x+xo][y+yo]==pl; /* Every single one needs to be ==pl. */
O RLY

Name: Anonymous 2008-01-10 3:18

>>157
lrn2comment faggot

Name: Anonymous 2008-01-10 3:34

>>157
Stuffing your FOR loop full of this shit isn't going to make your code run any faster.

Name: Anonymous 2008-02-07 16:36

#include <stdlib.h>
#include <stdio.h>
char* main() {
  char* DATA = malloc(4097);
  printf("REAL `DATA' SIZE: %u\n", *(unsigned int*)(DATA - 4));
  return DATA; /* ONLY PUSSEYS FREE THERE MEMORT; LET THE DOS DO IT!!! */
}

Name: Anonymous 2008-02-07 16:40

>>159
s/well /over

Name: Anonymous 2008-02-07 16:54

>>164
>>163
Actually, it originates from a program called QED, originally written in the late 1960s by Butler Lampson and Peter Deutsch. Their version had the command SUBSTITUTE /x/ FOR /y/. Ken Thompson (of Unix fame) then wrote a version for MIT's CTSS system, and shortened the substitution command to just s/x/y/ - and, crucially, added regular expression support to it. Thompson later wrote Unix's standard editor ed, taking a lot of features from QED, including s//. It was the massive spread of Unix that so popularised this idiom.

Name: Anonymous 2008-02-07 16:56

from sys/cdefs.h:
/*
 * Compiler-dependent macros to help declare dead (non-returning) and
 * pure (no side effects) functions, and unused variables.  They are
 * null except for versions of gcc that are known to support the features
 * properly (old versions of gcc-2 supported the dead and pure features
 * in a different (wrong) way).  If we do not provide an implementation
 * for a given compiler, let the compile fail if it is told to use
 * a feature that we cannot live without.
 */
#ifdef lint
#define __dead2
#define __pure2
#define __unused
#define __packed
#define __aligned(x)
#define __section(x)
#else
#if !__GNUC_PREREQ__(2, 5) && !defined(__INTEL_COMPILER)
#define __dead2
#define __pure2
#define __unused
#endif
#if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7 && !defined(__INTEL_COMPILER)
#define __dead2         __attribute__((__noreturn__))
#define __pure2         __attribute__((__const__))
#define __unused
/* XXX Find out what to do for __packed, __aligned and __section */
#endif
#if __GNUC_PREREQ__(2, 7)
#define __dead2         __attribute__((__noreturn__))
#define __pure2         __attribute__((__const__))
#define __unused        __attribute__((__unused__))
#define __used          __attribute__((__used__))
#define __packed        __attribute__((__packed__))
#define __aligned(x)    __attribute__((__aligned__(x)))
#define __section(x)    __attribute__((__section__(x)))
#endif
#if defined(__INTEL_COMPILER)
#define __dead2         __attribute__((__noreturn__))
#define __pure2         __attribute__((__const__))
#define __unused        __attribute__((__unused__))
#define __used          __attribute__((__used__))
#define __packed        __attribute__((__packed__))
#define __aligned(x)    __attribute__((__aligned__(x)))
#define __section(x)    __attribute__((__section__(x)))
#endif
#endif

#if __GNUC_PREREQ__(2, 96)
#define __pure          __attribute__((__pure__))
#else
#define __pure
#endif

#if __GNUC_PREREQ__(3, 1) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 8
00)
#define __always_inline __attribute__((__always_inline__))
#else
#define __always_inline
#endif

#if __GNUC_PREREQ__(3, 3)
#define __nonnull(x)    __attribute__((__nonnull__(x)))
#else
#define __nonnull(x)
#endif

/* XXX: should use `#if __STDC_VERSION__ < 199901'. */
#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER)
#define __func__        NULL
#endif

#if (defined(__INTEL_COMPILER) || (defined(__GNUC__) && __GNUC__ >= 2)) && !defi
ned(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901
#define __LONG_LONG_SUPPORTED
#endif

/*
 * GCC 2.95 provides `__restrict' as an extension to C90 to support the
 * C99-specific `restrict' type qualifier.  We happen to use `__restrict' as
 * a way to define the `restrict' type qualifier without disturbing older
 * software that is unaware of C99 keywords.
 */
#if !(__GNUC__ == 2 && __GNUC_MINOR__ == 95)
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901
#define __restrict
#else
#define __restrict      restrict
#endif
#endif

/*
 * GNU C version 2.96 adds explicit branch prediction so that
 * the CPU back-end can hint the processor and also so that
 * code blocks can be reordered such that the predicted path
 * sees a more linear flow, thus improving cache behavior, etc.
 *
 * The following two macros provide us with a way to utilize this
 * compiler feature.  Use __predict_true() if you expect the expression
 * to evaluate to true, and __predict_false() if you expect the
 * expression to evaluate to false.
 *
 * A few notes about usage:
 *
 *      * Generally, __predict_false() error condition checks (unless
 *        you have some _strong_ reason to do otherwise, in which case
 *        document it), and/or __predict_true() `no-error' condition
 *        checks, assuming you want to optimize for the no-error case.
 *
 *      * Other than that, if you don't know the likelihood of a test
 *        succeeding from empirical or other `hard' evidence, don't
 *        make predictions.
 *
 *      * These are meant to be used in places that are run `a lot'.
 *        It is wasteful to make predictions in code that is run
 *        seldomly (e.g. at subsystem initialization time) as the
 *        basic block reordering that this affects can often generate
 *        larger code.
 */
#if __GNUC_PREREQ__(2, 96)
#define __predict_true(exp)     __builtin_expect((exp), 1)
#define __predict_false(exp)    __builtin_expect((exp), 0)
#else
#define __predict_true(exp)     (exp)
#define __predict_false(exp)    (exp)
#endif

Name: Anonymous 2008-02-07 17:11

optimized code

#include <stdio.h>

#define LEFT_CURLY_BRACE {
#define RIGHT_CURLY_BRACE }
#define LEFT_PARENTHESIS (
#define RIGHT_PARENTHESIS )
#define EOL ;
#define INTEGER int
#define CHARACTER char
#define NOTHING void
#define ECHO printf
#define TERMINATE exit

INTEGER main LEFT_PARENTHESIS NOTHING RIGHT_PARENTHESIS LEFT_CURLY_BRACE
        ECHO LEFT_PARENTHESIS "hello nigra!\n" RIGHT_PARENTHESIS EOL
        TERMINATE LEFT_PARENTHESIS 0 RIGHT_PARENTHESIS EOL
RIGHT_CURLY_BRACE

Name: Anonymous 2008-02-07 18:32

>>167
Fuck off Guido, stop posting CPython source code

Name: Anonymous 2008-02-07 20:17

These are meant to be used in places that are run `a lot'
that are run `a lot'
run `a lot'
`a lot'

Name: Anonymous 2008-03-18 8:15

Here's a little secret that allows you to save memory when allocating structures:
struct s { int a; char b };
struct s s1 = malloc(sizeof(struct s)); /* OH NO MASSIVE MEMORY WASTE */
struct s s2 = malloc(offsetof(struct s, b) + sizeof(char)); /* YAY MEMORY SAVED */


If you don't have offsetof (stddef.h), it can be implemented liek this:

#define offsetof(type, f) ((size_t) ((char *)&((type *)0)->f - (char *)(type *)0))

Name: Anonymous 2008-03-18 8:31

>>167
You suck.
exit(3) requires <stdlib.h>, which you did not include.

Name: Anonymous 2008-03-18 8:35

>>170
And don't forget -O3 -funroll_loops -fOMG_OPTIMIZED !

Name: Anonymous 2008-03-18 8:36

>>170
s2 becomes a dangling pointer in case of padding bytes after b.

Name: Anonymous 2008-03-18 8:39

>>173
>>163 might disagree! (just noticed that I forgot the *s for s1 and s2)

And it's not like you will try to access the padding, anyway.

Name: Anonymous 2008-03-18 9:04

>>174
you? no. the compiler? yes.
Sorry, but your code is not good.

Name: Anonymous 2008-03-18 9:28

>>170
struct s s1 = malloc(...);

MY EYES ARE BLEEDING

Name: Anonymous 2008-03-18 10:18

>>175
Prove me wrong, bitch.

Name: Anonymous 2008-03-18 11:04

Use memcpy.

Name: Anonymous 2008-03-18 12:38

>>178
Use struct assignment.

Name: Anonymous 2008-03-18 13:37

COMPUTER SCIENCE 4 LYFE!!!

Name: Anonymous 2008-03-18 13:52

>>170
What, you save about 3 bytes in memory? Big deal. Unless you're programming an embedded system in which every byte is precious, you'd better stick with the more widely-used and more readable "malloc(sizeof(struct s))".

Name: Anonymous 2008-03-18 13:58

Name: Anonymous 2008-03-18 14:43

>>181
Please read the rest of this thread before continuing.  This thread is about secret tricks of the C language that work well (most of the time), but may not have totally defined behavior or be very portable.

Name: Anonymous 2009-08-16 3:02

Lain.

Name: Anonymous 2009-08-16 3:03

Lain.

Name: Anonymous 2009-08-16 3:45

Lain.

Name: Anonymous 2009-08-16 3:56

Lain.

Name: Anonymous 2009-08-16 4:08

Lain.

Name: Anonymous 2009-08-16 4:14

Lain.

Name: Anonymous 2009-08-16 4:36

Lain.

Name: Anonymous 2010-12-17 1:28

Are you GAY?
Are you a NIGGER?
Are you a GAY NIGGER?

If you answered "Yes" to all of the above questions, then GNAA (GAY NIGGER ASSOCIATION OF AMERICA) might be exactly what you've been looking for!

Don't change these.
Name: Email:
Entire Thread Thread List