How to loop through allocated memory with pointer arithmetic C - c

In order to loop through a regular int array with pointer arithmetic looks like such:
int *p;
int arraySize = 20;
int array[arraySize];
for (p = array; p< array+(sizeof(array)/sizeof(int)); p++){
int random = rand() % 200;
*p = random;
}
for (p = array; p< array+(sizeof(array)/sizeof(int)); p++){
printf("%d\t%x\n", *p, p);
}
for (p = array; p<array+(sizeof(array)/sizeof(int)); p++){
int random = rand() % 200;
*p = random;
}
for (p = array; p< array+(sizeof(array)/sizeof(int)); p++){
printf("%d\t%x\n", *p, p);
}
However, I want to declare:
int *array = (int*) calloc(arraySize, sizeof(int));
I am very confused on how to loop through dynamically allocated memory as opposed to a regular static array.

int *array = (int*)calloc(arraySize, sizeof(int));
int *array_end = array + arraySize;
int* ptr;
for(ptr = array; ptr < array_end; ptr++)
printf("%p\t%d", ptr, *ptr);

Related

Incorrect first value in array of pointers

The dynamicRandomMatrix function should return a pointer to an array of n pointers each of which points to an array of n random integers.
I got it to print mostly correct, except the first number in the array. This is the output:
n=3: -2084546528, 59, 45
Can anyone help me figure out why the first number in the array is so small? I think it must be something to do with local variables and access or something, but I am not sure.
int** dynamicRandomMatrix(int n){
int **ptr;
ptr = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
int *address = randomArray(n);
ptr[i] = address;
}
return ptr;
free (ptr);
}
int* randomArray(int n){
int *arr;
arr = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
int num = (rand() % (100 - 1 + 1)) + 1;
arr[i] = num;
}
return arr;
free(arr);
}
int main(){
int **ptr;
int i;
ptr = dynamicRandomMatrix(3);
printf("n=3: ");
for (i = 0; i < 3; i++) {
printf("%d, ", *ptr[i]);
}
return 0;
}
In your code,
ptr = malloc(sizeof(int) * n);
is not correct, each element in ptr array is expected to point to a int *, so it should be ptr = malloc(sizeof(int*) * n);. To avoid this, you can use the form:
ptr = malloc(sizeof(*ptr) * n);
That said, all your free(array); and free (ptr); are dead code, as upon encountering an unconditional return statement, code flow (execution) returns to the caller, and no further execution in that block (function) takes place. Your compiler should have warned about this issue. If not, use proper flags to enbale all warnings in your compiler settings.

Multiplication Table issue

