[comp.lang.c] Assigning to Pointers

tom@vrdxhq.UUCP (04/28/87)

This may be a dumb question, but could someone please explain
to me how I assign an absolute address to a pointer to an array?

I'm trying to overlay various structures and arrays at different
times on top of the physical page frame in EMM.

I'm using MSC 4.0

I want to do the following :


int *aa[];


aa = 0x50000;


-- or even better --

struct POINTER_PARTS
  {
    unsigned offset_part;
    unsigned segment_part;
   }

union POINTER_ACCESS
  {
     struct POINTER_PARTS pp;
     int *far_pointer;
   }

union POINTER_ACCESS upa;


upa.pp.segment_part = 0x5000;
upa.pp.offset_part = 0x0;

aa = upa.far_pointer;


===

I keep getting "need lvalue" type errors.  Any help anyone can provide,
or comments on my code example, are greatly appreciated.

toma@tekgvs.TEK.COM (Thomas Almy) (04/29/87)

In article <3537@vrdxhq.UUCP> tekgvs!tekcrl!tektronix!uw-beaver!teknowledge-vaxc!sri-unix!husc6!seismo!vrdxhq!tom tom@vrdxhq.UUCP (Tom Welsh) writes:
>
>This may be a dumb question, but could someone please explain
>to me how I assign an absolute address to a pointer to an array?
>...
>I'm using MSC 4.0
>
I thought that this would be general enough to followup rather than reply.

You have to remember that addresses of "far" data structures are longs and
not ints.

For SMALL or MEDIUM memory models (i.e., one data segment), you can say

int far *aa[];	/* aa is a far pointer to an array of ints */

aa = (int far *) 0x50000L;	/* for a fixed address */

#define absAddress(segment,offseg)  (((long)(segment) << 16) + (offseg))

aa = (int far *) absAddress(5,0);	/* for convenience */

For COMPACT or LARGE memory models (i.e., more than one data segment),
just delete the keyword "far" from the preceeding examples.


Tom Almy
(I hate C, but use it twice a day)

chris@mimsy.UUCP (Chris Torek) (04/29/87)

In article <3537@vrdxhq.UUCP> tom@vrdxhq.UUCP (Tom Welsh) writes:
>This may be a dumb question,

No, pointers and arrays and their interconversions are a common
confusion point in C.

>but could someone please explain to me how I assign an absolute
>address to a pointer to an array?

Given your example, you should use a pointer, not a pointer to an
array.  The C language assumes a flat memory space*, and given this
assumption, a single pointer can tell you everything you need to
know about a one-dimensional array save its size (which C does not
use anyway, in this case).

(*The flat space is only per data object, which allows segmented
implementations on the 80x86.)

>int *aa[];

% cdecl
explain int *aa[]
declare aa as array of pointer to int
% 

