[comp.lang.c] Dynamically malloc

phaedra@blake.acs.washington.edu (J. Anderson) (12/24/88)

	I have a small C syntax problem.  Given I have a structure of
with the following nature:

struct xyzzy {
	int plugh;
	long black_rod;
	char *foobar;	/* This wants to be a pointer to a variable-length
			 * array
			 */
}

	I have tried various means of doing a malloc which _should_ (I
think?) assign a memory value to foobar, but to no avail.  K&&R
doesn't have a lot to say on this subject, nor does volume 5 of the
Unix Programmer's Reference manual.  Is there a way to accomplish what
I wish to do, or have I found a minor limitation in C?

-- 
There are two major products that come out of Berkeley: LSD and UNIX.  We don't
believe this to be a coincidence. ||  phaedra@blake.acs.washington.edu

ark@alice.UUCP (Andrew Koenig) (12/24/88)

In article <448@blake.acs.washington.edu>, phaedra@blake.acs.washington.edu (J. Anderson) writes:
> struct xyzzy {
> 	int plugh;
> 	long black_rod;
> 	char *foobar;	/* This wants to be a pointer to a variable-length
> 			 * array
> 			 */
> }

Nothing particularly hard about this, except that you must
allocate two separate areas of memory, one for an `xyzzy' object
and one for the character array addressed by `foobar'.  The
`xyzzy' object may be a local variable, of course:

	struct xyzzy a;
	a.foobar = malloc(n);

If you want the `xyzzy' object to be dynamic as well, do this:

	struct xyzzy *p;
	p = (struct xyzzy *) malloc (sizeof(struct xyzzy));
	p->foobar = malloc(n);

To free it, reverse the process:

	free(p->foobar);
	free(p);

What's the problem?
-- 
				--Andrew Koenig
				  ark@europa.att.com

rkl1@hound.UUCP (K.LAUX) (12/26/88)

In article <448@blake.acs.washington.edu>, phaedra@blake.acs.washington.edu (J. Anderson) writes:
> 
> 	I have a small C syntax problem.  Given I have a structure of
> with the following nature:
> 
> struct xyzzy {
> 	int plugh;
> 	long black_rod;
> 	char *foobar;	/* This wants to be a pointer to a variable-length
> 			 * array
> 			 */
> }
> 

	Try:

#include	<malloc.h>	/* or whatever include file your system has */

	struct	xyzzy	s;

	s.foobar	= (char *) malloc (nbytes);

	if (s.foobar == NULL) {		/* don't forget to test for failure */
		/* Error */
	}

--rkl

chuck@Morgan.COM (chuck) (12/29/88)

In article <448@blake.acs.washington.edu> phaedra@blake.acs.washington.edu (J. Anderson) writes:
>
>	I have a small C syntax problem.  Given I have a structure of
>with the following nature:
>
>struct xyzzy {
>	int plugh;
>	long black_rod;
>	char *foobar;	/* This wants to be a pointer to a variable-length
>			 * array
>			 */
>}
>	I have tried various means of doing a malloc which _should_ (I
>think?) assign a memory value to foobar, but to no avail.  K&&R
>doesn't have a lot to say on this subject, nor does volume 5 of the
>Unix Programmer's Reference manual.  Is there a way to accomplish what
>I wish to do, or have I found a minor limitation in C?
>

I have two interpretations of the problem and therefore 2 answers.

1) The first is the most obvious:

  struct xyzzy dumb;
	    :
  dumb.foobar = malloc(N_NUMBER_OF_CHARS);

This allocates however many bytes you want for the foobar member to point to.
You can easily reallocate using realloc().

2) If you want to allocate the structure and the variable size foobar member
in 1 shot, try changing the struct definition as follows:

  struct xyzzy {
    int plugh;
    long black_rod;
    char foobar[1];	/* The bytes for foobar are contiguous
			 * with the rest of the structure
			 */
  };

Now, if you want to allocate a struct xyzzy with N_ELEMENTS
elements in the foobar array, do the following:

  struct xyzzy *dump;
	    :
  dump = (struct xyzzy *)malloc(sizeof(*dump) + (N_ELEMENTS-1) * sizeof(char));

This allocates the enough memory to hold the structure (sizeof(*dump)) plus
the remaining elements of foobar ((N_ELEMENTS-1) * sizeof(char)).  In fact
on many machines which promote allcoations to longword boundaries this might
allocate a few extra bytes so further optimization can be achived by computing
the offset of foobar within the struct etc...  To reallocate the foobar
array the entire struct must be reallocated.

This technique is used by the System V message queue interface.  The msgbuf
struct is declared as:

  struct msgbuf {
    long	mtype;
    char	mtext[1];
  };

Zardoz Ocheret

-- 
+------------------+   Chuck Ocheret, Sr. Staff Engineer   +------------------+
| chuck@morgan.com |       Morgan Stanley & Co., Inc.      |  (212)703-4474   |
|   Duty now ...   |19th Floor, 1251 Avenue of the Americas| for the future.  |
+------------------+         New York, N.Y.  10020         +------------------+