I am trying to write a C function to store a multiplication table from the range 0-x. The function I have written has a bug in it where it only stores either the first 2 or 3 rows of the table and the function is also never returning a value and I am very confused, any help is appreciated.
void makeTable (int x) {
int** table = malloc(x * sizeof(int*));
int i;
int q;
int* ptr;
for(i = 0; i <= x; i++){
ptr = calloc(x, sizeof(int));
for(q = 0; q <= x; q++){
ptr[q] = (i * q);
}
table[i] = ptr;
}
return table;
}
Here you access memory that you have not allocated. That is undefined behavior.
Correct would be to consider x elements not x+1.
for(q = 0; q < x; q++){
ptr[q] = (i * q);
Same goes with the outer loop also.
for(i = 0; i < x; i++){
Also few other things - returning from a function which is declared void (Undefined behavior). Not checking the return value of malloc and calloc is problematic.
So correct way to write the function would be
int** makeTable (int x) {
int** table = malloc(x * sizeof *table);
if(!table)
{
fprintf(stderr,"Error in mem alloc");
exit(1);
}
for(size_t i = 0; i < x; i++){
int * ptr = calloc(x, sizeof *ptr);
if(!ptr)
{
fprintf(stderr,"Error in mem alloc");
exit(1);
}
for(size_t q = 0; q < x; q++){
ptr[q] = (i * q);
}
table[i] = ptr;
}
return table;
}
Also somewhere in this program you should add the logic to free all these dynamically allocated memory using free.

How to passing the pointer parameters and return them right?

Here is my code sample:
#include <stdio.h>
#include <stdlib.h>
void foo(int size, int new_size, int * ptr1, double * ptr2) {
int i;
new_size = size * 2;
ptr1 = (int *) calloc(new_size, sizeof(int));
ptr2 = (double *) calloc(new_size, sizeof(double));
for (i = 0; i < new_size; i++) {
ptr1[i] = 1;
ptr2[i] = 2;
}
}
int main(){
int i, size = 4, new_size = 4;
int *ptr1 = NULL;
double *ptr2 = NULL;
foo(size, new_size, ptr1, ptr2);
for (i = 0; i < new_size; i++) {
printf("new_size: %d\n", new_size);
printf("ptr1: %d, ptr2: %f\n", ptr1[i], ptr2[i]);
}
free(ptr1);
free(ptr2);
return 0;
}
And I have to malloc space and assign data to ptr1 and ptr2 in foo function (because I don't know the new size of them in main functin) and then use them in the main function.Why the code doesn't work? And How to implement the above process I want?
You can pass the address of the pointer to the function like so:
void foo(int size, int new_size, int ** ptr1, double ** ptr2) {
int i;
new_size = size * 2;
*ptr1 = (int *) calloc(new_size, sizeof(int));
*ptr2 = (double *) calloc(new_size, sizeof(double));
for (i = 0; i < new_size; i++) {
(*ptr1)[i] = 1;
(*ptr2)[i] = 2;
}
}
and in main
foo(size, new_size, &ptr1, &ptr2);
Your code didn't work because parameter are passed by value. ptr1 and ptr2 while being pointers are still passed by values so any modification to them(compared to modification to what they point to) will not remain after the function.
Pass the addresses of the pointers, modify the pointers in the functions and thats all, other that that I have a few observations on your code
Don't cast the return value of malloc(), it's not necessary in c, and it hurts your code readability.
Always check the return value of malloc() and pretty much any function that returns a value, because normally there is a special value indicating failure, and you don't want your program to misbehave under extraordinary conditions.
This is a version of your own code with the main issue addressed and also the observations above.
#include <stdio.h>
#include <stdlib.h>
int foo(int size, int new_size, int ** ptr1, double ** ptr2) {
int i;
new_size = size * 2;
*ptr1 = malloc(new_size * sizeof(int));
*ptr2 = NULL;
if (*ptr1 == NULL)
return 1;
*ptr2 = malloc(new_size * sizeof(double));
if (*ptr2 == NULL) {
free(*ptr1);
return 2;
}
for (i = 0; i < new_size; i++) {
(*ptr1)[i] = 1;
(*ptr2)[i] = 2;
}
return 0;
}
int main() {
int i, size = 4, new_size = 4;
int *ptr1 = NULL;
double *ptr2 = NULL;
if (foo(size, new_size, &ptr1, &ptr2) != 0)
return -1;
for (i = 0; i < new_size; i++) {
printf("new_size: %d\n", new_size);
printf("ptr1: %d, ptr2: %f\n", ptr1[i], ptr2[i]);
}
free(ptr1);
free(ptr2);
return 0;
}
In c you always pass parameters by value, it might be confusing because you are passing a pointer, but a pointer is just another variable which stores a memory address, that address is changing inside the foo() function but it's only being written into the local pointer ptr1.
Passing the address writes the value to the original pointer in main().

Why I get segfault when initializing the struct?

Searched around for one hour. I guess I'd better post the question here.
I simplify the code. The segfault is in the function initMyStruct.
#include "stdlib.h"
typedef struct {
int * arr1;
int * arr2;
} myStruct;
void allocMyStruct (myStruct * a, int num) {
a = malloc(sizeof(myStruct));
a->arr1 = malloc(10*sizeof(int));
a->arr2 = malloc(10*num*sizeof(int));
}
void initMyStruct (myStruct * a, int num) {
int i;
for (i = 0; i < 10; i++) a->arr1[i] = 0;
for (i = 0; i < 10*num; i++) a->arr2[i] = -1;
}
void freeMyStruct (myStruct * a, int num) {
int i;
for (i = 0; i < 10; i++) free(a->arr1);
for (i = 0; i < 10*num; i++) free(a->arr2);
free(a);
}
int main (void) {
int num = 3;
myStruct * a;
allocMyStruct (a, num);
initMyStruct (a, num);
freeMyStruct (a, num);
return 1;
}
Because you're not keeping the pointer to the newly allocated memory, instead you use an uninitialized pointer and getting undefined behavior.
You pass the a variable into allocMyStruct(), but that call is (like all others) by value, so the new value being assigned to it inside the function does not affect the value of a in main().
Change it so that allocMyStruct() either returns the new pointer value, or takes a pointer to the pointer. I would prefer the former, it's cleaner and using function return values often leads to better code:
myStruct * allocMyStruct(int num)
{
myStruct *p;
if((p = malloc(sizeof *p +
10 * sizeof *p->arr1 +
10 * num * sizeof *p->arr2)) != NULL)
{
p->arr1 = (int *) (p + 1);
p->arr2 = p->arr1 + 10;
}
return p;
}
The above code also streamlines the memory allocation, doing it all in one big malloc() call which is then "sliced" into the three parts you actually need.
If the size of arr1 is always 10 by the way, there's no point in having it dynamically allocated, it should just be int arr1[10]; in the struct declaration.
a is used uninitialized, change to:
myStruct * allocMyStruct (int num) {
myStruct *a;
a = malloc(sizeof(myStruct));
a->arr1 = malloc(10*sizeof(int));
a->arr2 = malloc(10*num*sizeof(int));
return a;
}
myStruct * a = allocMyStruct(num);
Also, there is no need to loop in your free function
void freeMyStruct (myStruct * a, int num) {
int i;
for (i = 0; i < 10; i++) free(a->arr1);
for (i = 0; i < 10*num; i++) free(a->arr2);
free(a);
}
Must be
void freeMyStruct (myStruct * a) {
free(a->arr1);
free(a->arr2);
free(a);
}
When you call void allocMyStruct (myStruct * a, int num) the a pointer will be passed as a value and the a parameter is a local copy of your pointer from main , after you change the local a in any of your three functions, it will not change in main.
For this you have to use double pointer as a function argument, so those functions will get an address of a pointer so they can modify it.
#include "stdlib.h"
typedef struct {
int * arr1;
int * arr2;
} myStruct;
void allocMyStruct (myStruct ** a, int num) {
*a = malloc(sizeof(myStruct));
(*a)->arr1 = malloc(10*sizeof(int));
(*a)->arr2 = malloc(10*num*sizeof(int));
}
void initMyStruct (myStruct ** a, int num) {
int i;
for (i = 0; i < 10; i++) (*a)->arr1[i] = 0;
for (i = 0; i < 10*num; i++) (*a)->arr2[i] = -1;
}
void freeMyStruct (myStruct ** a, int num) {
free((*a)->arr1);
free((*a)->arr2);
free(*a);
*a = NULL;
}
int main (void) {
int num = 3;
myStruct * a;
allocMyStruct (&a, num);
initMyStruct (&a, num);
freeMyStruct (&a, num);
return 1;
}
EDIT: Alter Mann is right about multiple freeing of the same address, on linux you would get instant crash for double freeing. And he has a simpler solution.

Assign pointer to block reserved with malloc

Based on this answer: https://stackoverflow.com/a/19765782/1606345
#include <stdlib.h>
typedef struct {
int *arr1;
int *arr2;
} myStruct;
myStruct *allocMyStruct(int num)
{
myStruct *p;
if ((p = malloc(sizeof *p +
10 * sizeof *p->arr1 +
10 * num * sizeof *p->arr2)) != NULL)
{
p->arr1 = (int *)(p + 1);
p->arr2 = p->arr1 + 10;
}
return p;
}
void initMyStruct(myStruct * a, int num)
{
int i;
for (i = 0; i < 10; i++) a->arr1[i] = 0;
for (i = 0; i < 10 * num; i++) a->arr2[i] = -1;
}
int main (void)
{
int num = 3;
myStruct *a = allocMyStruct(num);
initMyStruct(a, num);
free(a);
return 1;
}
It is safe to assign p->arr1 to the address of (p + 1)?
p->arr1 = (int *)(p + 1);
You have a fundamental problem here in how you are thinking about struct allocation.
When you malloc a struct, you malloc the sizeof that struct, you don't malloc for the arrays it will contain, those need to be allocated separately. To do this your code should look more like:
myStruct *allocMyStruct(int num)
{
myStruct *p = malloc( sizeof( myStruct ) );
if( p != NULL )
{
p->arr1 = malloc( sizeof( int ) * 10 ); // p->arr1 now points to an array of 10 elements
p->arr2 = malloc( sizeof( int ) * 10 * num ); // p->arr2 now points to an array of 10 * num elements
}
return p;
}
Keep in mind when you free this you will need to free the arrays individually as well so if your pointer the myStruct was a:
free( a->arr1 );
free( a->arr2 );
free( a );

Resources