[comp.lang.c] ** help...

nol2321@dsacg2.dsac.dla.mil (Jim Dunn) (08/21/90)

Well, no one took me up on my offer of checking out the Curses Source I've
been working on, so I'll ask a "more direct and specific" question...

Why can't I do the following?!?  (C'mon you gurus...)

---Cut Here---

#include <stdio.h>

typedef struct _window {
	int x;
	int y;
	int **array;
	int beg_x;
	int beg_y;
	int max_x;
	int max_y;
} WINDOW;

main()
{
	int x, xL = 10;
	WINDOW *w1;

	w1 = (WINDOW *) malloc(sizeof(WINDOW));

/* the problem is next */
	w1->array = malloc( xL * sizeof(int) );
/* isn't the above line legal, or how can I allocate mem for the storage */

	for(x=0;x < xL; x++)
		w1->array[x] = (int *) malloc( 10 * sizeof(int *) );

}

This is setup for, let's say, a 10 x 10 matrix of ints, OK?

It'll compile ok, but it'll lock up the machine...  (at least on the PC).

Jim
jdunn@dsac.dla.mil

vu0310@bingvaxu.cc.binghamton.edu (R. Kym Horsell) (08/21/90)

In article <2409@dsacg2.dsac.dla.mil> nol2321@dsacg2.dsac.dla.mil (Jim Dunn) writes:
\\\
>/* the problem is next */
>	w1->array = malloc( xL * sizeof(int) );
>/* isn't the above line legal, or how can I allocate mem for the storage */
\\\

The first, minor, problem is that you haven't declared the prototype
for malloc(). You'd better say

	extern char *malloc();

at the top or include the appropriate header (malloc.h is std but
some PCs use alloc.h). This'll fix other problems when you
try to change memory models.

The main problem is that you didn't allocate the array, only
the *rows* of the array. Better put

	w1->array = (int**)malloc(10 * sizeof(int*));

before the for-loop; otherwise there isn't anywhere for the 
``row-of-rows'' to be stored!

The final point: inside the for-loop you have said the
array elements are int* -- i gather you really want to store ints
in them so:

	w1->array[x] = (int*)malloc(10*sizeof(int));

Hope this helps,
-Kym Horsell

P.S. please don't edit the "Newsgroups" line.

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (08/21/90)

In article <3871@bingvaxu.cc.binghamton.edu>, vu0310@bingvaxu.cc.binghamton.edu (R. Kym Horsell) writes:
> 	extern char *malloc();
> at the top or include the appropriate header (malloc.h is std but
                                                ^^^^^^^^^^^^^^^
In ANSI-compliant compilers, the prototype for malloc() can be found
in <stdlib.h>.  The ANSI standard does not require any <malloc.h>, though
there is nothing to stop an implementation providing such a thing.
-- 
The taxonomy of Pleistocene equids is in a state of confusion.

rmj@tcom.stc.co.uk (Rhodri James) (08/21/90)

In article <2409@dsacg2.dsac.dla.mil> nol2321@dsacg2.dsac.dla.mil (Jim Dunn) writes:
>Why can't I do the following?!?  (C'mon you gurus...)
>
>typedef struct _window {
>	int x;
>	int y;
>	int **array;

       [etc]

>} WINDOW;
>
>main()
>{
>	int x, xL = 10;
>	WINDOW *w1;
>
>	w1 = (WINDOW *) malloc(sizeof(WINDOW));
>
>/* the problem is next */
>	w1->array = malloc( xL * sizeof(int) );

You want the whole list or just the short version? :-)

1) array is an int **  so the malloc should be cast to that
2) the "elements" are int *, so that should be what you take sizeof.
Pointers haven't been equivalent to ints for some while.
3) this isn't vastly relevant to PC applications, but doing a
multiplication as your argument to malloc is just asking for alignment
trouble. Either calloc(xL, sizeof(int *)), or (more grungily)
malloc(sizeof(int *[xL])) (will this work if xL is a variable?)
4) you really ought to consider #defining xL rather than making it a
variable. Unless you have pressing reasons otherwise.

>/* isn't the above line legal, or how can I allocate mem for the storage */

