C arrays and pointers - c

Just started to learn C language.
I have a pointer array int *parr and I need to fill it with random numbers and then do some other things with it.
But I even don't understand how to fill it with random numbers. I tried something like this, but it hangs the program:
for(i=0 ; i<R ; i++)
{
for(j=0 ; j<C; j++)
{
*(parr+i*C+j)=rand() % 10;
printf("%d",*(parr+i*C+j));
}
printf("\n");
}

The way you initialize it, you probably have to malloc memory like this:
parr = malloc(R * C * sizeof(*parr));

int *parr;
just defines a pointer to a n integer, but there's no storage associated with it. You could either
int parr[sizeofarray];
or
int *parr = calloc (sizeofarray, sizeof(int));
to obtain the right amount of storage.
based on your example sizeofarray should be at least R * C.

Related

Mallocing a 3 dimensions array

I have to use a 3 dimensions array because I want to divide a pic into squares and store the average of the RGB of each square in my array.
I want it to be this size, tab[height][width][3],
so I did that:
i = 0; j = 0; k = 0;
float*** tab;
tab = malloc((hauteur+1)*sizeof(float*));
while(i <= hauteur){
tab[i] = malloc((largeur+1)*sizeof(float**) );
i++;
}
i = 0;
while(i <= hauteur){
j = 0;
while (j <= largeur){
tab[i][j] = malloc(3*sizeof(float***));
j++;
}
i++;
}
but I have a segfault after : tab[1][30][2];.
Is there a problem in my malloc?
It's strange because it doesn't segfault when I declare tab using:
tab[hauteur][largeur][3].
(Sorry: "hauteur" means "height" in French and "largeur" means "width".)
(If you think you need to check my whole function: http://pastebin.com/eqQXz8Ad; it's a writer for a JPEG file.)
Your types aren't right in your malloc calls. I'd suggest the following:
tab = malloc( (hauteur + 1) * sizeof *tab ); // sizeof (float **)
tab[i] = malloc( (largeur + 1) * sizeof *tab[i] ); // sizeof (float *)
tab[i][j] = malloc( 3 * sizeof *tab[i][j] ); // sizeof (float)
Given the declaration of tab, the following are all true:
Expression Type
---------- ----
tab float ***
*tab float **
tab[i] float **
*tab[i] float *
tab[i][j] float *
*tab[i][j] float
I usually recommend taking the sizeof of the target expression, rather than an explicit type; that way, if you ever change the type of tab (from float to double, for example), you never have to touch the malloc calls.
What you are crafting is basically an array of array of array of pointers to float, not a three dimensional array of floats.
You may want have a look at this Ambiguity in 2d array declaration in C. It works out a similar problem with a bidimensional array.
Maybe the solution for your problem can looks like:
float (*tab)[hauteur][largeur][3]; //declare a pointer to a real array
tab = malloc(hauteur * largeur * 3 * sizeof(float)); //Allocate room for threedimensional array
for (int i=0; i<hauteur; i++)
for (int j=0; j<largeur; j++)
for (int k=0; k<3; k++)
{
(*tab)[i][j][k] = (float)((i*100)+j*1000+k); //Fill elements with something using threedimensional subscripting
}
for (int i=0; i<hauteur; i++)
for (int j=0; j<largeur; j++)
for (int k=0; k<3; k++)
{
printf("[%d][%d][%d]=%f\n", i, j, k, (*tab)[i][j][k]); //Check back data...
}
EDITED
Looking at comments I see that it is someway 'unnatural' to access an array using the pointer to array notation (*array)[a][b]...[n] even if this notation explicitly report whole dimensions in declaration. To make more friendly the usage you can use the form below that allows the well known format:
#include <stdio.h>
#include <stdlib.h>
int largeur = 10;
int hauteur = 10;
int main(int argc, char *argv[])
{
float (*tab)[largeur][3]; //declare a bidimensional array of pointers to our variable
//this fools the compiler acting as a one more dimension array of variable
tab = malloc(hauteur * largeur * 3 * sizeof(float)); //Allocate room for threedimensional array
for (int i=0; i<hauteur; i++)
for (int j=0; j<largeur; j++)
for (int k=0; k<3; k++)
{
tab[i][j][k] = (float)((i*100)+j*1000+k); //Fill elements with something using threedimensional subscripting
//This use the natural addressing...
}
for (int i=0; i<hauteur; i++)
for (int j=0; j<largeur; j++)
for (int k=0; k<3; k++)
{
printf("[%d][%d][%d]=%f\n", i, j, k, tab[i][j][k]); //Check back data...
}
}
This kind of trick works because of the lack of multidimensional array concept in C language.
C knows only of array, or better it should have been string, of something, so a bidimensional array is simply an array of arrays of something. If we add one more dimension it is an array of an array of an array of something ... and so on for each more dimension we add.
This defines the memory layout of arrays in C and the addressing method that the compiler uses to access data. Because the data is streamed in memory to access a value at a specific subscript the compiler need to compute the space used for all dimensions but the very first.
+++ I fixed a bug, now the sample can be compiled under any C99-C11 compliant compiler and works.
If you care a lot about efficiency, you should consider having a single dimension array (like in Frankie_C's answer):
int height = something_to_compute_height();
int width = something_to_compute_width();
double *arr = malloc(height*width*3*sizeof(double));
if (!arr) { perror("malloc"); exit(EXIT_FAILURE); }
(as an aside, even if we both are native French speakers, let's try to use English in questions and code here)
then you might define a macro to ease speaking of some element inside arr
#define ELEM_ARR(a,i,j,k) a[i*width*height+j*width+k]
#define ARR(i,j,k) ELEM_ARR(arr)
(You've got the idea, details can be different)
This is probably more efficient than your array of pointers to array of pointers because of cache locality and because you need only one single allocation.
Choose carefully row-major or column-major access to fit the most frequent access patterns.
If height & width are specific to each array, you could use some flexible array member as last in a struct.
As a rule of thumb, it is useful in C to use multidimensional arrays only if all the dimensions (except perhaps the last) are a compile-time constant, e.g. double arr3d[3][4][5];; otherwise, better have a single-dimension array and do the index computing by yourself.
BTW, if you care a lot about performance, you might be concerned by OpenCL and OpenMP (and both usually prefer single-dimensional arrays).

function to get 2d-arrays from stack and heap

Consider a simple struct, Foo, which contains a pointer to some other strucrt, Baz. and a two-dimensional array, (stack-allocated):
Foo arr[ARR_SIZE][ARR_SIZE];
Next, consider a function which mallocs (in the heap, obviously) a memory for a new 2d-array of Foos. A code snippet:
Foo** arr_copy = malloc(sizeof(Foo*) * ARR_SIZE);
for (int i = 0; i < ARR_SIZE; i++)
{
arr_copy[i] = malloc(sizeof(Foo) * ARR_SIZE);
}
for (int i = 0; i < ARR_SIZE; i++)
{
for (int j = 0; j < ARR_SIZE; j++)
{
arr_copy[i][j].baz = malloc_baz();
}
}
Now, in my project I have various of functions which need to handle both the original array (stack allocated) and the copy (which is heap-allocated)
Problem is, things got quirky (memory looks corrupted) when I passed the copy to some function which iterate the 2d-array and print some info.
Basically, I know that there should not be a difference between: void fun(Foo** arr) to void fun(Foo arr[ARR_SIZE][ARR_SIZE]) but both ways were problematic.
So my question is, how can a function handle both arrays, stack/heap allocated?
Thanks.
If you try to do this in c or c++:
int test[][];
you will get this error:
error: declaration of 'test' as multidimensional array must have bounds for all dimensions except the first
This is because test is not in fact a double ponter as you'd expect. But the compiler converts it into a single block of data. And this:
int test[XSIZE][YSIZE];
int n = test[x][y];
will be converted into something like this:
int test[XSIZE*YSIZE];
n = test[YSIZE*x + y];
For solving this, i think #BLUEPIXY already put a solution in the comments.
Also, have a look at this question.

Allocate a matrix in C using malloc

I wrote a C code that usea a matrix of double:
double y[LENGTH][4];
whith LENGTH=200000 I have no problem.
I have to increase the numbers of rows to LENGTH=1000000 but when I enter this value and execute the program it returns me segmentation fault.
I tried to allocate more memory using malloc:
double **y = (double **)malloc(LENGTH * sizeof(double*));
for(int i = 0; i < LENGTH; i++){
y[i] = (double *)malloc(4 * sizeof(double));
}
I run the the code above and after some second of calculations it still gives me "segmentation fault".
Could anyone help me?
If you want a dynamic allocated 2D array of the specified row-width, just do this:
double (*y)[4] = malloc(LENGTH * sizeof(*y));
There is no need to malloc each row in the matrix. A single malloc and free will suffice. Only if you need dynamic row width (each row can vary in width independent of others) or the column count is arbitrary should a nested malloc loop be considered. Neither appears to be your case here.
Notes:
Don't cast malloc in C programs
Be sure to free(y); when finished with this little tryst.
The reason your statically allocated array is segfaulting with a million elements is (presumably) because it's being allocated on the stack. To have your program have a larger stack, pass appropriate switches to your compiler.
ProTip: You will experience less memory fragmentation and better performance if you flip your loop around, allocating
(double *)malloc(LENGTH * sizeof(double));
four times. This will require changing the order of your indices.
I ran the the code with this definition and after some second of calculations it still gives me "segmentatin fault"
If you're getting a segmentation fault after allocating the memory, you're writing outside of your memory bounds.
I run this code
#include <stdio.h>
#include <stdlib.h>
// We return the pointer
int **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i, **table;
table = malloc(N*sizeof(int *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(int) );
return table;
}
void free2Darray(int** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
int main(void)
{
const int LENGTH = 1000000;
int **p;
p = get(LENGTH, 4);
printf("ok\n");
free2Darray(p ,LENGTH);
printf("exiting ok\n");
return 0;
}
and it was executed normally.
I got the code from my pseudo-site.
You should not cast what malloc returns. Why?
Also notice, that since you need a dynamic allocation only for the number of rows, since you know the number of columns. So, you can modify the code yourself (so that you have some fun too. :) )
I hope you didn't forget to **free** your memory.

find middle point in c array

I am studying C programming. I want to find a middle point of array without knowing about length of it. If length of array is 6, middle point must be 4th, but I have an error and I don't know what it is. Here is my code:
int *a =(int *) malloc(sizeof(int) * n);
int i;
for( i = 0; i < sizeof(a); i++)
scanf("%d",&a[i]);
Anyone can help, thank you.
scanf is reading into an address, so:
scanf("%d",a[i])
should really be:
scanf("%d", &a[i])
And do not forget to free the memory when you're done. (For tiny applications like this it does not matter, but it is a good habit if you get used to it when you are stepping out from the learning phase and getting into the real life programming)
And also: sizeof(a) is the size of the pointer, not the size of the memory allocated the pointer points to (as correctly pointed out in the other answer).
This is wrong: for( i = 0; i < sizeof(a); i++). Here sizeof(a) will return size of the int pointer, likely 4 or 8 on your system. In general, don't use sizeof to determine the element count of an array, use separate variable instead.
You'll want to use for( i = 0; i < n; i++) instead.

Is this code doing what I want it to do?

I want to create an integer pointer p, allocate memory for a 10-element array, and then fill each element with the value of 5. Here's my code:
//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
printf("Current value of array: %p\n", *p);
*p += sizeof(int);
i += sizeof(int);
}
I've added some print statements around this code, but I'm not sure if it's actually filling each element with the value of 5.
So, is my code working correctly? Thanks for your time.
First:
*p += sizeof(int);
This takes the contents of what p points to and adds the size of an integer to it. That doesn't make much sense. What you probably want is just:
p++;
This makes p point to the next object.
But the problem is that p contains your only copy of the pointer to the first object. So if you change its value, you won't be able to access the memory anymore because you won't have a pointer to it. (So you should save a copy of the original value returned from malloc somewhere. If nothing else, you'll eventually need it to pass to free.)
while (i < sizeof(array)){
This doesn't make sense. You don't want to loop a number of times equal to the number of bytes the array occupies.
Lastly, you don't need the array for anything. Just remove it and use:
int *p = malloc(10 * sizeof(int));
For C, don't cast the return value of malloc. It's not needed and can mask other problems such as failing to include the correct headers. For the while loop, just keep track of the number of elements in a separate variable.
Here's a more idiomatic way of doing things:
/* Just allocate the array into your pointer */
int arraySize = 10;
int *p = malloc(sizeof(int) * arraySize);
printf("Size of array: %d\n", arraySize);
/* Use a for loop to iterate over the array */
int i;
for (i = 0; i < arraySize; ++i)
{
p[i] = 5;
printf("Value of index %d in the array: %d\n", i, p[i]);
}
Note that you need to keep track of your array size separately, either in a variable (as I have done) or a macro (#define statement) or just with the integer literal. Using the integer literal is error-prone, however, because if you need to change the array size later, you need to change more lines of code.
sizeof of an array returns the number of bytes the array occupies, in bytes.
int *p = (int *)malloc( sizeof(array) );
If you call malloc, you must #include <stdlib.h>. Also, the cast is unnecessary and can introduce dangerous bugs, especially when paired with the missing malloc definition.
If you increment a pointer by one, you reach the next element of the pointer's type. Therefore, you should write the bottom part as:
for (int i = 0;i < sizeof(array) / sizeof(array[0]);i++){
*p = 5;
p++;
}
*p += sizeof(int);
should be
p += 1;
since the pointer is of type int *
also the array size should be calculated like this:
sizeof (array) / sizeof (array[0]);
and indeed, the array is not needed for your code.
Nope it isn't. The following code will however. You should read up on pointer arithmetic. p + 1 is the next integer (this is one of the reasons why pointers have types). Also remember if you change the value of p it will no longer point to the beginning of your memory.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define LEN 10
int main(void)
{
/* Allocate memory for a 10-element integer array. */
int array[LEN];
int i;
int *p;
int *tmp;
p = malloc(sizeof(array));
assert(p != NULL);
/* Fill each element with the value of 5. */
printf("Size of array: %d bytes\n", (int)sizeof(array));
for(i = 0, tmp = p; i < LEN; tmp++, i++) *tmp = 5;
for(i = 0, tmp = p; i < LEN; i++) printf("%d\n", tmp[i]);
free(p);
return EXIT_SUCCESS;
}
//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
At this point you have allocated twice as much memory -- space for ten integers in the array allocated on the stack, and space for ten integers allocated on the heap. In a "real" program that needed to allocate space for ten integers and stack allocation wasn't the right thing to do, the allocation would be done like this:
int *p = malloc(10 * sizeof(int));
Note that there is no need to cast the return value from malloc(3). I expect you forgot to include the <stdlib> header, which would have properly prototyped the function, and given you the correct output. (Without the prototype in the header, the C compiler assumes the function would return an int, and the cast makes it treat it as a pointer instead. The cast hasn't been necessary for twenty years.)
Furthermore, be vary wary of learning the habit sizeof(array). This will work in code where the array is allocated in the same block as the sizeof() keyword, but it will fail when used like this:
int foo(char bar[]) {
int length = sizeof(bar); /* BUG */
}
It'll look correct, but sizeof() will in fact see an char * instead of the full array. C's new Variable Length Array support is keen, but not to be mistaken with the arrays that know their size available in many other langauges.
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
*p += sizeof(int);
Aha! Someone else who has the same trouble with C pointers that I did! I presume you used to write mostly assembly code and had to increment your pointers yourself? :) The compiler knows the type of objects that p points to (int *p), so it'll properly move the pointer by the correct number of bytes if you just write p++. If you swap your code to using long or long long or float or double or long double or struct very_long_integers, the compiler will always do the right thing with p++.
i += sizeof(int);
}
While that's not wrong, it would certainly be more idiomatic to re-write the last loop a little:
for (i=0; i<array_length; i++)
p[i] = 5;
Of course, you'll have to store the array length into a variable or #define it, but it's easier to do this than rely on a sometimes-finicky calculation of the array length.
Update
After reading the other (excellent) answers, I realize I forgot to mention that since p is your only reference to the array, it'd be best to not update p without storing a copy of its value somewhere. My little 'idiomatic' rewrite side-steps the issue but doesn't point out why using subscription is more idiomatic than incrementing the pointer -- and this is one reason why the subscription is preferred. I also prefer the subscription because it is often far easier to reason about code where the base of an array doesn't change. (It Depends.)
//allocate an array of 10 elements on the stack
int array[10];
//allocate an array of 10 elements on the heap. p points at them
int *p = (int *)malloc( sizeof(array) );
// i equals 0
int i = 0;
//while i is less than 40
while (i < sizeof(array)){
//the first element of the dynamic array is five
*p = 5;
// the first element of the dynamic array is nine!
*p += sizeof(int);
// incrememnt i by 4
i += sizeof(int);
}
This sets the first element of the array to nine, 10 times. It looks like you want something more like:
//when you get something from malloc,
// make sure it's type is "____ * const" so
// you don't accidentally lose it
int * const p = (int *)malloc( 10*sizeof(int) );
for (int i=0; i<10; ++i)
p[i] = 5;
A ___ * const prevents you from changing p, so that it will always point to the data that was allocated. This means free(p); will always work. If you change p, you can't release the memory, and you get a memory leak.

Resources