Passing char array to const void* param - c

I have a structure like this:
typedef struct {
float batch;
float length;
uint32_t test;
char val[0];
}
PARAM;
And am calling a function with this format:
void fillValues(float val, float len, uint32_t tmp, const void* prw);
I declare the structure and allocate some memory:
PARAM *first = calloc(10, sizeof(PARAM));
The problem I am having is if I print the values of first->data before calling the function, it contains as expected but if I call the function:
fillValues (test, first->batch, first->length,
first->test, &first->val);
and try and print prw inside, it contains nothing.
I think I am passing the value incorrectly because it is declared as a char array but the function parameter is a const void *.
P.S. I don't want to change the fucntion param type.
The only part where prw is used in fillValues is converting to a double:
double *value
value = (double*)first->data;
*value = *(const double*)pwr;

char val[0]; is nonsense, this is not valid C. Arrays cannot have size zero. The GCC compiler had a non-standard language extension that allowed this (as a 1990s fix to the old "struct hack"). This all turned obsolete in the year 1999 with the C99 standard, when flexible array members were added to the language.
Change your struct to this:
typedef struct {
float batch;
float length;
uint32_t test;
char val []; // flexible array member
}
PARAM;
Then allocate memory as
PARAM* p = malloc(sizeof(PARAM) + sizeof(n));
where n is the length you want the array char val[] to have.
Since your function has the format const void* prw, the last parameter in the call should be first->val and not &first->val.
This is a perfect example of why void pointers should be avoided when possible: they tend to hide bugs and block compiler warnings.

Related

Return a dynamically allocated array? (C)