In other words, this is an array of unspecified size (which is treated
as though it were an `extern' definition, and allocates no memory,
but, at least on Unix compilers, does set the symbol), each member of
which points to zero or more integers.

>-- or even better --

>struct POINTER_PARTS
>  {
>    unsigned offset_part;
>    unsigned segment_part;
>   }

>union POINTER_ACCESS
>  {
>     struct POINTER_PARTS pp;
>     int *far_pointer;
>   }

>union POINTER_ACCESS upa;

>upa.pp.segment_part = 0x5000;
>upa.pp.offset_part = 0x0;

>aa = upa.far_pointer;

This is indeed better:  Simply leave out the final assignment, and use

	<int_lvalue> = upa.far_pointer[<int_expr>];

If you need a separate variable:

	int *aa;
	union POINTER_ACCESS upa;

	... set upa ...
	aa = upa.far_pointer;

`int *aa' is a pointer to a block of memory just as much as it is a
pointer to a single `int'.  The only thing that distinguishes the
two is the programmer.

(Yes, one can argue for `int (*aa)[]', but the current dpANS does
not allow this declaration---though it does allow `int ar[]; &ar',
in which &ar has type int (*)[]!)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
UUCP:	seismo!mimsy!chris	ARPA/CSNet:	chris@mimsy.umd.edu

mason@gargoyle.UChicago.EDU (Tony Mason) (04/30/87)

>>This may be a dumb question, but could someone please explain
>>to me how I assign an absolute address to a pointer to an array?
>>...
>>I'm using MSC 4.0
>>
>You have to remember that addresses of "far" data structures are longs and
>not ints.
>
>For SMALL or MEDIUM memory models (i.e., one data segment), you can say
>
>int far *aa[];	/* aa is a far pointer to an array of ints */
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Unless my understanding of C (and of those around me) has just gone out the
window, that is an array of far pointers to integers. To make the delcaration
fit the comment it should be:

int far *aa; /* aa is a far pointer to an array of ints */

Now you just use integer arithmetic to acces elements in the array (eg.
*(aa + 4) would be the fifth integer in the array).

To make the comment match the declaration :

int far *aa[]; /* aa is an array of far pointers to integers */

Now, to access an integer, you would use something like *aa[4] to access the
integer pointed at by the fifth element of the pointer array.

Finally, if you use the undefined array size syntax, you are defining
something that must be external (or in a function declaration list).  Whether
or not the compiler should accept this at all is quite suspect (at least to
me) without an extern in front.  As for using far, that is only necessary
when you are using (1) any model with restricted data size AND (2) accessing
a data structure outside the normal data segment.  In line with the type of
question asked, this is probably NOT what was being asked.  I think the
confusion in this case was with pointer declarations, not access problems.

Tony Mason
Univ. of Chicago, Dept. of C.S.
ARPA: mason@gargoyle.uchicago.edu
UUCP: ...ihnp4!gargoyle!mason

rh@cs.paisley.ac.uk (Robert Hamilton) (05/01/87)

In article <3537@vrdxhq.UUCP> tom@vrdxhq.UUCP (Tom Welsh) writes:
>
>This may be a dumb question, but could someone please explain
>to me how I assign an absolute address to a pointer to an array?
>
>I'm trying to overlay various structures and arrays at different
>times on top of the physical page frame in EMM.
>
>I'm using MSC 4.0
>
>I want to do the following :
>
>
>int *aa[];
>
>
>aa = 0x50000;

This is an old one. int *aa[] is actually a *constant*
So you cant assign to it.
Try int **aa; aa= (int **) 0x50000;
This should be ok. Subtle difference between *aa[] and **aa !!

-- 
JANET:  rh@uk.ac.paisley.cs
EMAIL:	rh@cs.paisley.ac.uk		| Post: Systems manager.
UUCP:	...!seismo!mcvax!ukc!paisley!rh	|	Department of Computing,
Phone:	+44 41 887 1241 Ext. 219	|	Paisley College
					|	High St. Paisley.
					|	Scotland.
					|	PA1 2BE

jfh@killer.UUCP (John Haugh) (05/06/87)

In article <3537@vrdxhq.UUCP>, tom@vrdxhq.UUCP (Tom Welsh) writes:
> 
> This may be a dumb question, but could someone please explain
> to me how I assign an absolute address to a pointer to an array?
> 
> I'm trying to overlay various structures and arrays at different
> times on top of the physical page frame in EMM.
> 
> I'm using MSC 4.0
> 
> I want to do the following :
> 
> 
> int *aa[];
This is not a pointer to an array.  This is an array of pointers.  So,
the assignment
> aa = 0x50000;
doesn't make much sense.  If you want a pointer to an array, you could
try
int	**aa;
which works nicely, since the [] is really not all that needed (flame
retardant statement).  If you REALLY want a pointer to an array, how
about
int	*(aa[]);
The parenthesis come in real handy at times, for example (small lesson in
C to follow :-) when you can't figure out how to declare a 'something' with
a weird shape.  My weakness is pointers to functions -
	int	foo ();		/* this is a function */
	int	*foo ();	/* this is a function RETURNING a pointer */
	int	*(foo ());	/* pointer to first function */
I won't even bother with POINTER to FUNCTION returning POINTER to FUNCTION
returning an integer (the return value of signal() is one of these).

- John.

Disclaimer:
	I don't have the slightest idea what I am talking about.  I can't
	handle these problems either.

chris@mimsy.UUCP (Chris Torek) (05/10/87)

In article <857@killer.UUCP> jfh@killer.UUCP (John Haugh) writes:
>The parenthesis come in real handy at times, for example (small lesson in
>C to follow :-) when you can't figure out how to declare a 'something' with
>a weird shape.  My weakness is pointers to functions -
>	int	foo ();		/* this is a function */

Right;

>	int	*foo ();	/* this is a function RETURNING a pointer */

right; and

>	int	*(foo ());	/* pointer to first function */

wrong: this last is `function returning pointer to int'.

>I won't even bother with POINTER to FUNCTION returning POINTER to FUNCTION
>returning an integer (the return value of signal() is one of these).

Actually, the return value from signal is not representable,
as it is `pointer to function returning pointer to function
returning pointer to function returning ...', with no final
type.  Instead, we all cheat and use `pointer to function
returning int' (or, in some cases, `returning void').