It's legal, but hardly sensible. Actually, it isn't all that legal.

>	for(x=0;x < xL; x++)
>		w1->array[x] = (int *) malloc( 10 * sizeof(int *) );

This time you should be taking the sizeof an int! Comments above about
multiplicative mallocs apply, and this time malloc( sizeof(int[10]))
does work (I think).

>}
>
>Jim
>jdunn@dsac.dla.mil

Hope this helps.

Rhodri
-- 
* Windsinger                 * "Nothing is forgotten..."
* rmj@islay.tcom.stc.co.uk   *                    Mike Whitaker
*     or (occasionally)      * "...except sometimes the words"
* rmj10@phx.cam.ac.uk        *                    Phil Allcock

volpe@underdog.crd.ge.com (Christopher R Volpe) (08/22/90)

In article <1884@jura.tcom.stc.co.uk>, rmj@tcom.stc.co.uk (Rhodri James)
writes:
|>You want the whole list or just the short version? :-)
|>
|>1) array is an int **  so the malloc should be cast to that
|>2) the "elements" are int *, so that should be what you take sizeof.
|>Pointers haven't been equivalent to ints for some while.
|>3) this isn't vastly relevant to PC applications, but doing a
|>multiplication as your argument to malloc is just asking for alignment
|>trouble. Either calloc(xL, sizeof(int *)), or (more grungily)
|>malloc(sizeof(int *[xL])) (will this work if xL is a variable?)

First, malloc doesn't know or care (and couldn't find out if it wanted
to) whether the argument being passed in is a constant expression
(like sizeof(anything)) or an expression computed at runtime via
a multiplication. My copy of K&R II says (section 7.8.5) that the
pointer returned by malloc or calloc has proper alignment for the
object in question. My manpage (SunOS 4.0.?) says that calloc USES
malloc to allocate the storage, and then initializes it to zeros.

Second, types must have a size determinable at compile time, since
sizeof yields a constant expression. So, (int *[xL]) is not a legal
type. AND EVEN IF IT WERE LEGAL, the value produced would be the
same as (xL * sizeof(int *)), so malloc wouldn't know the difference.

|>Rhodri
|>-- 
|>* Windsinger                 * "Nothing is forgotten..."
|>* rmj@islay.tcom.stc.co.uk   *                    Mike Whitaker
|>*     or (occasionally)      * "...except sometimes the words"
|>* rmj10@phx.cam.ac.uk        *                    Phil Allcock
                                                          
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

nol2321@dsacg4.dsac.dla.mil (Jim Dunn) (08/22/90)

Well, I appreciate ALL the suggestions that everyone has made.  You've truly
opened my eyes to my own ignorance, actually you've opened my eyes to my
typos...  You see, I was typing the program in from reading a bad program
listing.  Most of the (int *)'s WERE (int)...  So, now I've written a small
sample demo program, using all the suggestions, and will explain my use...

This **int matrix is for use with a direct screen write project.  Instead of
declaring a **char, I want to use a **int since the PC SCREEN is set up with
an attribute byte and then an actual character byte.  Such that:

	int **junk;

	junk[1][3] = (attr<<8) | chr;

OK?

I won't bother you with a net posting of the source samples, but if anyone
would be interested in giving it a look see, please e-mail me and I'll ship
you the source.  It's a new implementation of Curses using direct screen
write...

Jim
jdunn@dsac.dla.mil

rmj@tcom.stc.co.uk (Rhodri James) (08/30/90)

In article <11245@crdgw1.crd.ge.com> volpe@underdog.crd.ge.com (Christopher R Volpe) writes:
>In article <1884@jura.tcom.stc.co.uk>, rmj@tcom.stc.co.uk (Rhodri James)
>writes:
>|>3) this isn't vastly relevant to PC applications, but doing a
>|>multiplication as your argument to malloc is just asking for alignment
>|>trouble. Either calloc(xL, sizeof(int *)), or (more grungily)
>|>malloc(sizeof(int *[xL])) (will this work if xL is a variable?)

Several people have pointed out to me that it won't work if xL is a
variable. I wasn't sure, but I really should have known. Thankyou, one
and all.

