C matrix, allocating doesnt zero all elements? - c

I'm trying to write a little matrix program. Using doublke pointers doesnt work so I figure the easiest way is to have a struct that has the #rows and #columns and a 1d array as the matrix.
But there is some error in the initiation of the matrix as i get:
weird values for the indices (0,0) and (0.1) instead of 0.
Something with this perhaps:
matrix *mtrx = malloc(sizeof(matrix));
mtrx->m = malloc(r * c * sizeof(int));
matrix.c:
#include <stdio.h>
#include <stdlib.h>
#include "Matrix.h"
matrix *alloc_matrix(int r, int c)
{
matrix *mtrx = malloc(sizeof(matrix));
mtrx->m = malloc(r * c * sizeof(int));
if (mtrx == NULL || m == NULL) {
printf("Out of memory.");
exit(1);
}
mtrx->rows = r;
mtrx->columns = c;
return mtrx;
}
void free_matrix(matrix *mtrx)
{
free(mtrx->m);
free(mtrx);
}
void set(matrix *mtrx, int r, int c, int v)
{
(mtrx->m)[r * mtrx->columns + c] = v;
}
int get(matrix *mtrx, int r, int c)
{
return (mtrx->m)[r * mtrx->columns + c];
}
void print_matrix(matrix *mtrx)
{
int i,j;
printf("\n");
for(i=0; i<mtrx->rows; i++) {
for(j=0; j<mtrx->columns; j++) {
printf("%i ", get(mtrx,i,j));
}
printf("\n");
}
}
matrix.h:
struct matrix_ {
int rows;
int columns;
int *m;
};
typedef struct matrix_ matrix;
matrix *alloc_matrix(int r, int c);
void free_matrix(matrix *mtrx);
void set(matrix *mtrx, int r, int c, int v);
int get(matrix *mtrx, int r, int c);
void print_matrix(matrix *m);
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "Matrix.h"
int main(void)
{
matrix *m = alloc_matrix(3,4);
print_matrix(m);
printf("\nm[0][0] = %i", get(m,0,0));
set(m,0,0,0);
printf("\nm[0][0] = %i", (m->m)[0]);
printf("\nm[0][0] = %i", (m->m)[12]);
return 0;
}
output:
all elements except (0,0) and (0,1) is 0.

Function malloc allocates a block of memory, returning a pointer to the beginning of the block. It doesn't set all its bits to zero.
Allocating a block of memory and initializing all its bits to zero - that's what calloc function is for.
Or you can explicitly set these bits to zero by using memset

The object allocated by malloc has an unspecified value. If needed, you have to zero-ize the object yourself (for example using memset function) or call calloc instead of malloc.

malloc() is not guaranteed to zero the memory. Use calloc() to allocate memory with zeros.

malloc does not initiate with 0's (because of performance issues... it's not always what you want)...
use calloc() instead.

malloc does not zero out allocated memory. If you want to fill the matrix with zeros on allocation, use calloc instead. In your case, replace:
mtrx->m = malloc(r * c * sizeof(int));
with
mtrx->m = calloc(r*c, sizeof(int));
Answering your follow-up question:
However is there any difference in efficiency between malloc+memset and calloc? or is calloc simplye malloc+memset?
Typically, for "small" allocations calloc is equivalent to malloc + memset. For "large" allocations (multiple pages, at least), your library may do something more clever relying on some amount of OS support. One approach would be for the OS to lazily zero fill the allocated pages as they are actually used, rather than zero filling all of them immediately upon allocation.

That is correct. The C specification does not say arrays are initilized to anything. You just get a piece of memory that will have whatever values there where before.
You can easily initialize to sero though: memset(mtrx->m, 0, sizeof(int) * r * c);

Related

dynamic allocation of 2d array function

