Function that calculates memory reserved in different function - c

I have two functions, one that creates a double array,fill it with zeros and reserve memory for it. The other function 'noarr' is supposed to calculate the memory I have reserved in the 'myarr' function for the array. I'm pretty sure I have successfully filled the array with zeros,
but I am not sure how I can access the array from another function? Am I on the right track of doing it?
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
void noarr(double *** myarr(int n, int m));
double** myarr(int n, int m);
double** myarr(int n, int m){
int i, j;
double ** A;
A = malloc(sizeof(double*)*n*m);
for(i = 0; i < n; i++){
A[i] = malloc(m*sizeof(double));
for(j = 0; j < m; j++){
A[i][j] = 0;
}
}
return A;
}
void noarr(double *** myarr(int n, int m)){
printf("%d\n", sizeof(myarr));
}
int main(int argc, const char * argv[]){
int i,j;
int n,m;
double (*A)[n];
A = myarr(n,m);
printf("%.1f %.1f \n",A[0][0],A[2][9]);
noarr(A);
return 0;
}

You simply cannot derive the size of memory (m)alloced somewhere when solely having a pointer to that memory. You need to pass the dimension(s) separately.

Related

Can somone please explain this to me

For n=3 and a={1,2,3},b={4,5,6} its supposed to calculate 1*4+2*5+3*6.
I don't understand why does it work because p is a pointer and p=produs(a,b,n) means that the address of p becomes the value returned by produs.
#include <stdio.h>
#include <conio.h>
void citire(int *x,int *n)
{
for(int i=1; i<=*n; i++)
scanf("%d",&x[i]);
}
int produs(int *a,int*b,int n)
{
int produs=0;
for(int i=1;i<=n;i++)
produs=a[i]*b[i]+produs;
return produs;
}
int main()
{
int n;
int*p;
scanf("%d",&n);
int *a=(int*)malloc(n*sizeof(int));
int *b=(int*)malloc(n*sizeof(int));
citire(a,&n);
citire(b,&n);
p=produs(a,b,n);
printf("%d",p);
return 0;
}
When you do:
size_t size = 10;
int* x = calloc(size, sizeof(int));
You get an array x with 10 items in it, indexed 0..9, not 1..10. Here calloc is used to make it abundantly clear what's being requested instead of doing multiplication that can be mysterious or obtuse.
As such, to iterate:
for (int i = 0; i < size; ++i) {
x[i] ...
}
You have a number of off-by-one errors in your code due to assuming arrays are 1..N and not 0..(N-1).
Putting it all together and cleaning up your code yields:
#include <stdio.h>
#include <stdlib.h>
void citire(int *x, size_t s)
{
for(int i=0; i < s; i++)
scanf("%d", &x[i]);
}
int produs(int *a, int* b, size_t s)
{
int produs = 0;
for(int i = 0; i < s; i++)
produs = a[i] * b[i] + produs;
return produs;
}
int main()
{
int n;
scanf("%d",&n);
int* a = calloc(n, sizeof(int));
int* b = calloc(n, sizeof(int));
citire(a, n);
citire(b, n);
// produs() returns int, not int*
int p = produs(a,b,n);
printf("%d", p);
return 0;
}
You're using pointers in places where pointers don't belong. In C passing a pointer to a single value means "this is mutable", but you don't change those values, so no pointer is necessary nor advised.
Try and use size_t as the "size of thing" type. That's what's used throughout C and it's an unsigned value as negative indexes or array lengths don't make any sense.

Allocate memory for 2d array to print a matrix using functions, in C89