And now to business.

>First, malloc doesn't know or care (and couldn't find out if it wanted
>to) whether the argument being passed in is a constant expression
>(like sizeof(anything)) or an expression computed at runtime via
>a multiplication. My copy of K&R II says (section 7.8.5) that the
>pointer returned by malloc or calloc has proper alignment for the
>object in question. My manpage (SunOS 4.0.?) says that calloc USES
>malloc to allocate the storage, and then initializes it to zeros.

Yes, K&R 2 says the *pointer* has proper alignment for the object in
question, by taking the most restrictive possibility, and I wouldn't be
surprised if calloc were implemented by using malloc. However, note the
emphasis and read on...

>[...] the value produced [by sizeof(int *[xL]) if it were legal] would be the
>same as (xL * sizeof(int *)), so malloc wouldn't know the difference.

This is not guarenteed true for all types by anything I can find in K&R 2.
The crux of the potential health hazard comes with the definition of
sizeof, which K&R2 says (section 6.3) gives a size_t result equal to the
size of the specified object or type in bytes. Nothing here guarentees
that the *end* of the object will be such that another object straight
after it in memory (which is what the multiplication implies) will be
correctly aligned. Many structs would give appropriately odd lengths;
I'm sure you don't need examples.

I admit I jumped too fast on int *, which is OK (probably, on most
modern machines), and I don't have a copy of the standard. Can anyone
quote chapter and verse invalidating this argument (please)?
-- 
* Windsinger                 * "Nothing is forgotten..."
* rmj@islay.tcom.stc.co.uk   *                    Mike Whitaker
*     or (occasionally)      * "...except sometimes the words"
* rmj10@phx.cam.ac.uk        *                    Phil Allcock

volpe@underdog.crd.ge.com (Christopher R Volpe) (08/30/90)

In article <1912@islay.tcom.stc.co.uk>, rmj@tcom.stc.co.uk (Rhodri
James) writes:
|>In article <11245@crdgw1.crd.ge.com> volpe@underdog.crd.ge.com
(Christopher R Volpe) writes:
|>>First, malloc doesn't know or care (and couldn't find out if it wanted
|>>to) whether the argument being passed in is a constant expression
|>>(like sizeof(anything)) or an expression computed at runtime via
|>>a multiplication. My copy of K&R II says (section 7.8.5) that the
|>>pointer returned by malloc or calloc has proper alignment for the
|>>object in question. My manpage (SunOS 4.0.?) says that calloc USES
|>>malloc to allocate the storage, and then initializes it to zeros.
|>
|>Yes, K&R 2 says the *pointer* has proper alignment for the object in
|>question, by taking the most restrictive possibility, and I wouldn't be
|>surprised if calloc were implemented by using malloc. However, note the
|>emphasis and read on...
|>
|>>[...] the value produced [by sizeof(int *[xL]) if it were legal]
would be the
|>>same as (xL * sizeof(int *)), so malloc wouldn't know the difference.
|>
|>This is not guarenteed true for all types by anything I can find in K&R 2.

You can find it in K&R2 in sec. 6.3 (page 135 in my copy). It says, 
"The size of the array is the size of one entry times the number
of entries, so the number of entries is just 
     sizeof(keytab)/sizeof(struct key)
...
Another way to write this is to divide the array size by the size of
a specific element...
     sizeof(keytab)/sizeof(keytab[0]) "


|>The crux of the potential health hazard comes with the definition of
|>sizeof, which K&R2 says (section 6.3) gives a size_t result equal to the
|>size of the specified object or type in bytes. Nothing here guarentees
|>that the *end* of the object will be such that another object straight
|>after it in memory (which is what the multiplication implies) will be
|>correctly aligned. Many structs would give appropriately odd lengths;
|>I'm sure you don't need examples.

They would have to be padded by the compiler to make the above statement
(Sec 6.3) work out correctly. 
                                               
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

bruce@seismo.gps.caltech.edu (Bruce Worden) (08/31/90)

