Assign values to a void array? - c

Here's my code :
#include <stdio.h>
#include <stdlib.h>
void *create_array(int size) {
double *v;
v = (double*)malloc(size * sizeof(double));
v[0] = (double)size;
return (void*)v;
}
int main() {
void *a;
double b = 5;
a = create_array(10);
a[1] = b;
return 0;
}
I'm trying to assign the value stored in b to (*a[1]). I get the following error :
"main.c:19:9: error: incomplete type 'void' is not assignable
a[1]=b;"
~~~~^

Main Answer
void is an incomplete type and cannot be used in expressions, including assignments. You can, however, have pointers to this type, void *. void * is a type that means “this points to something, but we are not saying what at this point.”
In order to use a void *, you must say what it points to, by converting it to a different kind of pointer, such as double *, which says “this points to a double.”
C, unlike C++, will do this conversion automatically in assignments. If we declare a with double *a; and then we assign it with a = create_array(10);, then the void * that is returned from create_array is automatically converted to a double * for storing in a. After that, we can write a[1] = b; to store b in the double at a[1].
Supplement
Your create_array contains a mix of double * and void *. It is better to either write a routine that is designed for a specific type:
double *create_array(int NumberOfElements)
{
double *v = malloc(NumberOfElements * sizeof *v);
v[0] = NumberOfElements; // (Yuck, this is ugly.)
return v;
}
or to write a routine that handles any type:
void *create_array(int NumberOfElements, size_t SizeOfElement)
{
void *v = malloc(NumberOfElements * SizeOfElement);
// Cannot store size easily since we do not know what element type is.
return v;
}
As noted, that business about storing the number of elements in the first element is messy. It is better to handle the size separately, even if that requires writing more code.
Also, avoid calling something just a “size,” because this can be confusing: Is the size of an array the number of elements in it or the number of bytes? The name or accompanying comments should always make the unit of measurement clear.

neither pointers nor variables can be void type, just function's return
change to:
#include <stdio.h>
#include <stdlib.h>
double *create_array(int size){
double *v;
v=(double*)malloc(size*sizeof(double));
v[0]=(double)size;
return (double*)v;
}
int main() {
double *a;
double b;
b=5;
a=create_array(10);
a[1]=b;
return 0;
}

You can't dereference a void *, but you can use a cast:
#include <stdio.h>
#include <stdlib.h>
void *
create_array(int size)
{
double *v = malloc(size * sizeof *v);
if( v == NULL ){
perror("malloc");
exit(EXIT_FAILURE);
}
v[0] = (double)size;
return v;
}
int
main(void)
{
void *a;
double b = 5.0;
double *c;
c = a = create_array(10);
((double *)a)[1] = b;
printf("%f %f\n", c[0], c[1]);
return 0;
}

Related

Regarding question about function pointer in C?