Hello I had to write a program (well still have) that would allocate memory in function for storing numbers that you have to input then print a matrix (rows and columns are the same size). Most importantly the program has to be written using pointers, local variables, functions and C 89 standard.
#include <stdio.h>
#include <stdlib.h>
void Matrix_Input(int *m, int ***Matrix);
void Matrix_Output(int m, int **Matrix);
int main()
{
int m;
int **Matrix;
int i;
Matrix_Input(&m, &Matrix);
Matrix_Output(m, Matrix);
for (i = 0; i < m; i++) /*free memory*/
free(*(Matrix+i));
free(Matrix);
return 0;
}
void Matrix_Input(int *m, int ***Matrix)
{
int i, j;
printf("Input number of rows/columns: \n");
scanf("%d", m);
*Matrix = malloc(*m* sizeof(int*)); /*allocate memory*/
for (i = 0; i < *m; i++)
*(*Matrix+i) = malloc(*m* sizeof(int));
printf("Input integers: \n");
for (i = 0; i < *m; i++)
for (j = 0; j < *m; j++)
scanf("%d", &((*Matrix)[i][j]));
}
void Matrix_Output(int m, int **Matrix)
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < m; j++)
printf("%5d", Matrix[i][j]);
printf("\n");
}
}
The program works fine, but I was asked not to use triple pointers here(for input function):
void Matrix_Input(int *m, int ***Matrix)
Teacher told me to use double pointers for input function just like I did for output like this:
void Matrix_Input(int *m, int **Matrix)
And this is where everything goes wrong since I only know how to allocate with triple pointers. I have to leave input as a separate function, can't put it in main.
Could someone help me out? Please.
Return your Matrix pointer instead. It's an output to the function, not a real input.
int** Matrix_Input(int* n)

Adding 2 matrices using pointers