In article <1912@islay.tcom.stc.co.uk> rmj@htc1.UUCP (Rhodri James) writes:
[material deleted]
>The crux of the potential health hazard comes with the definition of
>sizeof, which K&R2 says (section 6.3) gives a size_t result equal to the
>size of the specified object or type in bytes. Nothing here guarentees
>that the *end* of the object will be such that another object straight
>after it in memory (which is what the multiplication implies) will be
>correctly aligned. Many structs would give appropriately odd lengths;
>I'm sure you don't need examples.

Actually, examples would be nice, since I don't see what you mean. 
On a machine requiring alignment:

struct thingy {
	char a;
	}

sizeof(struct thingy) is 1.

struct thingy {
	int i;	/* four byte ints */
	}

sizeof(struct thingy) is 4.

struct thingy {
	int i;
	char a;
	}

sizeof(struct thingy) is 8.  The structure is padded to insure that 
alignment is maintained.

> ... Can anyone
>quote chapter and verse invalidating this argument (please)?

I don't know what the standard says about the issue (if anything), but it 
is difficult to imagine a serious vendor shipping a system that required 
more than single byte alignment and in which the structure in the last 
example was size 5.  It is not so much a question of the standard, but, 
rather, one of functionality. 
--------------------------------------------------------------------------
C. Bruce Worden                            bruce@seismo.gps.caltech.edu
252-21 Seismological Laboratory, Caltech, Pasadena, CA 91125

henry@zoo.toronto.edu (Henry Spencer) (08/31/90)

In article <1912@islay.tcom.stc.co.uk> rmj@htc1.UUCP (Rhodri James) writes:
>The crux of the potential health hazard comes with the definition of
>sizeof, which K&R2 says (section 6.3) gives a size_t result equal to the
>size of the specified object or type in bytes. Nothing here guarentees
>that the *end* of the object will be such that another object straight
>after it in memory (which is what the multiplication implies) will be
>correctly aligned...

Please take a long hard look at section A7.4.8 of K&R2.  The numbered
chapters, useful though they are, are *not* meant as a precise definition
of the language; they are a tutorial.  Appendix A is the reference manual.

Actually, if you want a definitive reference you have to look at the ANSI
C standard itself, but in fact K&R2 A7.4.8 clears this issue up quite
satisfactorily.
-- 
TCP/IP: handling tomorrow's loads today| Henry Spencer at U of Toronto Zoology
OSI: handling yesterday's loads someday|  henry@zoo.toronto.edu   utzoo!henry

gordon@sneaky.UUCP (Gordon Burditt) (09/02/90)

>>[...] the value produced [by sizeof(int *[xL]) if it were legal] would be the
>>same as (xL * sizeof(int *)), so malloc wouldn't know the difference.
>
>This is not guarenteed true for all types by anything I can find in K&R 2.
>The crux of the potential health hazard comes with the definition of
>sizeof, which K&R2 says (section 6.3) gives a size_t result equal to the
>size of the specified object or type in bytes. Nothing here guarentees
>that the *end* of the object will be such that another object straight
>after it in memory (which is what the multiplication implies) will be
>correctly aligned. Many structs would give appropriately odd lengths;
>I'm sure you don't need examples.

ANSI C standard 3.3.3.4 "The sizeof operator":
...
Another use of the sizeof operator is to compute the number of members
in an array:
	sizeof array / sizeof array[0]

end quote


Set '=' to mean mathematical equation, not C assignment.
Set '/' to mean C integer division.

If you have an array of structs, then:
    number_elements = sizeof array / sizeof array[0]
If the array is some structs plus external padding (the total padding in the
whole array),
    sizeof array = number_elements * sizeof struct foo + external_padding_bytes
Substituting,
    number_elements = ((number_elements * sizeof struct foo) + 
	external padding bytes) / sizeof struct foo

    number_elements = number_elements + 
	external_padding_bytes / sizeof struct foo

    0 = external_padding_bytes / sizeof struct foo

If you make the dimension of the array much larger than sizeof struct foo,
then the total number of external padding bytes in the array must be
much less than one per array element.

This pretty much kills the alignment argument.  Sizeof must include
trailing padding and internal padding in a structure.  And there
cannot be any *LEADING* padding for other reasons.

					Gordon L. Burditt
					sneaky.lonestar.org!gordon