tags:

views:

149

answers:

5

I ran the following:

#include <stdio.h>
typedef unsigned short boolean;

#define false 0
#define true (!false)
int main()
{
    int STATUS = 0;
    int i = 0;
    boolean ret = true;
    for(i = 0; i < 99999; i++)
    {
        ret = ret && printf("Hello, World.");
    }
    if(!ret)
    {
        STATUS = -1;
    }

    return STATUS;
}

It completes in just under a second. Typically 0.9 - 0.92.

Then I changed int i = 0; to int *i = 0; and now I am getting execution times under 0.2 seconds. Why the speed change?

+2  A: 

Typically, printing to a console will be several orders of magnitude larger than any gain with micro optimization you could do to such a loop.

Are you really sure your second version prints hello world 99999 times as well ?

When you're doing for(int *i = 0; i++ ; i < 99999 ) , you're cheking if the pointer value(an address) is less than 99999, which doesn't normally make a lot of sense. Incrementing a pointer means you step it up to point at the next element, and since you have an int*, you'll increment the pointer by sizeof(int) bytes.

You're just iterating 99999/sizeof(int) times.

nos
Good point, I just checked and it seems to be spitting out every fourth iteration. Now this is weird.
Josh K
@Josh K it's printing out every fourth iteration because `sizeof(int)` is 4 on your system. so when you do `i++`, you are increasing it by four. Try `char* i` for comparison. If you want it to go really fast try `long long* i`.
aaronasterling
@aaron: I don't know what you mean when you say *" `char* i` for comparision"*, can you clarify?
Josh K
@Josh k. use a pointer of type `char` in the loop instead of type `int`.
aaronasterling
@aaron: You can use a char pointer in a for loop? That is wicked. I though it was crazy enough having to define `boolean`...
Josh K
+1  A: 

The correct way to do this test with a pointer would be something like:

int i;
int *i_ptr = &i; 

for (*i_ptr = 0; *i_ptr < 99999; *i_ptr++) {
    ...
Seth
Loop is being executed, just a bad increment.
Josh K
The loop would run in his pointer case. He initializes the pointer to null (0) and the increments it until it passes 99999. He never sets it to point at any instance of a variable or any other valid address.
Alan
@Seth: he's creating a pointer which pointes at memory location 0; That is the pointer's value (not the value at the location) is 0. Dereferencing the point would throw a segmentation fault on most architectures, but he never does that. Instead, when he writes i++ he gets a pointer increment suitable for an int (4 bytes on his architecture), so the loop runs fewer times. Your suggested replacement code is correct, however.
dmckee
Typing faster than I was thinking today :|, Edited.
Seth
+8  A: 

Your runtime is dominated by the time required to print to the console. i++ on an int* will increment the pointer by the size of a pointer. That will be either 4 or 8 depending on your computer and compiler settings. Based on the numbers you report, presumably it would be 4. So printf is executed only a quarter as many times.

Alan
downvotes? why the hate?
Alan
+2  A: 

Your comment on nos's answer confirmed my suspicion: it's pointer arithmetic. When you increment an int pointer using ++, it doesn't just add one to the number, but it actually jumps up by the size of an integer, which is usually 4 (bytes). So i++ is actually adding 4 to the numeric value of i.

Similarly, if you use += on a pointer, like i += 5, it won't just add 5 (or whatever) to the numeric value of i, it'll advance i by the size of that many integers, so 5*4 = 20 bytes in that case.

The reasoning behind this is that if you have a chunk of memory that you're treating as an array,

int array[100]; // for example

you can iterate over the elements in the array by incrementing a pointer.

int* i = array;
int* end = array + 100;
for (i = array; i < end; i++) { /* do whatever */ }

and you won't have to rewrite the loop if you use a data type of a different size.

David Zaslavsky
@David: Now that is a cool loop with the pointer. Looks like I have a lot to learn.
Josh K
@Josh: it's a pretty common pattern in low-level C code, so it'd definitely be a good idea to be familiar with that one.
David Zaslavsky
Also I wonder why I got downvoted? Explanation please?
David Zaslavsky
@David: No idea who did the downvote, almost all the answers provided were helpful in one form or another.
Josh K
+1  A: 

The reason is because the increment operates differently on pointers.

On ints, i++ increments i by 1.

For pointers, i++ increments by the size of the pointed-to object, which will be 4 or 8 depending on your architecture.

So your loop runs for only 1/4 or 1/8 of the iteration count when i is a pointer vs when i is an int.

DigitalRoss