So I have a program in C structured in 3 files: main.c, alloc.h and alloc.c. In the main.c function, I have the declaration of a pointer to another pointer to which I intend to alloc an n * m array:
#include <stdio.h>
#include <stdlib.h>
#include "alloc.h"
int main() {
int **mat, n, m;
alloc_matrix(&mat, int &n, int &m);
return 0;
}
In alloc.c I have the following declarations:
#ifndef ALLOC_H_INCLUDED
#define ALLOC_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
void alloc_matrix(int***, int*, int*);
#endif
In alloc.c I have the function:
void alloc_matrix(int ***mat, int *n, int *m) {
printf("\nn = "); scanf("%d", n);
printf("\nm = "); scanf("%d", m);
*mat = (int**)calloc(*n, sizeof(int*));
int i;
for (i = 0; i < *n; i++)
*(mat + i) = (int*)calloc(*m, sizeof(int));
}
But the program doesn't work. It enters some kind of loop and doesn't end.
If I allocate it in main it would work but I have no idea what I am doing wrong in the alloc function.
Here is the correct code. Your error was that in the definition of alloc_matrix, you used *(mat+i) in the allocation loop, which should be *(*mat+i) as, mat is a int*** so the base address for the 2D array would be in *mat. Then you need to move by offset i and then de-reference that memory location for the 1D array.
Main:
#include <stdio.h>
#include <stdlib.h>
#include "alloc.h"
int main()
{
int **mat,n,m;
alloc_matrix(&mat,&n,&m);
return 0;
}
alloc.h
#ifndef ALLOC_H_INCLUDED
#define ALLOC_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
void alloc_matrix(int***,int*,int*);
#endif
alloc.c :
void alloc_matrix(int ***mat,int *n,int *m)
{
printf("\nn = "); scanf("%d", n);
printf("\nm = "); scanf("%d", m);
*mat = (int**)calloc(*n,sizeof(int*));
int i;
for(i = 0; i < *n; i++)
*(*mat+i) = (int*)calloc(*m,sizeof(int));
}
The code for the read function :
void read_matrix(int ***mat,int n,int m)
{
int i,j;
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
{
printf("mat[%d][%d] = ", i, j);
scanf("%d", (*(*mat+i))+j);
}
}
The problem with it is that it only reads the first row and the it freezes.
void alloc_matrix(int ***mat,int *n,int *m)
There are two problems in this line. Neither is fatal but both are worth fixing.
First problem: A matrix in this program is represented as an int**. Why does alloc_matrix accept an int***? All standard functions that allocate something (malloc and friends) return a pointer to that something. This is an idiomatic way of doing things in C. It reduces your star count (being a three-star C programmer is not an achievement to be proud of) and simplifies the code. The function should be changed to
int** alloc_matrix( // but what's inside the () ?
The second problem is, why should a function called alloc_matrix prompt the user and read values? These things are not related to allocation. A function should do one thing and do it well. Does malloc prompts you to enter the size? Does fopen prompt you to enter the filename? These things would be regarded as nonsense of the first degree, and rightly so. It is advised to read the sizes elsewhere and pass them to alloc_matrix as input arguments. Hence,
int** alloc_matrix(int n, int m) { // but what's inside the {}?
What remains of alloc_matrix is simple:
int** alloc_matrix(int n, int m) {
int** mat; // that's what we will return
int i;
mat = (int**)calloc(n, sizeof(int*));
for(i = 0; i < n; i++)
// here comes the important part.
Since we have simplified alloc_matrixand reduced the star count in mat, what should we do with the old body of the loop? It was:
*(mat+i) = (int*)calloc(...);
but if we remove a star, it becomes
(mat+i) = (int*)calloc(...);
which is an obvious nonsense. Perhaps the old line was a problem. The fact that it provoked a compiler warning certainly doesn't speak for its correctness. So how to correct it? There aren't too many options. It turns out that in order to restore sanity, we must leave the old left-hand side (written for the three-star mat) intact. Or, better still, use an equivalent but more idiomatic notation:
mat[i] = (int*)calloc(m, sizeof(int));
So the entire function now becomes
int** alloc_matrix(int n, int m) {
int **mat;
int i;
mat = (int**)calloc(n, sizeof(int*));
for(i = 0; i < n; i++)
mat[i] = (int*)calloc(m, sizeof(int));
return mat;
}
and it should be called like
mat = alloc_matrix(n, m);
It is often said that one should not cast the result of calloc and friends. But in this case the cast has enabled a warning which helped to find a bug. I'm leaving the casts in place for now.
There is another idiom for the allocation that does not require the cast, but also avoids the problem of types not matching.
Instead of using the type for the sizeof, you can use the dereferenced pointer as the type information is available in the variable:
mat = (int**)calloc(n, sizeof(int*));
can be changed to
mat = calloc(n, sizeof *mat); //sizeof is an operator not a function

C malloc of pointer to pointer inside function not giving correct size

So I am now rewriting my fortran code in C (to use CUDA), and apparently I do not understand how to properly use malloc and pointers. I am trying to make the main function just calls to other functions, which need to malloc arrays that will then be used inside other functions. So, I am passing pointers of pointers to them as per this post: C Programming: malloc() inside another function
But the right amount of memory is not being allocated so I get segmentation faults. Here is the code:
#include <stdio.h>
#include <stdlib.h>
//#include <cuda.h>
#include <math.h>
//#include "cublas.h"
//datatype to match FORTRAN complex type
typedef float real;
typedef struct{
int nx;
int ny;
int nz;
int sz;
int tz;
} states;
void set_SPB(real **,int,states **,states **,int **);
//void set_SPB();
int find_minimum(int a[], int n,int start);
const real hc =197.32697,pi=3.1415927;
int main(){
int nmax = 2, A = 28;
real *etemp, *fock;
int *Ndex,*lookup,*lookup_a;
states *channel,*SPB;
//!generates the single particle basis to be used
set_SPB(&etemp,nmax,&SPB,&channel,&Ndex);
free(etemp);
free(Ndex);
free(SPB);
return 0;
}
void set_SPB(real **etemp,int nmax,states **SPB,states **channel,int **Ndex){
int tot_orbs = (2*nmax+1)*(2*nmax+1)*(2*nmax+1)*4;
int D = tot_orbs/4;
int Nalpha = (2*nmax+1)*(2*nmax+1)*(2*nmax+1)*9;
real E;
*etemp = (real*)malloc(D);
*Ndex = (int*)malloc(D*3);
*SPB = (states*)malloc(tot_orbs);
printf("orbits without spin degeneracy %d \n",D);
printf("size of etemp %ld \n",sizeof(*etemp)/sizeof(*etemp[0]));
return;
int i = 0;
for(int nx =-nmax;nx<=nmax;nx++){
for(int ny =-nmax;ny<=nmax;ny++){
for(int nz =-nmax;nz<=nmax;nz++){
E = 0.5*4.0*pi*pi*(nx*nx+ny*ny+nz*nz);
//printf("%d\n",i);
*etemp[i] = E;
*Ndex[0*D+i] =nx;
*Ndex[1*D+i] = ny;
*Ndex[2*D+i] = nz;
i+=1;
}
}
}
return;
}
Also I am not sure exactly if my assignments of the arrays are correct.
Specifically the print to find the number of elements of that have been allocated always gives 2, when it should be D = 125.
I cannot believe that float and int take only 1 byte in your environment.
Multiply the size to be allocated by size of their elements.
*etemp = malloc(sizeof(**etemp) * D);
*Ndex = malloc(sizeof(**Ndex) * D*3);
*SPB = malloc(sizeof(**SPB) * tot_orbs); /* not sure because this is not used */
Note that they say you shouldn't cast the result of malloc() in C.
Also note that [] operator has higher precedence than * operator, so you have to use parentheses to use the arrays.
(*etemp)[i] = E;
(*Ndex)[0*D+i] =nx;
(*Ndex)[1*D+i] = ny;
(*Ndex)[2*D+i] = nz;

Array C pass by reference

How do I pass an array as a function parameter by reference so I can allocate memory for it and then have it returned. I am already returning anothe rarray with the routine.
int main(){
float * array_in = NULL;
float * data = Fill_Array(&array_in);
return 0;
}
float * Fill_Array(float * array)
{
array = malloc(sizeof(float*));
*array[1] = 10;
float * return_array = malloc(sizeof(float*));
return return_array;
}
I think you want something like:
#include <stdio.h>
#include <stdlib.h>
void
Fill_Array (float **pArray)
{
*pArray = malloc (sizeof (float) * 100); /* 100 = number of items */
(*pArray)[0] = 1.0;
(*pArray)[1] = 2.0;
return;
}
int
main ()
{
float *array_in = NULL;
Fill_Array (&array_in);
/* do something here */
free (array_in);
return 0;
}
Arrays are always passed by reference in the sense you pass a pointer, rather than a thick copy. If you want to do an allocation in the function, you need to pass a pointer to a pointer.
This code is messed up. I'm not sure what to start.
First off, you can pass an array like this:
Fill_Array(array_in);
But this code won't work. For starters, the first thing Fill_Array does is throw the value away by overwriting the variable with a newly allocated block of memory.
Second, you are only allocated enough memory or a pointer to a float. It is not safe to write floats to the memory returne.
And finally, you then call malloc() a second time. Where is any of this memory getting freed by calling free()? This is causing memory leaks.
You need to better define what you are trying to do, and then start again.
Another variant. This one is free from memory leaks.
You can create any number of arrays of any dimensions.
Just do not forget to work in pairs "Create-Destroy"
#include <stdio.h>
#include <stdlib.h>
float *CreateArray (int N)
{
float *arr = malloc (sizeof (float) * N);
for (int i = 0; i<N; i++)
arr[i] = 0.0f;
return arr;
}
void DestroyArray (float *arr)
{
free(arr);
}
int main ()
{
int N = 10; /* number of items you need this time*/
float *arr = CreateArray (N);
//...do something
DestroyArray (arr);
//.......
return 0;
}

correct way to free m*n matrix bidimensional allocation

I allocate a non-square matrix in this way, but I'm not sure if I'm using the deallocation correctly
float **matrix_alloc(int m /* rows */, int n /* columns */)
{
int i;
float **arr = malloc(m*sizeof(*arr));
for(i=0; i<m; i++)
{
arr[i]=malloc(n*sizeof(**arr));
}
return arr;
}
I have tried two way to free the memory
-Attempt A loop rows
void free_mem_mat(int m, float **array) {
int i;
for (i = 0; i < m; i++) {
free(array[i]);
}
free(array);
}
- Attempt B loop columns
void free_mem_mat(int n, float **array) {
int i;
for (i = 0; i < n; i++) {
free(array[i]);
}
free(array);
}
what should I use to free? the way A on the rows or the way B? (I know as written the method is the same I have rewritten this to be most clear possible)
You need one free() for each malloc()*. There were m+1 calls to malloc(); you'd better make m+1 calls to free() too.
Given that as the starting point, option A is the correct solution. However, it is also fair to note that the two functions (option A and option B) are strictly equivalent as long as you pass the m dimension given to the allocation function as the size argument of the deallocation function. The comment in option B is misleading; you're not looping over columns.
Given:
enum { MAT_ROWS = 20, MAT_COLS = 30 };
float **matrix = matrix_alloc(MAT_ROWS, MAT_COLS);
The correct call to free_mem_mat() is:
free_mem_mat(MAT_ROWS, matrix);
* This is an over-simplified statement if you use realloc() or calloc(). You need a free() for each malloc() that was not realloc()'d, and a free() for each realloc() that did not do a free() — by setting the size to 0. Treat calloc() as equivalent to malloc() as far as free() is concerned.
The trouble is that it has many allocations
I prefer this mode
#include <stdio.h>
#include <stdlib.h>
float **matrix_alloc(int m /* rows */, int n /* columns */)
{
int i;
float **arr = malloc(m * sizeof(float *));
*(arr) = malloc(m * n * sizeof(float));
for (i = 0; i < m; i++) {
*(arr + i) = (*(arr) + i * n);
}
return arr;
}
void free_mem_mat(float **array) {
free(*(array));
free(array);
}
int main () {
float **matrix = matrix_alloc(10, 20);
free_mem_mat(matrix);
return 0;
}
more information in:
http://c-faq.com/aryptr/dynmuldimary.html
arr was allocated as an array of m elements, each a pointer to some allocated memory. Therefore, you must free the m pointers in arr. In freeing each, you don't need to mention the size of the thing pointed to.

How do I tell a C program to create n arrays, reading n by scanf?

I'd like to create a small program that adds, subtracts, multiplies and does a cross product for vectors.
Therefore I'd like to have the user enter
- the amount of vectors
- the dimension of said vectors
- what exactly he wants to do with the vectors (one of the above mentioned functions)
Since I am quite new to programming maybe I haven't found the correct source yet, in this case I would be grateful for a hint in the right direction (especially what to search exactly, since I am not a native speaker)
My problem:
I don't know how to program the sum function so that it always sums up n vectors (n being the amount of vectors the user entered)
I have a rough idea about the rest of the functions so maybe I won't bother you with this program again but this sum-problem really is a problem for me.
I'm sure the answer is somewhere near but I just don't seem to be able to find it.
So many thanks in advance :)
Simple vector
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int Type;
typedef struct vector {
size_t size;
size_t capacity;
Type *array;
} Vector;
Vector *vec_make(){
Vector *v;
v = (Vector*)malloc(sizeof(Vector));
v->size = 0;
v->capacity=16;
v->array=(Type*)realloc(NULL, sizeof(Type)*(v->capacity += 16));
return v;
}
void vec_pushback(Vector *v, Type value){
v->array[v->size] = value;
if(++v->size == v->capacity)
v->array=(Type*)realloc(v->array, sizeof(Type)*(v->capacity += 16));
}
size_t vec_size(Vector *v){
return v->size;
}
Type *vec_getArray(Vector *v){
return v->array;
}
void vec_free(Vector *v){
free(v->array);
free(v);
}
int main(){
int n=5;//user input
Vector *a, *b, *c;
int i, sum=0, size;
int *ap, *bp, *cp;
a = vec_make(); b = vec_make(); c = vec_make();
for (i=0; i<n; ++i) {
vec_pushback(a, i+1);//1,2,3,4,5
}
vec_pushback(b, 2);
vec_pushback(b, 4);
vec_pushback(b, 5);
vec_pushback(b, 6);
vec_pushback(b, 10);
ap=vec_getArray(a);bp=vec_getArray(b);cp=vec_getArray(c);
for(i=0;i<a->size;++i){
sum+=ap[i];
}
printf("sum(va)=%d\n", sum);
size=vec_size(b);
for(i=0;i<size;++i)
vec_pushback(c, ap[i]+bp[i]);
printf("va + vb = vc(");
for(i=0;i<size;++i){
printf("%d", cp[i]);
if(i<size-1)
printf(",");
else
printf(")\n");
}
vec_free(a);vec_free(b);vec_free(c);
return 0;
}
Are you using straight C or C++?
Since you want dynamic memory allocation, I'd really recommend C++ since you can use std::vector for your array which is totally straightforward. The C way is not nearly as simple.
http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c4027/C-Tutorial-A-Beginners-Guide-to-stdvector-Part-1.htm
This question explains how to malloc a 2-d array Using malloc for allocation of multi-dimensional arrays with different row lengths basically you start by allocating an array of n int pointers then you loop over that array and do array[i] = (int*)malloc(sizeof(int) * lenght))
Putting that into more a step by step how to;
1) allocate an array of int pointers - int** array = malloc(sizeof(int*) * n);
you use ** because your first pointer points the the beginning of the array and the array is of type int*, each of these int pointers will point to another array.
2) loop over the array - for (i = 0; i < n; i++)
in C there is no simple way to malloc 2-d arrays. you have to build each row 1 by 1.
3) inside the loop allocate the horizontal array - array[i] = (int*)malloc(sizeof(int) * length)
The question I link to includes some checks to make sure the allocation was successful. I don't know how necessary this is, but it can't hurt.

Resources