I was reading about function pointer. That it contains address of instructions. And there I encountered one question to find an element in array using function pointer. Here is the code.
#include <stdio.h>
#include <stdbool.h>
bool compare(const void* a, const void* b)
{
return (*(int*)a == *(int*)b);
}
int search(void* arr, int arr_size, int ele_size, void* x, bool compare(const void*, const void*))
{
char* ptr = (char*)arr; // Here why not int *ptr = (int*)arr;
int i;
for (i = 0; i < arr_size; i++)
{
if (compare(ptr + i * ele_size, x))
{
return i;
}
}
return -1;
}
int main()
{
int arr[] = { 2, 5, 7, 90, 70 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = 7;
printf("Returned index is %d ", search(arr, n, sizeof(int), &x, compare));
return 0;
}
In the search function char *ptr = (char*)arr; is used which is giving perfect answer = 2.
But when I have used int *ptr = (int*)arr; it gives -1 as answer.
Why is this? Can anyone explain this?
A char is the smallest addressable unit in any C program, and on most system it corresponds to a single byte. That treats the array as a generic sequence of bytes, and uses the ele_size to calculate the byte-position of each element with ptr + i*ele_size.
If you use int *ptr then the byte-position calculation will be wrong by a factor of sizeof(int) (typically 4), since the pointer arithmetic will be done in units of the base type (int instead of char).
The function search knows nothing about what is the type of elements of the array pointed to by the pointer arr of the type void *.
So casting the pointer to the type int * does not make a sense. If to do so then the expression ptr + i*ele_size where the pointer arithmetic is used will produce an incorrect result.
That it contains address of instructions
There is a subtle difference between normal (object) pointers and function pointers. It is not possible to access the single instructions of a function - they do not have the same length.
With other pointers the increment (arithmetic) is adapted to the type, whether as p[i] or p + i or *(p+i).
Side note: there still is int at the bottom of the call chain:
return (*(int*)a == *(int*)b);

Cast void pointer to double without knowing its type in C

I need to write a function which takes as parameters a void pointer (representing an array) and an integer which represents the length of the array. In the function, I need to cast this void pointer into a double one. The problem is that the void pointer can represent an array of integers or floats or doubles.
So the following is obviously not working in case the void pointer represents an array of integers or floats:
void foo(void *v,int n){
double *values;
values=(double*)v;
for(i=0;i<n;i++)
printf("%f\n",values[i]);
}
so this will print the correct output:
foo((double[]){1,2,3,4},4);
and this will print a wrong output:
foo((int[]){1,2,3,4},4);
foo((float[]){1,2,3,4},4);
So... can I correctly cast the void pointer to a double one only knowing that it can be an array of integers or floats or doubles? And is it necessary to have the length of the array or I can calculate it somehow?
P.s. without using callbacks
can I correctly cast the void pointer to a double one only knowing that it can be an array of integers or floats or doubles?
No, you cannot. You need to pass the type information somehow.
And is it necessary to have the length of the array or I can calculate it somehow?
It's necessary to pass the length.
You can "hide" the information inside a struct
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum etype { INTEGER, FLOAT, DOUBLE };
struct data {
void *values;
size_t n;
enum etype type;
};
void foo(struct data *x) {
int *xd = x->values;
float *xf = x->values;
double *xg = x->values;
for (int k = 0; k < x->n; k++) {
switch (x->type) {
default: printf("%g ", xg[k]); break;
case FLOAT: printf("%f ", xf[k]); break;
case INTEGER: printf("%d ", xd[k]); break;
}
}
puts("");
}
int main(void) {
struct data x;
x.values = malloc(4 * sizeof(int));
((int*)(x.values))[0] = 42;
((int*)(x.values))[1] = -1;
((int*)(x.values))[2] = 0;
((int*)(x.values))[3] = 999;
x.n = 4;
x.type = INTEGER;
foo(&x);
x.values = calloc(4, sizeof(float));
x.type = FLOAT;
float tmp = 3.14159;
memcpy(((float*)(x.values))+1, &tmp, sizeof (float));
foo(&x);
free(x.values);
x.values = calloc(4, sizeof(double));
x.type = DOUBLE;
((double*)(x.values))[2] = 2.7182818;
foo(&x);
free(x.values);
}
See code running on ideone

expected 'double **' but argument is of type 'double (*)[2]'

I encountered this strange behavior in C.
This code gives me the compile warning:
expected 'double **' but argument is of type 'double (*)[2]'
What is the problem?
An array of doubles is a pointer to double, right?
BTW, if I send the array itself, the assignment doesn't affect the values and I don't know why.
#include <stdio.h>
void set1(double **x)
{
(*x)[0] = (*x)[1] =1.0;
}
int main()
{
double x[2];
set1(&x);
printf("%d\n%d\n",x[0],x[1]);
}
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
To output objects of type double you should use at least the conversion specifier %f instead of %d. Otherwise the function printf has undefined behavior.
Now about pointers.
If you have an object of type T where T is some type specifier sequence as for example
T x;
then a pointer to the object will have type T *
So let's write your program using this abstract type T.
#include <stdio.h>
void set1( T *x )
{
//...
}
int main(void)
{
T x;
set1( &x ) ;
// ...
return 0;
}
The program will not compile because the type T till now is unknown. But what is the type T for the original program?
It can be defined the following way
typedef double T[2];
Now if to add this typedef to the program then it will compile.
#include <stdio.h>
typedef double T[2];
void set1( T *x )
{
//...
}
int main(void)
{
T x;
set1( &x ) ;
// ...
return 0;
}
So what is the type of the function parameter if to use the expression &x as its argument?
Its type is double ( *x )[2]. It is not the same as double ** and there is no implicit conversion between these two types of pointers. That is pointers of these types are incompatible.
Returning to your original program in this case it will look like
#include <stdio.h>
void set1( double ( *x )[2] )
{
(*x)[0] = (*x)[1] = 1.0;
}
int main(void)
{
double x[2];
set1( &x ) ;
printf( "%f\n%f\n", x[0] , x[1] );
return 0;
}
If you want that the function parameter indeed had type double ** then the function argument has to be specified as it is shown in the program below
#include <stdio.h>
void set1( double **x )
{
(*x)[0] = (*x)[1] = 1.0;
}
int main(void)
{
double x[2];
double *p = x;
set1( &p ) ;
printf( "%f\n%f\n", x[0] , x[1] );
return 0;
}
In this program the pointer p of the type double * points to the first element of the array and the address of the pointer of the type double ** is passed to the function.
However to change the elements of the array it is enough to declare the parameter as having the type double * because in this case the elements of the array are already passed indirectly by using a pointer.
#include <stdio.h>
void set1( double *x )
{
x[0] = x[1] = 1.0;
}
int main(void)
{
double x[2];
set1( x ) ;
printf( "%f\n%f\n", x[0] , x[1] );
return 0;
}
Instead of sending &x you should only send x in the function.
x indicates the address of the first data in the array, and hence the starting address of the array itself.
What you should do is:
void set1(double *x)
{
x[0] = x[1] =1.0;
}
int main()
{
double x[2];
set1(x);
printf("%d\n%d\n",x[0],x[1]);
}
You're problem arises because you set the type of the argument as a pointer to a pointer to a double value but sent a pointer to an array of double values of length 2 instead.
There is no need for pointer syntax at all.
You can simplify the code like this :
#include <stdio.h>
void set1(double x[2])
{
x[0] = x[1] = 1.0;
}
int main(void)
{
double x[2];
set1(x);
printf("%f\n%f\n", x[0], x[1]);
}
If you explicitly convert the type in the function call as follows set1((double **)&x); the warning will go away

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;

Initialization makes pointer from integer without a cast - C

Sorry if this post comes off as ignorant, but I'm still very new to C, so I don't have a great understanding of it. Right now I'm trying to figure out pointers.
I made this bit of code to test if I can change the value of b in the change function, and have that carry over back into the main function(without returning) by passing in the pointer.
However, I get an error that says.
Initialization makes pointer from integer without a cast
int *b = 6
From what I understand,
#include <stdio.h>
int change(int * b){
* b = 4;
return 0;
}
int main(){
int * b = 6;
change(b);
printf("%d", b);
return 0;
}
Ill I'm really worried about is fixing this error, but if my understanding of pointers is completely wrong, I wouldn't be opposed to criticism.
To make it work rewrite the code as follows -
#include <stdio.h>
int change(int * b){
* b = 4;
return 0;
}
int main(){
int b = 6; //variable type of b is 'int' not 'int *'
change(&b);//Instead of b the address of b is passed
printf("%d", b);
return 0;
}
The code above will work.
In C, when you wish to change the value of a variable in a function, you "pass the Variable into the function by Reference". You can read more about this here - Pass by Reference
Now the error means that you are trying to store an integer into a variable that is a pointer, without typecasting. You can make this error go away by changing that line as follows (But the program won't work because the logic will still be wrong )
int * b = (int *)6; //This is typecasting int into type (int *)
Maybe you wanted to do this:
#include <stdio.h>
int change( int *b )
{
*b = 4;
return 0;
}
int main( void )
{
int *b;
int myint = 6;
b = &myint;
change( &b );
printf( "%d", b );
return 0;
}
#include <stdio.h>
int change(int * b){
* b = 4;
return 0;
}
int main(){
int b = 6; // <- just int not a pointer to int
change(&b); // address of the int
printf("%d", b);
return 0;
}
Maybe too late, but as a complement to the rest of the answers, just my 2 cents:
void change(int *b, int c)
{
*b = c;
}
int main()
{
int a = 25;
change(&a, 20); --> with an added parameter
printf("%d", a);
return 0;
}
In pointer declarations, you should only assign the address of other variables e.g "&a"..

Resources