Is `void *` a dynamic type? - c

I am always tempted to refer to void * as dynamic typing for C & C++, usually as a throwaway joke.
I could not find a wikipedia entry or a dictionary entry for Dynamic Type. Perhaps the term is non-sensical?
Questions:
Is void * a dynamic type?
Is QVariant a dynamic type?
Thanks.

Note this answer assumes dynamic type conversion as definition
void* is not a dynamic type, it is a pointer without a type, that doesn't make it a dynamic type because it's type does not automagically adapt to the situations as in Javascript.
For example such code wouldn't work at all:
void* test = malloc(20);
test[0] = 'E'; /* dereferencing void pointer */
puts(test);
Void pointers has to be casted by the programmer and in a sense that what would "dynamic" correspond to is not dynamic.
Some of C Compilers may cast void into other types automatically at compile time but that wouldn't make it dynamic.
Technically speaking similar thing can be done with char* too and you can convert it into a int and that wouldn't make it dynamic.
char* e = malloc(sizeof(int));
memset(e, 0, sizeof(int));
int coolint = *(int*)(e);
printf("%d", coolint);
It's better to think void* like an any type, anything stored in your computer's memory is represented by bytes and by themselves they do not correspond to any type they are just numbers make up the data.
Main usage area of void* in C is to emulate polymorphism.

Related

How to connect a concrete 2D array to a previously defined pointer to a pointer in a header file?

I am trying to implement a checkers game.
I have to use a given header file which contains some #defines and statements.
one of them is:
typedef char** board_t;
I understand that this is a pointer to a pointer to a char i.e that:
**board_t = board_t[0][0]
In the checkers.c file I am implementing some methods with a board 2d array input.
In some of them I'm interested in changing the board so I want to insert it using a pointer.
considering the header typedef, is it ok to define the board this way:
char board_t [BOARD_SIZE][BOARD_SIZE];
and then to use it in a method :
void init_board(board_t){...}
in this writing am I really passing on a pointer to the previously defined 2d array?
if so, how do I approach board[i][j] using this pointer in the method?
If you did it like this:
typedef char** board_t;
Then, declare and allocate memory like:
int i;
board_t arr = malloc(BOARD_SIZE * sizeof(char *));
for(i = 0; i < BOARD_SIZE; i++)
arr[i] = malloc(BOARD_SIZE * sizeof(char));
For a function defined like:
void init_board(board_t arr){...}
Pass on to it like:
init_board(arr);
Some points to note:
If you have used typedef for aliasing a pointer type, you cannot have an array-like declaration (where you specify two index sizes) of the newly created type name. You must declare and allocate memory just like you do with pointers.
In function init_board you can treat the parameter arr as a 2-D array, and refer to its values like arr[row][col].
Note that pointers and arrays are not equivalent in all aspects. There are subtle differences which should be elaborated in a good C book or tutorial (otherwise it is not good).
board_t = board_t[0][0]; that is wrong. You assign an integer (char) to a pointer. Hint: always enable most warnings. For gcc, at least -Wall ist strongly recommended, adding -Wextra is good advice.
If you just want a 2D array, it is still char *board_t. You do not have to add one * per dimension (that would be for an array of pointer to array).
Notes:
A _t suffix should be reserved for implementation defined types. Your name might collide with such a type for a later version of the language. For custom types, CamelCase is commonly used (no specific prefix/suffix).
Using the same name for a type name and a variable is not allowed (it will generate an error).
For conversion of pointers, you should read the standard, expecially 6.3.2.1p3 and 6.7.6.3p7 are of interest here.
Briefly, if you have a formal function argument of array type, that will implicitly converted to a pointer to that same type. If you apply the array operator on a pointer, that will have the same semantics as for an array.

What exactly is type void and how does it work?