Consider the given 2d array allocation:
int (*some)[10] = malloc(sizeof(int[10][10]));
This allocates a 10 x 10 2d array. Apparently its type is int (*)[10]. I want to write a function initialize() that will allocate it, initialize it and then return a pointer to the array, so that the construction some[i][j] would be usable in other functions which can pass a pointer to the array it onto each other.
What should the prototype, specifically the return type of initialize() be?
int (*initialize(void))[10] { ... }
initialize is a function, which takes no parameters and returns a pointer to an array of 10 int.
You should use a typedef for that.
allocates the table of nrow pointers to (allocated) int array of size elements
void *allocate_rows(int *(*ptr)[size], size_t nrows)
{
int (*tmpptr)[size] = *ptr;
*ptr = malloc(nrows * sizeof(*ptr));
if(*ptr)
{
while(nrows--)
{
tmpptr = malloc(sizeof(*tmpptr));
if(!tmpptr)
{
/* malloc failed do something */
}
else
{
tmpptr++;
}
}
return *ptr;
}
In
int (*some)[10] = malloc(sizeof *some);, some is a "pointer to an array of 10 int`.
If you want other to be a function returning a pointer to an array of of 10 int, you can start with int (*some)[10]; and replace some with what a call to a such function would look like to get your declaration.
int (*some)[10]; => int (*other(argument1,argument2))[10];
That's how it worked in pre-standardized C. Since standardized C has prototypes, you'd also replace the argument identifier list with a parameter type list, e.g.:
int (*other(int argument1, double argument2))[10];
The cdecl program or the cdecl website can help you verify the result:
$ echo 'explain int (*other(int,double))[10]'|cdecl
declare other as function (int, double) returning pointer to array 10 of int
Most people find typedefs more readable:
typedef int (*pointer_to_an_array_of_10_int)[10];
pointer_to_an_array_of_10_int other(int, double);
//to verify it's a compatible declaration
int (*other(int , double ))[10];

Why do I get garbage values from a structure initialized from void**

I test this code:
void foo (void* data[])
{
static struct structure
{
char character;
int integer;
} st1 = *((struct structure *)data);
printf("[%i][%c]", st1.integer, st1.character);
}
int main (void)
{
void* *data = calloc(2, sizeof(void* ));
char arg1 = 'b';
int arg2 = 20;
data[0] = (char* )&arg1;
data[1] = (int* ) &arg2;
foo(data);
return(0);
}
but I get garbage values instead of the intended
[20] [b]
I have tried many things, including st1 = *((struct structure *)&data);, (despite that AFAIK data is already an address) declaring and initializing separate structure pointer and then deref-ing it, but nothing works.
What could be the reason this happens and how should I do it properly approaching the same idea of obtaining function arguments ?
You generally and portably can't expect your struct to be the same size as two void*.
You can't expect any specific padding inside the struct itself. And you can't expect that casting a char to void* will produce the same valid char back when the memory region is reinterpreted as part of a struct.
The behavior of (the code I think I read) is as undefined as it can get.
I originally completely overlooked the fact that you assign addresses to the two void* (imagined you cast the char and int themselves to void*), so your reinterpretation of those values need to not result in what you expect at all. In fact, it may result in trap values. So your code is undefiend behavior.
Your problem is located in your structure itself.
In your data, in main, you wrote an int* and a char*. However, in your function, you define the struct as it contains a char and int, what you should write is :
void foo (void* data[])
{
static struct structure
{
char* character;
int* integer;
} st1 = *((struct structure *)data);
printf("[%i][%c]", *(st1.integer), *(st1.character));
}

Writing a generic function in C, how to handle strings

I have a function that takes a void** argument and an integer that indicates its datatype
void foo (void** values, int datatype)
Inside the function, depending on the datatype, I malloc it this way:
if (datatype == 1)
*values = (int*) malloc (5 * sizeof(int));
else if (datatype == 2)
*values = (float*) malloc (5 * sizeof(float));
All is good upto now. However, when character strings come into the picture, things get complicated. The void** would need to be void***, since I will need to do something like this:
*values = (char**) malloc (5 * sizeof(char*));
for(i=0;i<5;i++)
(*values)[i] = (char*) malloc (10);
..
strncpy( (*values)[0], "hello", 5);
How should such a situation be handled?
Can I pass a char*** to the function that expects a void** but cast it correctly inside it?
void foo (void** values, int datatype) {
if(datatype == 3) {
char*** tmp_vals = (char***) values;
*tmp_vals = (char**) malloc (5 * sizeof(char*));
...
(*tmp_vals)[i] = (char*) malloc (10 * sizeof(char));
strncpy ( (*tmp_vals)[i], "hello", 5);
}
So I just cast the void** into a char***. I tried this and ignoring the warnings, it worked fine.
But is this safe? Is there a more graceful alternative?
How should such a situation be handled? Can I pass a char*** to the function that expects a void** but cast it correctly inside it?
No, that's technically Undefined Behavior. It may appear to work on your computer, but it may fail on some future computer that implements different pointer types with different representations, which is allowed by the C language standard.
If your function expects a void**, then you better pass it a void**. Any pointer type can be implicitly converted to void*, but that only works at the top level: char* can be converted to void*, and char** can be implicitly converted to void* (because char** is "pointer to char*"), but char** cannot be converted to void**, and likewise char*** also cannot be converted to void**.
The proper way to call this function is to pass it a proper void**, then cast the resulting void* pointer back to its original type:
void foo(void **values, int datatype)
{
if(datatype == 3)
{
char ***str_values = ...;
*values = str_values; // Implicit cast from char*** to void*
}
else
...
}
...
void *values;
foo(&values, 2);
char ***real_values = (char ***)values;
Assuming that *values was actually pointed to a char***, then this cast is valid and does not have any Undefined Behavior in any of the code paths.
A void * is just a pointer to an unspecified type; it could be a pointer to an int, or a char, or a char *, or a char **, or anything you wanted, as long as you ensure that when you dereference, you treat it as the appropriate type (or one which the original type could safely be interpreted as).
Thus, a void ** is just a pointer to a void *, which could be a pointer to any type you want such as a char *. So yes, if you are allocating arrays of some types of objects, and in one case those objects are char *, then you could use a void ** to refer to them, giving you something that could be referred to as a char ***.
It's generally uncommon to see this construction directly, because usually you attach some type or length information to the array, rather than having a char *** you have a struct typed_object **foo or something of the sort where struct typed_object has a type tag and the pointer, and you cast the pointer you extract from those elements to the appropriate types, or you have a struct typed_array *foo which is a struct that contains a type and an array.
A couple of notes on style. For one, doing this kind of thing can make your code hard to read. Be very careful to structure it and document it clearly so that people (including yourself) can figure out what's going on. Also, don't cast the result of malloc; the void * automatically promotes to the type its assigned to, and casting the result of malloc can lead to subtle bugs if you forget to include <stdlib.h> or your update the type declaration but forget to update the cast. See this question for more info.
And it's generally a good habit to attach the * in a declaration to the variable name, not the type name, as that's how it actually parses. The following declares one char and one char *, but if you write it the way you've been writing them, you might expect it to declare two char *:
char *foo, bar;
Or written the other way:
char* foo, bar;
You don't need to (and probably shouldn't) use a void ** at all - just use a regular void *. Per C11 6.3.2.3.1, "a pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer." A pointer variable, including a pointer to another pointer, is an object. void ** is not "a pointer to void". You can convert freely and safely to and from void *, but you're not guaranteed to be able to convert safely to and from void **.
So you can just do:
void foo (void* values, int datatype) {
if ( datatype == 1 ) {
int ** pnvalues = values;
*pnvalues = malloc(5 * sizeof int);
/* Rest of function */
}
and so on, and then call it similar to:
int * new_int_array;
foo(&new_int_array, 1);
&new_int_array is of type int **, which will get implicitly converted to void * by foo(), and foo() will convert it back to type int ** and dereference it to indirectly modify new_int_array to point to the new memory it has dynamically allocated.
For a pointer to an dynamic array of strings:
void foo (void* values, int datatype) {
/* Deal with previous datatypes */
} else if ( datatype == 3 ) {
char *** psvalues = values;
*psvalues = malloc(5 * sizeof char *);
*psvalues[0] = malloc(5);
/* Rest of function */
}
and so on, and call it:
char ** new_string_array;
foo(&new_string_array, 3);
Similarly, &new_string_array is type char ***, again gets implicitly converted to void *, and foo() converts it back and indirectly makes new_string_array point to the newly allocated blocks of memory.
There is a builtin mechanism to do this already with the added bonus that it allows a variable number of arguments. It is commonly seen in this format yourfunc(char * format_string,...)
/*_Just for reference_ the functions required for variable arguments can be defined as:
#define va_list char*
#define va_arg(ap,type) (*(type *)(((ap)+=(((sizeof(type))+(sizeof(int)-1)) \
& (~(sizeof(int)-1))))-(((sizeof(type))+ \
(sizeof(int)-1)) & (~(sizeof(int)-1)))))
#define va_end(ap) (void) 0
#define va_start(ap,arg) (void)((ap)=(((char *)&(arg))+(((sizeof(arg))+ \
(sizeof(int)-1)) & (~(sizeof(int)-1)))))
*/
So here is a basic example that you could use with a format string and variable number of args
#define INT '0'
#define DOUBLE '1'
#define STRING '2'
void yourfunc(char *fmt_string, ...){
va_list args;
va_start (args, fmt_string);
while(*fmt_string){
switch(*fmt_string++){
case INT: some_intfxn(va_arg(ap, int));
case DOUBLE: some_doublefxn(va_arg(ap, double));
case STRING: some_stringfxn(va_arg(ap, char *));
/* extend this as you like using pointers and casting to your type */
default: handlfailfunc();
}
}
va_end (args);
}
So you can run it as: yourfunc("0122",42,3.14159,"hello","world");
or since you only wanted 1 to begin with yourfunc("1",2.17); It doesn't get much more generic than that. You could even set up multiple integer types to tell it to run a different set of functions on that particular integer. If the format_string is too tedious, then you can just as easily use int datatype in its place, but you would be limited to 1 arg (technically you could use bit ops to OR datatype | num_args but I digress)
Here is the one type one value form:
#define INT '0'
#define DOUBLE '1'
#define STRING '2'
void yourfunc(datatype, ...){ /*leaving "..." for future while on datatype(s)*/
va_list args;
va_start (args, datatype);
switch(datatype){
case INT: some_intfxn(va_arg(ap, int));
case DOUBLE: some_doublefxn(va_arg(ap, double));
case STRING: some_stringfxn(va_arg(ap, char *));
/* extend this as you like using pointers and casting to your type */
default: handlfailfunc();
}
va_end (args);
}
With some tricks, you can do it. See example:
int sizes[] = { 0, sizeof(int), sizeof(float), sizeof(char *) }
void *foo(datatype) {
void *rc = (void*)malloc(5 * sizes[datatype]);
switch(datatype) {
case 1: {
int *p_int = (int*)rc;
for(int i = 0; i < 5; i++)
p_int[i] = 1;
} break;
case 3: {
char **p_ch = (char**)rc;
for(int i = 0; i < 5; i++)
p_ch[i] = strdup("hello");
} break;
} // switch
return rc;
} // foo
In the caller, just cast returned value to appropriate pointer, and work with it.

How do I correctly use a void pointer in C?

Can someone explain why I do not get the value of the variable, but its memory instead?
I need to use void* to point to "unsigned short" values.
As I understand void pointers, their size is unknown and their type is unknown.
Once initialize them however, they are known, right?
Why does my printf statement print the wrong value?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(int a, void *res){
res = &a;
printf("res = %d\n", *(int*)res);
int b;
b = * (int *) res;
printf("b =%d\n", b);
}
int main (int argc, char* argv[])
{
//trial 1
int a = 30;
void *res = (int *)a;
func(a, res);
printf("result = %d\n", (int)res);
//trial 2
unsigned short i = 90;
res = &i;
func(i, res);
printf("result = %d\n", (unsigned short)res);
return 0;
}
The output I get:
res = 30
b =30
result = 30
res = 90
b =90
result = 44974
One thing to keep in mind: C does not guarantee that int will be big enough to hold a pointer (including void*). That cast is not a portable thing/good idea. Use %p to printf a pointer.
Likewise, you're doing a "bad cast" here: void* res = (int*) a is telling the compiler: "I am sure that the value of a is a valid int*, so you should treat it as such." Unless you actually know for a fact that there is an int stored at memory address 30, this is wrong.
Fortunately, you immediately overwrite res with the address of the other a. (You have two vars named a and two named res, the ones in main and the ones in func. The ones in func are copies of the value of the one in main, when you call it there.) Generally speaking, overwriting the value of a parameter to a function is "bad form," but it is technically legal. Personally, I recommend declaring all of your functions' parameters as const 99% of the time (e.g. void func (const int a, const void* res))
Then, you cast res to an unsigned short. I don't think anybody's still running on a 16-bit address-space CPU (well, your Apple II, maybe), so that will definitely corrupt the value of res by truncating it.
In general, in C, typecasts are dangerous. You're overruling the compiler's type system, and saying: "look here, Mr Compiler, I'm the programmer, and I know better than you what I have here. So, you just be quiet and make this happen." Casting from a pointer to a non-pointer type is almost universally wrong. Casting between pointer types is more often wrong than not.
I'd suggest checking out some of the "Related" links down this page to find a good overview of how C types an pointers work, in general. Sometimes it takes reading over a few to really get a grasp on how this stuff goes together.
(unsigned short)res
is a cast on a pointer, res is a memory address, by casting it to an unsigned short, you get the address value as an unsigned short instead of hexadecimal value, to be sure that you are going to get a correct value you can print
*(unsigned short*)res
The first cast (unsigned short*)res makes a cast on void* pointer to a pointer on unsigned short. You can then extract the value inside the memory address res is pointing to by dereferencing it using the *
If you have a void pointer ptr that you know points to an int, in order to access to that int write:
int i = *(int*)ptr;
That is, first cast it to a pointer-to-int with cast operator (int*) and then dereference it to get the pointed-to value.
You are casting the pointer directly to a value type, and although the compiler will happily do it, that's not probably what you want.
A void pointer is used in C as a kind of generic pointer. A void pointer variable can be used to contain the address of any variable type. The problem with a void pointer is once you have assigned an address to the pointer, the information about the type of variable is no longer available for the compiler to check against.
In general, void pointers should be avoided since the type of the variable whose address is in the void pointer is no longer available to the compiler. On the other hand, there are cases where a void pointer is very handy. However it is up to the programmer to know the type of variable whose address is in the void pointer variable and to use it properly.
Much of older C source has C style casts between type pointers and void pointers. This is not necessary with modern compilers and should be avoided.
The size of a void pointer variable is known. What is not known is the size of the variable whose pointer is in the void pointer variable. For instance here are some source examples.
// create several different kinds of variables
int iValue;
char aszString[6];
float fValue;
int *pIvalue = &iValue;
void *pVoid = 0;
int iSize = sizeof(*pIvalue); // get size of what int pointer points to, an int
int vSize = sizeof(*pVoid); // compile error, size of what void pointer points to is unknown
int vSizeVar = sizeof(pVoid); // compiles fine size of void pointer is known
pVoid = &iValue; // put the address of iValue into the void pointer variable
pVoid = &aszString[0]; // put the address of char string into the void pointer variable
pVoid = &fValue; // put the address of float into the void pointer variable
pIvalue = &fValue; // compiler error, address of float into int pointer not allowed
One way that void pointers have been used is by having several different types of structs which are provided as an argument for a function, typically some kind of a dispatching function. Since the interface for the function allows for different pointer types, a void pointer must be used in the argument list. Then the type of variable pointed to is determined by either an additional argument or inspecting the variable pointed to. An example of that type of use of a function would be something like the following. In this case we include an indicator as to the type of the struct in the first member of the various permutations of the struct. As long as all structs that are used with this function have as their first member an int indicating the type of struct, this will work.
struct struct_1 {
int iClass; // struct type indicator. must always be first member of struct
int iValue;
};
struct struct_2 {
int iClass; // struct type indicator. must always be first member of struct
float fValue;
};
void func2 (void *pStruct)
{
struct struct_1 *pStruct_1 = pStruct;
struct struct_2 *pStruct_2 = pStruct;
switch (pStruct_1->iClass) // this works because a struct is a kind of template or pattern for a memory location
{
case 1:
// do things with pStruct_1
break;
case 2:
// do things with pStruct_2
break;
default:
break;
}
}
void xfunc (void)
{
struct struct_1 myStruct_1 = {1, 37};
struct struct_2 myStruct_2 = {2, 755.37f};
func2 (&myStruct_1);
func2 (&myStruct_2);
}
Something like the above has a number of software design problems with the coupling and cohesion so unless you have good reasons for using this approach, it is better to rethink your design. However the C programming language allows you to do this.
There are some cases where the void pointer is necessary. For instance the malloc() function which allocates memory returns a void pointer containing the address of the area that has been allocated (or NULL if the allocation failed). The void pointer in this case allows for a single malloc() function that can return the address of memory for any type of variable. The following shows use of malloc() with various variable types.
void yfunc (void)
{
int *pIvalue = malloc(sizeof(int));
char *paszStr = malloc(sizeof(char)*32);
struct struct_1 *pStruct_1 = malloc (sizeof(*pStruct_1));
struct struct_2 *pStruct_2Array = malloc (sizeof(*pStruct_2Array)*21);
pStruct_1->iClass = 1; pStruct_1->iValue = 23;
func2(pStruct_1); // pStruct_1 is already a pointer so address of is not used
{
int i;
for (i = 0; i < 21; i++) {
pStruct_2Array[i].iClass = 2;
pStruct_2Array[i].fValue = 123.33f;
func2 (&pStruct_2Array[i]); // address of particular array element. could also use func2 (pStruct_2Array + i)
}
}
free(pStruct_1);
free(pStruct_2Array); // free the entire array which was allocated with single malloc()
free(pIvalue);
free(paszStr);
}
If what you want to do is pass the variable a by name and use it, try something like:
void func(int* src)
{
printf( "%d\n", *src );
}
If you get a void* from a library function, and you know its actual type, you should immediately store it in a variable of the right type:
int *ap = calloc( 1, sizeof(int) );
There are a few situations in which you must receive a parameter by reference as a void* and then cast it. The one I’ve run into most often in the real world is a thread procedure. So, you might write something like:
#include <stddef.h>
#include <stdio.h>
#include <pthread.h>
void* thread_proc( void* arg )
{
const int a = *(int*)arg;
/** Alternatively, with no explicit casts:
* const int* const p = arg;
* const int a = *p;
*/
printf( "Daughter thread: %d\n", a );
fflush(stdout); /* If more than one thread outputs, should be atomic. */
return NULL;
}
int main(void)
{
int a = 1;
const pthread_t tid = pthread_create( thread_proc, &a );
pthread_join(tid, NULL);
return EXIT_SUCCESS;
}
If you want to live dangerously, you could pass a uintptr_t value cast to void* and cast it back, but beware of trap representations.
printf("result = %d\n", (int)res); is printing the value of res (a pointer) as a number.
Remember that a pointer is an address in memory, so this will print some random looking 32bit number.
If you wanted to print the value stored at that address then you need (int)*res - although the (int) is unnecessary.
edit: if you want to print the value (ie address) of a pointer then you should use %p it's essentially the same but formats it better and understands if the size of an int and a poitner are different on your platform
void *res = (int *)a;
a is a int but not a ptr, maybe it should be:
void *res = &a;
The size of a void pointer is known; it's the size of an address, so the same size as any other pointer. You are freely converting between an integer and a pointer, and that's dangerous. If you mean to take the address of the variable a, you need to convert its address to a void * with (void *)&a.

Cast 32 bit int to 64 void * pointer without warning

I have a "generic" linked link in C that takes void * data to store the data in a Node.
insertNode(linkedList * list, void *data);
//Storing/retrieving a string works fine;
char *str="test";
insertNode(list, str);
char *getback=(char *)node->data;
//Storing/retrieving an Int results a cast warning
int num=1;
insertNode(list,(void *)num);
int getback=(int)node->data;
This is because int is 32 bit, but void * is 64 bit on x64 machine. What is the best practice to get rid of this error?
Use intptr_t or uintptr_t. They are integers of the same size as a pointer:
#include <stdint.h>
...
intptr_t num = 1;
insertNode(list, (void *) num);
intptr_t getback = (intptr_t) node->data;
Of course, the maximum value that you can store depends on the system, but you can examine it at compile time via INTPTR_MIN and INTPTR_MAX.
Using a void * member to store an integer value isn't very good practice - apart from anything else, there's no guarantee what range of integers are storable in this way. If you want to store either a pointer or an integer in your structure, then what you should be using is a union:
union data {
void *p;
int i;
};
insertNode(linkedList * list, union data data);
// Storing/retrieving a string:
char *str="test";
union data d;
d.p = str;
insertNode(list, d);
char *getback = node->data.p;
// Storing/retrieving an int:
int num = 1;
union data d;
d.i = num;
insertNode(list, d);
int getback = node->data.i;
If you have a compiler that supports C99 constructs, you can make it a little neater by avoiding the local union variable:
// Insert a string
insertNode(list, (union data){ .p = str});
// Insert an int
insertNode(list, (union data){ .i = num});
You can cast it twice: insertNode( list, (void *)(uint64_t) num);
Or you can use "unsigned long" for num instead of int. At least in my experience, sizeof(unsigned long) == sizeof(void *) on both 32 and 64-bit systems. Using uintptr_t may be more correct; it's been a while since I've read the standards.
Are you sure you're doing what you actually want to be doing? In the first example with the string you are passing the pointer to the string literal to insertNode, while in the second example ((void *)num) you are casting the value of the int to a pointer to void. Did you actually want to do this: insertNode(list,(void *)&num);, i.e., passing the reference to the data like you were doing in the first example?
Also as an aside, char *str="test"; makes str point to a string literal, which is read-only. So you really should be doing const char *str="test";. If you wanted a normal (writable) string then char str[] = "test";.
Apologies if you already knew these things and actually wanted to store an int in a void *, I just can't imagine why you would.
Edit: If you actually want generic storage space then a union would be a safe approach. There is absolutely no guarantee that an int will fit in a void * in standard C, even though in most implementations it probably does.

Resources