The program `cdecl' is handy for this sort of thing.  It has been
posted several times, so your neighbor probably has a copy, and it
is available via anonymous FTP from host mimsy.umd.edu on the
ARPAnet.

	% cdecl
	declare foo as pointer to function returning pointer to \
	function returning int
	int (*(*foo)())()

(cdecl does not handle `\' continuation lines; this is purely a
mailer-bug-avoidance device)

	explain int (*(*foo)())()
	declare foo as pointer to function returning pointer to \
	function returning int

You can create horrendous things that no one ever would use:

	declare a as array 5 of pointer to function returning pointer to \
	pointer to function returning pointer to array 3 of pointer to char
	char *(*(**(*a[5])())())[3]

Amaze your friends by getting types like this right the first time!
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

jai@im4u.UUCP (Jai Srinivasan) (05/10/87)

In article <857@killer.UUCP>, John Haugh (jfh@killer.UUCP) writes:

> The parenthesis come in real handy at times, for example (small lesson in
> C to follow :-) when you can't figure out how to declare a 'something' with
> a weird shape.  My weakness is pointers to functions -
> 	int     foo ();         /* this is a function */
> 	int     *foo ();        /* this is a function RETURNING a pointer */
> 	int     *(foo ());      /* pointer to first function */

int *foo(); and int *(foo()); are equivalent because the () has a higher 
precedence than the * in the declaration.  To make foo a pointer to a
function which returns an integer, the declaration ought to be int (*foo)();.
I guess the same holds with the array declarations stated earlier in that
article because [] (like ()) has a higher precedence than the *.

Reading these declarations is not all that hard: just use the precedence
rules.  The parentheses around the * in int (*foo)(); indicates that the
* should be interpreted before the (), and reading "*" as "pointer to"
and "()" as "function that returns", one reads

int *foo();	as "foo is a function that returns a pointer to an integer",

and

int (*foo)();   as "foo is a pointer to a function that returns an integer".

Similarly,

int (*signal())(); is read as "signal is a function that returns a pointer
			       to a function which returns an integer".

I don't know if K&R ever explicitly state that the precedence rules hold
in the declaraions as well, but I assume they do.


Jai.
-----------------
Jai Srinivasan, UUCP: {gatech,harvard,ihnp4,pyramid,seismo}!ut-sally!im4u!jai
ARPA:  		      jai@im4u.UTEXAS.EDU, jai@sally.UTEXAS.EDU

sjoerd@cs.vu.nl (Sjoerd Mullender) (05/12/87)

In article <6611@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>Actually, the return value from signal is not representable,
>as it is `pointer to function returning pointer to function
>returning pointer to function returning ...', with no final
>type.  Instead, we all cheat and use `pointer to function
>returning int' (or, in some cases, `returning void').

We'll all agree that signal returns a pointer to some sort of function.
That function is the signal handler for a certain signal.  This means
that it is int function (or sometimes void).  So signal is a function
returning a pointer to a function returning int (or void).
In other words:

	int (*signal())();
-- 
Sjoerd Mullender
sjoerd@cs.vu.nl

john@viper.UUCP (05/12/87)

In article <857@killer.UUCP> jfh@killer.UUCP (John Haugh) writes:
 >In article <3537@vrdxhq.UUCP>, tom@vrdxhq.UUCP (Tom Welsh) writes:
 >> 
 >> I want to do the following :
 >> 
 >> 
 >> int *aa[];
 >This is not a pointer to an array.  This is an array of pointers.  So,
 >the assignment
 >> aa = 0x50000;
 >doesn't make much sense.  If you want a pointer to an array, you could
 >try
 >int	**aa;

Correct so far....

 >  If you REALLY want a pointer to an array, how about
 >int	*(aa[]);

How about because it's not a pointer to an array?

A pointer to an array of int would be:
	int (*aa)[];

What you gave ( int *(aa[]); ) is identical to ( int *aa[]; ) which is
actualy an array of pointers to ints...  The [] binds to aa with a higher
precedence than the *.

 >  My weakness is pointers to functions -

  So I see...  If it's any consolation, it's taken me a few years to