I can acheive it by passing (c,a,b) to add_mat function, where result of a,b is stored in c like,
void add_mat(int c[][3], int a[][3], int b[][3], int m, int n)
What should be the return type of add_mat if I want to construct the funtion in this way
?? add_mat(int a[][3], int b[][3], int m, int n)
Below is a sample code
#include<stdio.h>
void read_mat(int a[][3], int m, int n){
//scan data
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
printf("[%d][%d] : ",i,j);
a[i][j]=i+j;
}
}
}
int* add_mat(int a[][3], int b[][3], int m, int n){
int c[3][3];
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
c[i][j]=a[i][j]+b[i][j];
}
}
return c;
}
int main(){
int a[3][3];
int m=2,n=2; //mxn of a matrix
read_mat(a, m, n);
//add
int b[3][3];
read_mat(b, m, n);
int* c[3][3];
c = add_mat(a,b,m,n);
return 0;
}
Like passing or pointing the calculated value c inside add_mat function to variable in main function.
You cannot do that, since the memory of the c matrix will be gone when the function terminates.
You need to dynamically allocate it with malloc(), in order for the memory not to be free'd, unless you call free(). I have some examples for that in 2D dynamic array (C), if you want to take a look.
With your previous function, you would create the matrix c outside the function (in main()), that's why dynamic memory allocation was not required.
PS: You should compile with warnings enabled:
prog.c: In function 'add_mat':
prog.c:19:12: warning: returning 'int (*)[3]' from a function with incompatible return type 'int *' [-Wincompatible-pointer-types]
return c;
^
prog.c:19:12: warning: function returns address of local variable [-Wreturn-local-addr]
prog.c: In function 'main':
prog.c:32:7: error: assignment to expression with array type
c = add_mat(a,b,m,n);
^
prog.c:31:10: warning: variable 'c' set but not used [-Wunused-but-set-variable]
int* c[3][3];
^
Here is a working example, which is just for demonstrative purposes:
#include <stdio.h>
#include <stdlib.h>
void read_mat(int a[][2], int n, int m){
//scan data
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
a[i][j] = i + j ;
}
}
}
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 print(int** p, int N, int M) {
int i, j;
for(i = 0 ; i < N ; i++)
for(j = 0 ; j < M ; j++)
printf("array[%d][%d] = %d\n", i, j, p[i][j]);
}
void free2Darray(int** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
int** add_mat(int a[][2], int b[][2], int m, int n){
int** c = get(n, m);
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
c[i][j]=a[i][j]+b[i][j];
}
}
return c;
}
int main(){
int n = 2, m = 2; //nxm of a matrix
int a[n][m];
read_mat(a, n, m);
//add
int b[n][m];
read_mat(b, n, m);
int** c;
c = add_mat(a, b, n, m);
print(c, n, m);
free2Darray(c ,n);
return 0;
}
Output:
array[0][0] = 0
array[0][1] = 2
array[1][0] = 2
array[1][1] = 4
PPS: If you really want to use static arrays, then I recommend using int c[3][3]; add_mat(c, a, b, m, n);
Oh yes, the pointers ...
In C, locally declared arrays usually are allocated on the stack (not on the heap) which means they are not valid outside the respective scope.
In other words, in your function add_mat(), c technically can be returned, but the address it points to will only contain meaningful matrix data as long as the function is executed.
After having returned from the function, the return value of the function is a pointer which still contains (points to) the address where the matrix was stored during execution of the function, but the contents of that location, i.e. the matrix data, can contain arbitrary garbage now.
So what you are doing is technically possible (i.e. throws no compile errors), but is definitely not what you want.
Secondly, your line int* c[3][3]; probably is not what you intend it to be. You are declaring c to be a two-dimensional array (matrix) of pointer to int here. This is not correct since you want to process int values, but not pointers to int values (which are addresses).
To solve both problems, just write int c[3][3]; instead of int* c[3][3]; and change your add_mat() function as follows:
void add_mat(int a[][3], int b[][3], int c[][3], int m, int n){
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
c[i][j]=a[i][j]+b[i][j];
}
}
}
Then call that function like that:
add_mat(a,b,c,m,n);
In your code add_mat returns the pointer to the variable which lives while the function executes only. You can accomplish your goal with dynamically allocated matrix.
In C it is common to pass a dynamically allocated matrix via pointer to pointers to the rows of matrix as a first parameter:
void foo(int** matrix, size_t m, size_t n);
Here matrix is a pointer to the array of pointers. Every pointer in this array points to the row of matrix. So, matrix[0] points to the array containing the first row of matrix.
And it is common to use size_t type for any sizes of arrays.
If you need create matrix dynamically, be careful with memory. Every dynamically allocated block should be released. Otherwise you will get memory leaks, that may cause the program crash. Therefore, when you allocate rows of matrix, you should check if allocation of current row was successfull. If not, you should release all previously allocated rows.
There is a working code for your question:
#include <stdio.h>
#include <stddef.h>
#include <malloc.h>
void free_mat(int** a, size_t m) {
if (!a) {
return;
}
for (size_t i = 0; i < m; ++i) {
free(a[i]);
}
free(a);
}
int** create_mat(size_t m, size_t n) {
int** rows = calloc(m, sizeof(int*));
if (!rows) {
return NULL;
}
for (size_t i = 0; i < m; i++) {
rows[i] = malloc(n * sizeof(int));
if (!rows[i]) {
free_mat(rows, m);
return NULL;
}
}
return rows;
}
void read_mat(int** a, size_t m, size_t n) {
for (size_t i = 0; i < m; i++) {
for (size_t j = 0; j < n; j++) {
printf("[%d][%d]: ", i, j);
scanf("%d", a[i] + j);
}
}
}
void print_mat(const int* const* a, size_t m, size_t n) {
for (size_t i = 0; i < m; ++i) {
for (size_t j = 0; j < n; ++j) {
printf("[%d][%d]: %d\n", i, j, a[i][j]);
}
}
}
int** add_mat(const int* const* a, const int* const* b, size_t m, size_t n) {
int** c = create_mat(m, n);
if (c) {
for (size_t i = 0; i < m; ++i) {
for (size_t j = 0; j < n; ++j) {
c[i][j] = a[i][j] + b[i][j];
}
}
}
return c;
}
int main() {
size_t m = 3;
size_t n = 3;
int** a = create_mat(m, n);
int** b = create_mat(m, n);
if (!a || !b) {
printf("error when allocating matrix\n");
}
else {
read_mat(a, m, n);
read_mat(b, m, n);
int** c = add_mat(a, b, m, n);
if (!c) {
printf("error when allocating matrix\n");
}
else {
print_mat(c, m, n);
free_mat(c, m);
}
}
free_mat(a, m);
free_mat(b, m);
return 0;
}
But you would be more flexible, if add_mat didn't create a new matrix.
It is common to pass a pointer to the result matrix as a function parameter:
void add_mat(int** c, const int* const* a, const int* const* b, size_t m, size_t n);

Pointing to arrays using void function

