1

i have a simple structure:

typedef struct {
    int test;
} struct1_t;


typedef struct {
struct1_t** tests;
} struct2_t;


struct2_t *str
for(i=0;i<1000;i++) {
    (str->tests)[i]=(test1_t *) malloc(sizeof(test1_t));
    (str->tests)[i]->test = i;
}

How to know exist str->tests)[i] element on not ?

 if (str->tests)[i] != NULL 

call Segmentation failed :).

Bdfy
  • 23,141
  • 55
  • 131
  • 179
  • you must remember how much you allocated to struct->tests, there is no simple way of getting this boundary at runtime, save a size value in the struct containing the list – IanNorton Aug 22 '11 at 10:14
  • Don't cast the return value of `malloc()`: http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – makes Aug 22 '11 at 11:11

5 Answers5

3

Simply put, you can't. There is no way to know the length of an array in C, you have to keep track of it manually as your array changes or grows.

Charles Ma
  • 47,141
  • 22
  • 87
  • 101
1

C arrays are really just blocks of memory, so what you really want to do as add a field to your structs that keeps track of how much space has been allocated and make sure you initialize everything to sane values. You also have to be careful when using pointers of structs containing to pointers to pointers of structs, since in your example you failed to properly allocate memory for everything.

Try this:

typedef struct {
    int test;
} test_t;

typedef struct {
    test_t* tests; /* We only need a regular pointer here */
    size_t numtests;    /* This is so we know how many tests we allocated */
} mystruct_t;


/* .... Now skip to the actual usage: */

mystruct_t *str;
int i;

str = malloc(sizeof(mystruct_t)); /* Remember to allocate memory for
                                     the container! */
str->numtests = 1000; /* Set our size inside the container and use it! */

/* Now to allocate an array of tests, we only need to allocate
   a single chunk of memory whose size is the number of tests 
   multiplied by the size of each test: */
str->tests = malloc(sizeof(test_t)*str->numtests);

/* Now let's initialize each test: */
for (i=0; i<str->numtests; i++) { /* Notice we use str->numtests again! */
    str->tests[i]->test = 1; /* Notice we don't need all the extra
                                parenthesese. This is due to the operator
                                precedence of [] and -> */
}

Now when you need to see if a test element exists, you can just see if the index is within the size of the container:

if (i >= 0 && i < str->numtests) {
  str->tests[i]->test = 2; /* This code only runs if the index would exist. */
}

But that means you have to take care to always initialize str->numtests to be a sane value. For example, with no allocated tests:

mystruct_t *str = malloc(sizeof(mystruct_t));
/* Initialize the container to sane starting values! */
str->tests = NULL;
str->numtests = 0;

And that's how you know if something exists -- you keep track of it inside the structures you define. That's because C code maps very directly to assembly language, and C structs and arrays map very directly to bits and bytes in computer memory, so if you want to maintain meta information like how many elements are inside your array, you have to make room for that information and store it yourself.

James O'Doherty
  • 2,186
  • 13
  • 14
0

It is pretty fundamental that you can't do it this way in C. Your struct2_t would need an extra field such as int no_of_tests, which you would update.

In fact to do what your trying to do there, you also need 2 mallocs -

struct2_t str;
str.tests = malloc( 1000 * sizeof(int) );
str.no_of_tests = 1000;
for(i=0;i<1000;i++) {
  str.tests[i] = malloc( sizeof(struct1_t) );
  str.tests[1]->test = i;
}
asc99c
  • 3,815
  • 3
  • 31
  • 54
0

There is nothing in the language to do this for you, you need to keep track yourself. A common solution is to make the last pointer in an arbitrary-size array of pointers be a NULL pointer, so you know to stop looping when you hit NULL.

tripleee
  • 175,061
  • 34
  • 275
  • 318
0

If your compiler supports _msize you can find out the size that you allocated. For example:

if (i < _msize((str->tests)/sizeof(test1_t))
    then i is valid and points to an element of the allocated array
noelicus
  • 14,468
  • 3
  • 92
  • 111