get to the point where I get them right most of the time.  I know
many programmers who're excelent programmers, but even after 5-10
years they still get function pointers wrong now and then...

  I suspect the problem Tom Welsh is having is from the incorrect
(but often used) habit some programmers have of defining a pointer
to an array of pointers in-the-parameter-list as:

	foo(aa)
	int *aa[];
	{
	....

  Now, because C "knows" that you can't pass an array, it translates
the *aa[] into **aa but doesn't tell the programmer about it.  Any
reference to aa[x] is (per standard C) corectly converted to *(aa+x)
which will work for an array or a pointer.  Unfortunately for Tom,
this doesn't work anywhere except as part of the parameter list.  If
you have the sample I gave above, then aa = (int**)0x50000; will
work with no problem, but it won't work at-all if you try it with a 
non-function-argument variable since the identifier aa will then refer 
to a non-moveable array.

  Your best bet is to correctly define it as int **aa; in the first
place and avoid using the [] for for a pointer in parameter lists to
avoid future confusion...


 >I won't even bother with POINTER to FUNCTION returning POINTER to FUNCTION
 >returning an integer. 

Just for the hell of it...  B-) ...:

	int (*((*foo)()))();


 >Disclaimer:
 >	I don't have the slightest idea what I am talking about.  I can't
 >	handle these problems either.

  Oh...  (falseto voice)  "Nevermind..."  :)

--- 
John Stanley (john@viper.UUCP)
Software Consultant - DynaSoft Systems
UUCP: ...{amdahl,ihnp4,rutgers}!{meccts,dayton}!viper!john

chris@mimsy.UUCP (Chris Torek) (05/13/87)

In article <6611@mimsy.UUCP> I wrote some nonsense about signal.
Ignore it.  Thanks to sjoerd@cs.vu.nl (Sjoerd Mullender) for catching
that.

(enter exposition)

I was thinking of a particular sort of `onexit' function, wherein
each function returns a pointer to another function.  Each of these
functions is called until one returns a nil pointer:

	/* from <onexit.h>:
	typedef void (*onexit_t)();
	 * `cheating' */

	onexit_t module_lastexit;
	onexit_t module_cleanup();

	module_setup()
	{
		...
		/* arrange to have module_cleanup called at exit */
		module_lastexit = onexit(module_cleanup);
		/* and remember whatever was registered before us */
	}

	onexit_t
	module_cleanup()
	{
		/* clean up */
		...
		/* and have exit do the previously registered function */
		return (module_lastexit);
	}

Exit then has a loop of the form

		while (doatexit != NULL)
			/* note the odd cast required */
			doatexit = (*(onexit_t *(*)())doatexit)();

and the onexit function itself reads

	onexit_t
	onexit(f)
		onexit_t f;
	{
		onexit_t olddo = doatexit;

		doatexit = f;
		return (olddo);
	}

(exit exposition)

How I got this confused with signal I have no idea.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

gwyn@brl-smoke.ARPA (Doug Gwyn ) (05/13/87)

In article <266@sjoerd.cs.vu.nl> sjoerd@cs.vu.nl (Sjoerd Mullender) writes:
>In article <6611@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>>Actually, the return value from signal is not representable,
>>as it is `pointer to function returning pointer to function
>>returning pointer to function returning ...', with no final
>>type.  Instead, we all cheat and use `pointer to function
>>returning int' (or, in some cases, `returning void').
>We'll all agree that signal returns a pointer to some sort of function.
>That function is the signal handler for a certain signal.  This means
>that it is int function (or sometimes void).  So signal is a function
>returning a pointer to a function returning int (or void).
>In other words:
>	int (*signal())();

Sjoerd is right, except that the return type of a signal handler function
is void, not int.  Use of int dates back to the days before there was a
void type; we have finally in the past couple of years gotten the
standards to agree that void is the correct type.  There are still
several implementations that haven't updated their signal.h, however.

I don't know what Chris had in mind.  The only standard function I've seen
in recent years that had such a problem with recursive type was the X3J11
onexit() function, which registered functions to be called upon exit.
Each such function was supposed to keep track of the next in the chain,
which is where the recursive type came from.  Fortunately we managed to
get this function changed to atexit() which has a much simpler inerface.

If you were to consider the parameter types as part of a function's type,
then signal() would of necessity have recursive type.