I've almost completed my C Primer Plus book and I'm about to hit Structures and Unions, etc... etc..., but I still don't have a full grasp of what exactly the keyword void is. What does void do? How does it work? And when should I use it?
i understand that
void function(void)
basically says that there is no return value. there are no arguments.
i know that you can use different scenarios,
int function(void); //has a return of type int -- voids args
void function(int); //voids return type -- takes type int as an arg
i also understand that
void * p = 0L;
is valid code and that it's basically a pointer-to-void with the initialized value of 0 long.
but is there any value or purpose to using it in such a way
void k = 0;
or am i just voiding the data type? and if so, is there any usefulness to voiding a data type?
because from what i've been able to infer, it's very useful in functions and pointers for working
with an undefinable data type such as
size_t fwrite(const void * restrict ptr, ...more args...);
since the first argument is not a fixed type, my book describes this as being a "catchall type for pointers" and that "Pre-ANSI C uses type char * for this argument, which requires you to typecast actual arguments to that type".
Does this mean that I can use any data type?
And if so, is this restricted to pointers and functions only?
Again... I'm not concerned with how to convert a int to void. I'm not concerned with is a pointer-to-void valid, but merely on how to effectively use this keyword. I'm concerned with "When should I use it?" and "How should I use it?".
Thanks in advance for any answers.
is there any value or purpose to using it in such a way
void k = 0;
No, that statement doesn't make any sense, and the compiler will complain about an incomplete type. Notice that whenever you see void used in a type declaration, it's followed by a * that indicates a pointer, like:
void *foo = nil;
In that case, you're telling the compiler that foo is a pointer, which is really all it needs to know in order to create foo. Without the *, you're trying to declare a variable that has no type, and that's not something that a compiler (or a human, for that matter) can work with.
since the first argument is not a fixed type, my book describes this as being a "catchall type for pointers"
The first argument is a "fixed type" -- the type is a pointer. It's true that the type that the pointer points to is unspecified, but the parameter itself is a pointer.
Does this mean that I can use any data type?
You can use a pointer to any type of data. fwrite() takes a pointer to an array of some type of object, along with the size of that type, the number of objects, and a pointer to a file, and it writes those objects to the file. fwrite() doesn't care about the type of the objects, but since it doesn't have any type information you need to explicitly pass the size and number.
There are three basic situations where the void type is used. There might be some other marginal situations, but these three are where you'll see void used, maybe 99% of the time.
It helps to understand this by keeping in mind that "void" means "there is no type here", as in "datatype".
1) Declare a function that returns no value, as opposed to a function that returns some value.
2) Declare a function that takes no parameters, as opposed to a funciton that takes one or more parameters.
3) The "pointer to void" situation.
The third case basically defines a generic pointer. A pointer to ...something, but this "something" is not important in the section of code that deals with the pointer.
For example, here's manual page for the memcpy function():
MEMCPY(3) Linux Programmer's Manual MEMCPY(3)
NAME
memcpy - copy memory area
SYNOPSIS
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);
DESCRIPTION
The memcpy() function copies n bytes from memory area src to memory
area dest. The memory areas must not overlap. Use memmove(3) if the
memory areas do overlap.
You can read the rest of the manual page yourself. memcpy() takes a couple of pointers that specify a block of memory to be copied around. memcpy() doesn't care what the pointers point to. It doesn't need to know that, so it's function prototype specifies that any pointer can be passed to it. A point to an int, a pointer to a char, or a pointer to some class instance.

void ** parameter without temporary variable

