Unable to pass and retrieve array element? - c

Hi friends I am trying to assigned elements from arr2[] to a pointer p_arr and then trying to print from p_arr...
I think something is messing up, not getting expected values...
#include <stdio.h>
#include <stdlib.h>
#define MAX_ONE 9
#define MAX_TWO 9
int arr1[] = {10,20,30,40,50,67,23,47,79};
int arr2[] = {5,15,25,35,45,34,45,67,89};
int *main_arr[] = {arr1,arr2};
int main()
{
int i;
int *p_arr2;
p_arr2 = (int *)malloc(sizeof(int)*2);
for(i=0;i<MAX_ONE;i++)
{
*p_arr2++ = arr2[i];
arr2[i] = arr1[i];
}
for(i=0;i<MAX_TWO;i++)
{
printf("%d\n",*(p_arr2));
p_arr2++;
//printf("%d\t",arr2[i]);
}
system("PAUSE");
return 0;
}

p_arr2 = (int *)malloc(sizeof(int)*2);
You allocated only enough memory for 2 integers and you are trying to store MAX_ONE in this array. This results in writing beyond the allocated memory block and an Undefined behavior.
You need to allocated enough memory to store MAX_ONE elements.
p_arr2 = malloc(sizeof(int)*MAX_ONE);
^^^^^^^^^
Also, you do not need to cast the return type of malloc in C.

In addition to the allocation issues mentioned, before you start the print loop, you don't reset p_arr2 to point at the start of the array. So you're printing from uninitialized memory.

Try this. Also always try to free dynamically allocated memory
p_arr2 = malloc(sizeof(int)*MAX_ONE);
for(i=0;i<MAX_ONE;i++)
{
p_arr2[i] = arr2[i];
arr2[i] = arr1[i];
}
for(i=0;i<MAX_TWO;i++)
{
printf("%d\n",*(p_arr2 + i));;
//printf("%d\t",arr2[i]);
}
free (p_arr2);

Related

how to allocate arrays (in array of pointers) C -- can it be done in one line? with malloc

is there a simple one liner I can use in C to allocate arrays in (pointer of arrays)
This line creates 10 pointers of arrays
char *out[10];
I can't do this
char *out[100]=(char[10][100])malloc(sizeof(char)*10*100);
error: cast specifies array type
same error with
char *out[10]=(char*[10])malloc(sizeof(char)*10*100);
do I need to do it in loop like this
int main()
{
char *out[10];
int x=0;
while(x<10)
{
*(out+x)=malloc(sizeof(char)*100);// is this line correct?
x++;
}
*out[0]='x';
printf("%c\n",out[0][0]);
free(out);
return 0;
}
but this cause warning that
req.c:75:3: warning: attempt to free a non-heap object ‘out’ [-Wfree-nonheap-object]
75 | free(out);
so do I need to allocate and free each array in (array of pointers) in loop
Can't I do allocation and free arrays in array of pointer in one line instead of loop?
or is there anything thing in my loop wrong too
To allocate an array of pointers to strings, you need to do:
char** out = malloc(sizeof(char*[10]));
The whole point of using this form is that each pointer in that array of pointers can be allocated with individual size, as is common with strings. So it doesn't make sense to allocate such with a "one-liner", or you are using the wrong type for the task.
In case you don't need individual sizes but are rather looking for a char [10][100] 2D array with static size, then the correct way to allocate such is:
char (*out)[100] = malloc(sizeof(char[10][100]));
You can allocate the full array in one single step and have pointers inside that array:
char *out[10];
data = malloc(100); //sizeof(char) is 1 by definition
for (int x=0; x<10; x++) {
out[i] = data + x * 10;
}
*out[0] = 'x';
printf("%c\n",out[0][0]);
free(data); // you must free what has been allocated
int i;
char** out = (char**)malloc(sizeof(char*)*10);
for(i = 0; i<10;i++)
out[i] = (char*)malloc(sizeof(char)*100);
out[1][1] = 'a';
OR with same dimensions
#include <stdio.h>
#include <stdlib.h>
void main()
{
int r = 10, c = 100; //Taking number of Rows and Columns
char *ptr, count = 0, i;
ptr = (char*)malloc((r * c) * sizeof(char)); //Dynamically Allocating Memory
for (i = 0; i < r * c; i++)
{
ptr[i] = i + 1; //Giving value to the pointer and simultaneously printing it.
printf("%c ", ptr[i]);
if ((i + 1) % c == 0)
{
printf("\n");
}
}
free(ptr);
}

