1. ## correct malloc use

Hi all,
I 'm having a bit of trouble understanding about the use of malloc for 1d and 2d arrays., and I would appreciate if someone could tell me what is correct. Lets say for 1d arrays, which is correct?

vector = malloc(length*sizeof(vector));
or
vector = malloc(length*sizeof(*vector));
and for 2d arrays:
Code:
matrix=malloc(rows*sizeof(matrix));
for (i=0; i<columns; i++)
matrix[i]=malloc(columns*sizeof(matrix[i]));
or
Code:
matrix=malloc(rows*sizeof(*matrix));
for (i=0; i<columns; i++)
matrix[i]=malloc(columns*sizeof(*matrix[i]));
I've tried both with gcc and all warnings/pedantic flags on, but both produce the same result (and no warnings) when I put some values in vector and array and then display them.

I've also seen (assuming vector and matrix are unsigned integers
Code:
vector = malloc(length*sizeof(unsigned int*))
and
Code:
matrix=malloc(rows*sizeof(unsigned int *));
for (i=0; i<columns; i++)
matrix[i]=malloc(columns*sizeof(unsigned int));
Ideally I'd like to avoid this in case I want to chenge the type of vector or matrix eg from float to double.

Thank you
Spiros

2. what is vector?
Code:
const int SIZE = 10;
int *vector;
vector = malloc(SIZE*sizeof(int));
I'm a little rusty myself, but I think that's correct.

3. is it posible to use
Code:
const int SIZE = 10;
int *vector;
vector = malloc(SIZE*sizeof(vector));
Code:
const int SIZE = 10;
int *vector;
vector = malloc(SIZE*sizeof(int));
?

4. In both cases, the second is correct (I'm assuming your declarations look something like int *vector and int **matrix). For your 1d array, since you're creating an array of (say) ints, you want to multiply the length by the size of an int, not a pointer. The 2d array is similar, only first you create an array of pointers to int, and then you create arrays of ints.
Code:
int *vector;
sizeof vector;     /* size of a pointer to int, because that's what vector is */
sizeof *vector;    /* size of an int, because that's what *vector is */
int **matrix;
sizeof matrix;     /* pointer to pointer to int */
sizeof *matrix;    /* pointer to int */
sizeof *matrix[i]; /* int; same thing as sizeof **matrix */
I would not recommend using the type name with sizeof for the reason you mentioned. Why make it so you have to change the type twice? Less of a chance for a problem this way.

Also, your 2d allocation is incorrect: If you allocate "rows * sizeof *matrix" then you should be doing "for(i = 0; i < rows; i++)", because that's how many you just allocated. If columns is greater than rows, your code writes outside of your allocated memory area. If it's smaller than rows, then you have uninitialized elements.

5. >> I've tried both with gcc and all warnings/pedantic flags on, but both produce the same result (and no warnings) when I put some values in vector and array and then display them.

that's because sizeof( int ) == sizeof( int * ) on your system, naturally. for clarity, you should consider using that standard syntax for now, eg:

Code:
int * ptr = malloc( count * sizeof( int ) );

int ** mtx = malloc( rows * sizeof( int * ) );
for( int i = 0; i < rows; i++ )
mtx[ i ] = malloc( columns * sizeof( int ) );

6. thanks cas, I'm now trying to get my head round what you've posted... pointers are a pain!

As for the loop going over the columns, that's my mistake being too quick, it should go over "rows"

Sebastiani, I have seen this way of allocating arrays that you've posted, and I could do it this way, but I think that if I write for example
Code:
sizeof(ptr)
then I could change the type of ptr with one edit rather than two (one in declaration, and the other inside the sizeof). Is this way really non-standard syntax, because if it is then I'll try to get used to malloc as you suggested.

7. oh there's nothing wrong with that syntax, but if it's causing you so much confusion then why do it that way?

8. I'm just trying to learn by trying different things. Unfortunately the books I've borrowed from my library are not very clear and therefore things in my head are not clear as well, but fortunately you guys are really helpful.

thanks!

9. I'm now having another problem with how much memory is allocated
Code:
double *vec_y;
unsigned int nrows;

vec_y = malloc(nrows*sizeof(*vec_y));
for (i=0; i<nrows; i++) {
vec_y[i]=(double )i;
printf("\nvec_y[%i]=%f", i, vec_y[i]);
}
If I increase the for loop to eg 2*nrows like:
Code:
double *vec_y;
unsigned int nrows;

vec_y = malloc(nrows*sizeof(*vec_y));
for (i=0; i<2*nrows; i++) {
vec_y[i]=(double )i;
printf("\nvec_y[%i]=%f", i, vec_y[i]);
}
then the printf statement just carries on printing i, and vec_y (being the same value as i) like I allocated 2*nrows*sizeof(*vec_y). This should not happen as I'm deliberately going out of the bounds of vec_y allocated by memory, yet I'm getting no errors during compilation or run time. Why does this happen?

10. Code:
double *vec_y;
unsigned int nrows;

vec_y = malloc(nrows*sizeof(*vec_y));
for (i=0; i<2*nrows; i++) {
vec_y[i]=(double )i;
printf("\nvec_y[%i]=%f", i, vec_y[i]);
}
then the printf statement just carries on printing i, and vec_y (being the same value as i) like I allocated 2*nrows*sizeof(*vec_y). This should not happen as I'm deliberately going out of the bounds of vec_y allocated by memory, yet I'm getting no errors during compilation or run time. Why does this happen?
First, I assume that nrows is initialized somewhere before it is used in the call to malloc()? Then, what you are seeing is that in fact, C does not perform any type of bounds checking. You can read beyond the end of an array, as well as assign values beyond its bounds. Powerful and dangerous if you aren't careful.

Try this out this little bit of code:
Code:
char str[5] = "test";
int i = 1;

printf("str=%s\ti=%d\n", str, i);

strcpy(str, "This is sure more than 5 characters!");

printf("str=%s\ti=%d\n", str, i);
Can you explain what happened?

11. > yet I'm getting no errors during compilation or run time. Why does this happen?
Luck (for now).
Call malloc again, and your luck might go down somewhat.
Call free on the original pointer, that's a further decrease in luck.
Sooner or later, you're looking down the barrel of a segmentation fault in an unrelated part of the program wondering "WTF!!?"

Oh, and
p = malloc( howmany * sizeof *p );
ALWAYS works.
Let the compiler do the work.
No second looks back at how p was declared, or how many *s it has.