I have a function with a prototype like this:
ErrorType function(void ** parameter, other_args);
This function reads the pointer pointed by 'parameter' and changes it (think of it like a realloc).
Now, to be right according to the C Standard, if I want to pass the address of other pointer than a void *, I must declare a temporary void * variable and use that instead.
So that I want is to create a wrapper (I don't care if it's a function or a macro), that do the function call with any pointer type.
I think I could do that in C11 with _Generic and a function for each basic type, plus a function for all structs and a function for all unions, but I think it's too troublesome.
I also read about a GCC extension that let you to write statements and declarations in expressions, and I think that I can easily do that I want with that, but I prefer that my code compiles in all standard compilers, not only in GCC or Clang.
So the question is, is there any way to do that without too much problems in a C11 compiler?
If I understand the question correctly, you'd like for function to be able to modify various types of pointers. Well, there's bad news and good news about that.
Bad news: The object representation of pointers is opaque, so you'd need to communicate to your function which kind of pointer it should be working with, unless your function is guaranteed to copy an object representation from a source pointer's object representation and you know that the two representations have the same meaning.
For example, sizeof (double *) could be different than sizeof (void *)
Good news: A pointer to any object type can be cast to a void * and back again, which includes a void ** and a double ** any many other pointer-types. So you could have:
ErrorType function(void * ptr, int ptr_type, ...) {
void ** vpp;
double ** dpp;
...
...
switch (ptr_type) {
case PTR_TYPE_VOIDP:
vpp = ptr;
/* Now you can work with *vpp */
*vpp = ...
break;
case PTR_TYPE_DOUBLEP:
dpp = ptr;
/* Now you can work with *dpp */
*dpp = ...
break;
}
...
}

In C, is it good form to use typedef for a pointer?

Consider the following C code:
typedef char * MYCHAR;
MYCHAR x;
My understanding is that the result would be that x is a pointer of type "char". However, if the declaration of x were to occur far away from the typedef command, a human reader of the code would not immediately know that x is a pointer. Alternatively, one could use
typedef char MYCHAR;
MYCHAR *x;
Which is considered to be better form? Is this more than a matter of style?
If the pointer is never meant to be dereferenced or otherwise manipulated directly -- IOW, you only pass it as an argument to an API -- then it's okay to hide the pointer behind a typedef.
Otherwise, it's better to make the "pointerness" of the type explicit.
I would use pointer typedefs only in situations when the pointer nature of the resultant type is of no significance. For example, pointer typedef is justified when one wants to declare an opaque "handle" type which just happens to be implemented as a pointer, but is not supposed to be usable as a pointer by the user.
typedef struct HashTableImpl *HashTable;
/* 'struct HashTableImpl' is (or is supposed to be) an opaque type */
In the above example, HashTable is a "handle" for a hash table. The user will receive that handle initially from, say, CreateHashTable function and pass it to, say, HashInsert function and such. The user is not supposed to care (or even know) that HashTable is a pointer.
But in cases when the user is supposed to understand that the type is actually a pointer and is usable as a pointer, pointer typedefs are significantly obfuscating the code. I would avoid them. Declaring pointers explicitly makes code more readable.
It is interesting to note that C standard library avoids such pointer typedefs. For example, FILE is obviously intended to be used as an opaque type, which means that the library could have defined it as typedef FILE <some pointer type> instead of making us to use FILE * all the time. But for some reason they decided not to.
I don't particularly like typedef to a pointer, but there is one advantage to it. It removes confusion and common mistakes when you declare more than one pointer variable in a single declaration.
typedef char *PSTR;
...
PSTR str1, str2, str3;
is arguably clearer than:
char *str1, str2, str3; // oops
I prefer leaving the *, it shows there's a pointer. And your second example should be shortened as char* x;, it makes no sense.
I also think this is a matter of style/convention. In Apple's Core Graphics library they frequently "hide" the pointer and use a convention of appending "Ref" to the end of the type. So for example, CGImage * corresponds to CGImageRef. That way you still know it's a pointer reference.
Another way to look at it is from the perspective of types. A type defines the operations that are possible on that type, and the syntax to invokes these operations. From this perspective, MYCHAR is whatever it is. It is the programmers responsibility to know the operations allowed on it. If it is declared like the first example, then it supports the * operator. You can always name the identifier appropriately to clarify it's use.
Other cases where it is useful to declare a type that is a pointer is when the nature of the parameter is opaque to the user (programmer). There may be APIs that want to return a pointer to the user, and expect the user to pass it back to the API at some other point. Like a opaque handle or a cookie, to be used by the API only internally. The user does not care about the nature of the parameter. It would make sense not to muddy the waters or expose its exact nature by exposing the * in the API.
If you look at several existing APIs, it looks as if not putting the pointerness into the type seems better style:
the already mentionned FILE *
the MYSQL * returned by MySQL's mysql_real_connect()
the MYSQL * returned by MySQL's mysql_store_result() and mysql_use_result()
and probably many others.
For an API it is not necessary to hide structure definitions and pointers behind "abstract" typedefs.
/* This is part of the (hypothetical) WDBC- API
** It could be found in wdbc_api.h
** The struct connection and struct statement ar both incomplete types,
** but we are allowed to use pointers to incomplete types, as long as we don't
** dereference them.
*/
struct connection *wdbc_connect (char *connection_string);
int wdbc_disconnect (struct connection *con);
int wdbc_prepare (struct connection * con, char *statement);
int main(void)
{
struct connection *conn;
struct statement *stmt;
int rc;
conn = wdbc_connect( "host='localhost' database='pisbak' username='wild' password='plasser'" );
stmt = wdbc_prepare (conn, "Select id FROM users where name='wild'" );
rc = wdbc_disconnect (conn);
return 0;
}
The above fragment compiles fine. (but it fails to link, obviously)
Is this more than a matter of style?
Yes. For instance, this:
typedef int *ip;
const ip p;
is not the same as:
const int *p; // p is non-const pointer to const int
It is the same as:
int * const p; // p is constant pointer to non-const int
Read about const weirdness with typedef here typedef pointer const weirdness