Segmentation fault when using sprintf in dynamically allocated array

I am converting integers to strings and adding them to a dynamically allocated array. The problem is that it is causing a segfault. I don't understand why it is happening.
#include <stdio.h>
#include <stdlib.h>
int main() {
char *x = malloc(10 * sizeof(char));
x[0] = malloc(10 * sizeof(char));
sprintf(x[0],"%d",10);
for(int i = 0; i < 10;i++){
free(x[i]);
}
free(x);
return 0;
}
To allocate an array whose elements are char*, the pointer to point the array should be char**, not char*.
Also you mustn't use values in buffer allocated via malloc() and not initiaized. The values are indeterminate and using them invokes undefined behavior.
#include <stdio.h>
#include <stdlib.h>
int main() {
/* correct type here (both variable and allocation size) */
char **x = malloc(10 * sizeof(char*));
x[0] = malloc(10 * sizeof(char));
sprintf(x[0],"%d",10);
/* initialize the other elements to pass to free() */
for (int i = 1; i < 10; i++) x[i] = NULL;
for(int i = 0; i < 10;i++){
free(x[i]);
}
free(x);
return 0;
}
If you want a dynamic allocated array of strings, you should declare your variable x as a pointer to an array of e.g. 32 chars. The you can allocate/deallocate an array of these using a single malloc and likewise a single free.
Like:
#define NUM_STRINGS 10
#define STRING_SIZE 32
int main() {
// declare x as a pointer to an array of STRING_SIZE chars
char (*x)[STRING_SIZE];
// Allocate space for NUM_STRINGS of the above array, i.e.
// allocate an array with NUM_STRINGS arrays of STRING_SIZE chars
x = malloc(NUM_STRINGS * sizeof *x);
if (x)
{
for (int i = 0; i < NUM_STRINGS; ++i)
{
sprintf(x[i], "%d", 10 + i);
}
for (int i = 0; i < NUM_STRINGS; ++i)
{
puts(x[i]);
}
free(x);
}
return 0;
}
Output:
10
11
12
13
14
15
16
17
18
19
The best way to determine the amount of memory to be used with malloc is this:
#include <stdio.h>
#include <stdlib.h>
#define N_STRINGS 10
#define STRING_SZ 10
int main() {
// if you use *x (the deferred subexpression) the compiler can calculate its
// sizeof easily, and no need to use a constant or something that has to be
// revised if you change the type of x. Also, calloc will give instead N_STRINGS
// pointers already initialized to NULL.
char **x = calloc(N_STRINGS, sizeof *x);
// to be able to free(x[i]) for all i, you need to initialize all pointers,
// and not only the first one.
int i; // I prefer this, instead of for(int i..., which is more portable with legacy code.
for (i = 0; i < N_STRINGS; i++) {
// char is warranted to be sizeof 1, you don't need to specify but the
// number of chars you want for each character array.
x[i] = malloc(STRING_SZ); // remember only STRING_SZ chars you have, so...
// better to use snprintf(), instead.
snprintf(x[i], // the buffer pointer
STRING_SZ, // the buffer size (STRING_SZ chars, incl. the final null char)
"%d", // the format string
10); // initialize all strings to the string "10" ???
}
// upto here we have made N_STRINGS + 1 calls to malloc...
// you should do something here to check that the allocations went fine, like
// printing the values or do some work on the strings, but that's up to you.
// now, everything should be fine for free() to work.
for(int i = 0; i < N_STRINGS; i++){
free(x[i]);
}
free(x); // ... and this is the N_STRINGS + 1 call to free.
return 0;
}
Check always that the number of free calls executed by your program has to be the same of the malloc calls you have made (before). A free call must free the memory allocated by one (and only one) call to malloc. You cannot free something that has not been acquired by malloc() (or calloc()) directly or indirectly. The same as it is bad use (but not necessary an error) to do a malloc that is not freed before the program ends (this is not true in non-hosted environments, e.g. embedded programs, in which the operating system doesn't deallocate the memory used by a program when it finishes, although)
By the way, the reason of your segmentation fault is precisely that you have made only two calls to malloc(), but you made 11 calls to free(). free() tries to free memory that malloc() has not allocated, or even worse, you don't own. Anyway, this drives you to Undefined Behaviour, which is something you don't desire in a program. In this case, you got a program crash.

Simple question on pointers and how to initialize an array in C

I have a question on a simple program that i wrote to initialize an array one element at a time, the few lines of code are below:
#include <stdio.h>
int main(void)
{
int *ptr;
int index;
for (index = 0; index < 4; index++)
{
ptr[index]=index;
printf("%d\n", ptr[index]);
}
return 0;
}
All plain and simple but when I run the program I incur in segmentation fault (core dumped) error, that to my understanding occurs when you try to write on something that is only readeable or if you have exceeded your allowed memory...
Excuse me for this probably nobbish question but I could not find a similar question on SO.
You cannot just use int *ptr and treat it as an array. You need to actually create an array and allocate space for it, by specifying the size. You can either make it as an array like in the first option, or allocate it using malloc() in the second option. I suggest the first one because it executes faster, and it seems your array is of fixed length. The second option is for applications where you do not know the array size until runtime.
#include <stdio.h>
int main(void)
{
int ptr[4]; //you need to specify array size first
int index;
for (index = 0; index < 4; index++)
{
ptr[index]=index;
printf("%d\n", ptr[index]);
}
return 0;
}
You can also use malloc() if you want to allocate it on the heap, but make sure to free() it, to free the memory, or there will be a memory leak.
#include <stdio.h>
int main(void)
{
int *ptr = malloc(4*sizeof(int));
int index;
for (index = 0; index < 4; index++)
{
ptr[index]=index;
printf("%d\n", ptr[index]);
}
free(ptr);
return 0;
}
This should solve your problem
Also you don't need a for loop to initialize populate the values of the array, in case that is what you are trying to do. You can do this:
int ptr[4] = {0, 1, 2, 3};
As stated in #ChristianGibbons comment, you just need to allocate memory for the array the address of your pointer.
#include <stdio.h>
int main(void)
{
int sizeOfArray = 4;
int *ptr = calloc(sizeOfArray, sizeof(int)); // line to fix
int index;
for (index = 0; index < sizeOfArray; index++)
{
ptr[index]=index;
printf("%d\n", ptr[index]);
}
free(ptr);
return 0;
}

Print array that was set in another function with pointers

As you can see in the code below I tried to print an array that I created in a different function. The output was totally different numbers compares to what I expected: numbers between 0 - 20 were set but I got some negative values.
So my question is why is this happening? And how to fix it if it even possible?
#include <stdio.h>
#include <time.h>
#define LEN 10
int* creatingArray();
void printingArray(int* array);
int main(void)
{
int* pointer_array = creatingArray();
printingArray(pointer_array);
getchar();
return 0;
}
int* creatingArray()
{
srand(time(NULL));
int array[LEN] = { 0 };
int* i = 0;
for (i = array; i < array + LEN; i++)
{
*i = rand() % 20;
}
return array;
}
void printingArray(int* array)
{
int* i = 0;
for (i = array; i < array + LEN; i++)
{
printf("\n%d\n", *i);
}
}
Pay attention to this code:
int* creatingArray()
{
// stuff
int array[LEN] = { 0 };
// more stuff
return array;
}
array is a local variable, so it gets destroyed when the function returns. You then have a pointer to a destroyed variable. The space where it was will (most likely) continue to hold the data you put there - until the memory gets reused for something else and overwritten.
and how to fix it if it eve/n possible?
Several options:
Make array a static variable. Then it will not be destroyed when the function returns. (This also means that every time you call creatingArray it will use the same array, instead of a new one)
Make array global.
Move array to main, and pass a pointer to it into creatingArray, instead of having creatingArray return one. Then, since it's a local variable in main, it will only be destroyed when main returns.
Use malloc to allocate some space that will not be cleaned up automatically when the function returns.

Using 3d array outside a function

I have a function in which I make a 3D array and fill in all the values. I also have to pass a pointer to the function which will assign the memory location of the 3D array to that function so that it can be used outside of that function. Currently, I am doing something which does not seem to work, can someone guide me to the best possible resolution?
int (*arr)[4];
void assign_3D(int (*arr)[4])
{
int local[2][3][4]; //probably we should pass *local?
memset(local, 0, sizeof(int)*2*3*4); // fill the local array with numbers
arr = local;
}
printf("%d\n", arr[1][2][3]);
I know I have written horrible code above. But I am learning :).
It is not possible to assign arrays. You are also using the wrong type for the argument (int (*)[5] is not what a int [2][3][4] decays into, use int (*)[3][4] as the argument type). Once you have the correct type, you can use memcpy() to do the assignment:
#include <string.h>
#include <stdio.h>
int arr[2][3][4];
void assign_3D(int (*arr)[3][4]) {
int local[2][3][4];
memset(local, 0, sizeof(local)); //pass local here, because it is not a pointer but an array. Passing *local would only initialize the first element of the array, i. e. the first 2D slice of it.
// fill the local array with numbers
memcpy(arr, local, sizeof(local));
}
int main() {
assign_3D(arr);
printf("%d\n", arr[1][2][3]);
}
But you can also return a newly allocated array from your function:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef int arrayType[2][3][4];
arrayType* create_3D() {
arrayType* result = malloc(sizeof(*result)); //here we need to dereference because result is a pointer and we want memory for the array, not the pointer.
memset(result, 0, sizeof(*result));
(*result)[1][2][3] = 7; // fill the local array with numbers
return result; //that's easy now, isn't it?
}
int main() {
arrayType* array = create_3D();
printf("%d\n", (*array)[1][2][3]);
free(array); //cleanup
}
Edit:
You mention that the size of the first dimension is not know before the function is run. In that case, you have to use the malloc() approach, but a bit differently:
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
typedef int sliceType[3][4];
sliceType* create_3D(size_t* firstDimSize) {
*firstDimSize = 2;
size_t arraySize = *firstDimSize*sizeof(sliceType);
sliceType* result = malloc(arraySize);
memset(result, 0, arraySize);
result[1][2][3] = 7; // fill the local array with numbers
return result;
}
int main() {
size_t firstDim;
sliceType* array = create_3D(&firstDim);
printf("%d\n", array[1][2][3]);
free(array); //cleanup
}
There are two different ways to allocate a 3D array. You can allocate it either as a 1D array of pointers to a (1D array of pointers to a 1D array). This can be done as follows:
int dim1, dim2, dim3;
int i,j,k;
int *** array = (int ***)malloc(dim1*sizeof(int**));
for (i = 0; i< dim1; i++) {
array[i] = (int **) malloc(dim2*sizeof(int *));
for (j = 0; j < dim2; j++) {
array[i][j] = (int *)malloc(dim3*sizeof(int));
}
}
Sometimes it is more appropriate to allocate the array as a contiguous chunk. You'll find that many existing libraries might require the array to exist in allocated memory. The disadvantage of this is that if your array is very very big you might not have such a large contiguous chunk available in memory.
const int dim1, dim2, dim3; /* Global variables, dimension*/
#define ARR(i,j,k) (array[dim2*dim3*i + dim3*j + k])
int * array = (int *)malloc(dim1*dim2*dim3*sizeof(int));
To access your array you just use the macro:
ARR(1,0,3) = 4;

Resources