Sorry for that title. I really didn't know how to define this problem.
I was needed to declare integer array of N numbers and to fill it with random nums in void function. Then that array needs to be printed in main. The thing is that i am not allowed to use printf in void function so only way to print in main is to use pointers I guess. My knowledge is limited as I am beginner at pointers. Thx in advance and sorry for bad english.
Here is my code so far. When I compile it marks segmentation error.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void form();
int main()
{
int N, a[100];
printf("Input index: \n");
scanf("%d", &N);
form(N, &a);
printf("Array: \n");
for (int i = 0; i < N; i++) {
printf("a[%d] = %d", i, a[i]);
}
}
void form(int N, int *ptr[100])
{
srand(time(NULL));
for (int i = 0; i < N; i++) {
*ptr[i] = rand() % 46;
}
There are several issues in your code.
1) Your array decalaration form() is obsolete. Use proper prototype.
2) For declaring a VLA, declare it after reading N instead of using a fixed size array.
3) An array gets converted into a pointer to its first element when passed to a function. See: What is array decaying?
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void form(int, int*); /* see (1) */
int main(void) /* Standard complaint prototype for main.
If you need to pass arguments you can use argc, and argv */
{
int N;
printf("Input size: \n");
scanf("%d", &N);
int a[N]; /* see (2) */
form(N, a); /* see (3) */
printf("Array: \n");
for (int i = 0; i < N; i++) {
printf("a[%d] = %d", i, a[i]);
}
}
void form(int N, int *ptr) { /* Modified to match the prototype
srand(time(NULL));
for (int i = 0; i < N; i++) {
ptr[i] = rand() % 46;
}
}
So a couple things:
void form();
As Olaf was alluding to, this declaration is incorrect - you are missing the applicable parameters. Instead, it should be
void form(int N, int ptr[100]);
The main reason your program is crashing is because of the following line:
*ptr[i] = rand() % 46;
You are dereferencing the pointer at i, which is actaully giving you a number - what you want is to assign the value of the pointer at i the new random value:
ptr[i] = rand() % 46;
As related reading, see this question about passing an array in as a function parameter (basically, int ptr[] is the same thing as int * ptr)
Small modifications on your code:
1) Correction and simplification of parameter handling at function call. Just hand over "a", it's an array, so it is an address, you can use int *ptr, or int ptr[], or int ptr[100] in the formal parameter list for it. So you can use simply ptr[i] in your function.
2) Make a prototype for function from old-style declaration providing parameter list.
3) int i; declaration before the for loop - not mandatory, depends on your compiler standard
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void form(int N, int *ptr);
int main()
{
int N, a[100];
printf("Input index: \n");
scanf("%d", &N);
form(N, a);
printf("Array: \n");
int i;
for (i = 0; i < N; i++) {
printf("a[%d] = %d", i, a[i]);
}
}
void form(int N, int *ptr)
{
srand(time(NULL));
int i;
for (i = 0; i < N; i++) {
ptr[i] = rand() % 46;
}
}

Issues with passing pointer arrays and printing them

I'm having some issues with very simple situations of passing arrays as pointers into functions and returning them. I thought I had pointers figured but I just can't get my head around it.
Here's the code:
int* getLottoDraw();
void printArray(int * array);
int find_matches(int * array1, int * array2);
int main(int argc, char *argv[])
{
int * lotteryDraw = getLottoDraw();
printArray(lotteryDraw);
system("PAUSE");
return 0;
}
int* getLottoDraw(){
int draw[6];
int i;
srand(time(NULL));
for (i = 0; i < 6; i++) {
int r = rand() % 49;
draw[i] = r;
}
return draw;
}
void printArray(int *array){
int i;
for (i = 0; i < 6; i++){
printf("%i ", array[i]);
}
}
One example output is "3 2047 4614546 0 25 45". Not what was hoping for.
You are returning a stack address, which end up being destroyed when the function ends.
Stack variables are local variables, their scope is limited to the function they're created.
They're created on the function, and destroyed when the function ends, so if you've try to access this address later you'll get undefined behavior.
You should have a dynamic allocated pointer to be able to access it outside the function, or return by value, copying the content (which can be costly in an array case).
You could do something like:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int* getLottoDraw();
void printArray(int * array);
int find_matches(int * array1, int * array2);
int main(int argc, char *argv[])
{
int * lotteryDraw = getLottoDraw();
printArray(lotteryDraw);
free(lotteryDraw);
return 0;
}
int* getLottoDraw(){
int* draw = malloc(sizeof(int)*6);
int i;
srand(time(NULL));
for (i = 0; i < 6; i++) {
int r = rand() % 49;
draw[i] = r;
}
return draw;
}
void printArray(int *array){
int i;
for (i = 0; i < 6; i++){
printf("%i ", array[i]);
}
}

Resources