How do I get the type of an object in code?

How do I figure out the type of an object in C? My goal with this is to create a linked-list container in C.
Let's assume I have a function that takes a void pointer:
...
Foo *f;
f = Allocate(f);
...
void *Allocate(void *item)
{
return malloc(sizeof(f.GetType));
}
How do I make the above syntax possible?
That's not possible. A void * pointer, is just a pointer to the memory, nothing more, no more information is attached to it. It's impossible to do what you are asking, you can't know how many bytes to malloc.
That's why, the qsort function from stdlib.h library takes as a parameter
the size in bytes of each array element. If what you suggested was possible, then
qsort wouldn't need such a parameter.
Perhaps you could do something like this:
...
Foo *f;
f = Allocate(f, sizeof(Foo));
...
void *Allocate(void *item, size_t size)
{
return malloc(size);
}
In C, there's no cross platform way to find out the underlying type of a void*, since the type information is not stored in the object. In C++ this feature has been added for objects.
You could of course implement it yourself for your own objects by - for example - storing the size of every object in the object itself, but for system objects there is no built in way.
It is just not possible to get the type using a void * to that object. If you can calculate the size of Foo before calling Allocate(), then get the size and pass it as a parameter to Allocate(), else you should make Foo visible inside Allocate() to find the size.
The only way to do this in C is to create your own type system where you include typeinfo to the types that you create. That is what has been done for instance in Objective-C. In C, all types are just a series of bytes, when you allocate memory you are allocating just bytes, what you use those bytes for is of no concern to the C compiler.
The (arguable) beauty of C is that it doesn't do this. A void pointer is just an address that could point to anything. You could either create your own object system (structures with a "type" field and a "data" field is a simple way). From your implementation, it might also be possible to stick an allocate function into the Foo structure (assuming that it is) which knows how to allocate itself (the type is known here).
void *Allocate(void *item)
{
return malloc(sizeof(f.GetType));
}
It is impossible. ISO C language does't supply any facility to get the type info through variable. Gcc's extensions contains an operator called 'typeof', it could get the type info from a real type. such as:
typeof (x[0](1))
int a; typeof (a) b; b = a;
but even though typeof also could not get the real type info from a void pointer. the code below could not be compiled succesfully:
void *Allocate(typeof(*item) *item)
{
return malloc(sizeof(*item));
}

Resources