[comp.lang.c] pointers for speed

torek@elf.ee.lbl.gov (Chris Torek) (02/26/91)

(This is a topic for comp.lang.c, not comp.std.c; I have redirected
followups there.)

In article <1998@gold.gvg.tek.com> shaunc@gold.gvg.tek.com (Shaun Case) writes:
>I know that when you repeatedly access something like
>
>foo.a.b.c.d[11].value
>
>it is better to declare a (register) pointer, assign it the address
>of foo.a.b.c.d[11].value, and do manipulations on that, since it
>is faster.

This is an unsupported assertion, and in fact it often turns out to
be no faster (though usually no slower either).

In particular, given ...

>a heavily nested structure ...
>I want to access the various members of a.x.something (.foo, .foo2,
>.blah, .blah2) quickly.

... structures that are nested in this manner (where variable `a' is
a structure containing a member `x' which itself is a structure
containing a member `something' which itself is a structure containing
members `foo', `foo2', etc.) are typically implemented such that
computing &a.x.something.foo requires exactly as much work as computing
&a.x or &a.x.something.  For instance, on the 68010, the difference
between:

	a.x.something.foo = 3;

and:

	local_var = 3;

is, in essence,

	moveq	#3,a5@260

and

	moveq	#3,a7@-32

both of which require exactly the same amount of time and space.

On the other hand, writing

	ptr->x.something.foo = 3;
	ptr->x.something.foo2 = 3 * 3;
	ptr->x.something.blah = "headache";

is generally perceived to be less clear than writing:

	s->foo = 3;
	s->foo2 = 3 * 3;
	s->blah = "headache";

and if you agree, you should use the latter.

>I have a function that I pass a pointer to type struct a, thus:
>
>void do_stuff (struct *a ptr)
>{}
>
>and what I want to do is something like
>
>register char *fastptr;
>
>fastptr = &(ptr->x.something) 
>
>and then access fastptr->foo, fastptr->foo2, etc.

It would help greatly if your examples were legal C....

To take the conceptual error first:  Declaring `fastptr' as `register
char *fastptr' means that `fastptr' points to `char's.  It does not
point to structures.  Since it does not point to structures, you may
not use it to obtain elements of structures.  If you want a pointer
to point to one or more structures of type `struct glorp', you must
declare it as a pointer to `struct glorp':

		struct glorp *g;

Next, if `ptr' is to point to a `struct a', the proper syntax is:

	void do_stuff(struct a *ptr)

Composing these and adding the assignment to make `g' point to the
glorp member of the structure to which `ptr' points, we get:

	void do_stuff(struct a *ptr) {
		struct glorp *g;

		g = &ptr->x.something;

At this point you can use `g->foo', `g->foo2', and so on exactly
as above.  It will likely be no faster (but more readable and/or
less cumbersome) than using `ptr->x.something.foo', etc.

On the other hand, if `ptr' were to point to a structure in which the
sub-structures are not directly imbedded, but rather found through
pointers, then:

	void do_stuff(struct object *o) {
		struct value *v;

		/*
		 * Pick up object's current value pointer,
		 * which is found by reading its attributes
		 * to find its current binding, and then
		 * reading the binding to find the current value.
		 */
		v = o->o_attr->a_binding->b_value;
		...
	}

in this case using `v' is more likely (but still not guaranteed!) to
be faster than writing `o->o_attr->a_binding->b_value' each time.  It
is also almost certain to make those editing the code happier.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov