I am getting quite confused alot about pointers in structures.
I have a piece of code which i do no understand fully yet,
the code:
typedef struct{
int fildes // basic file descriptor
char* location // location would be somewhere in /dev/tty*
}context0; // structure named 'context' containing the 2 elements above.
context0 someContext; // create a context struct
process(&readLocation); // takes reference from the function 'readlocation'
// i do not know what this process function does.
uint_16_t readLocation(int8_t *buffer, int16_t n, SomeContext){ // buffer pointer, n size read, and fidles
context0 foo = *(context0*) SomeContext; // ???? What Is Going ON right here ????
return read(foo.fd, buffer, n);
}
I have changed some of the names but its the code which i do not fully understand.
Some questions:
since readLocation function is passed as a reference should it not be defined as void* ? infront of the uint_32_t
main question: what does the context0 foo = * (context0*) SomeContext; do?
ok so it seems that (context0 *) is infact a typecast which is done by (int)bar to set some other type to the type of 'int'. this is done to set the variable bar to the type of context.
this typecast can also be done to a pointer type cast wich would be done as (int*) or (struct name*), or in this case (context0 *).
lastly the pointer outside of the parenthisis dereferences the structure pointer to acces whatever it points towards and places this information in the struct context0 foo.
why this is nessesary i do not know but the syntax points to this.
thanks, oh ur welcome np
and thank u Gábor Angyal, but cannot give points or whatever level 1
Related
I am learning C++ using C++ Primer 5th edition. In particular, i read about void*. There it is written that:
We cannot use a void* to operate on the object it addresses—we don’t know that object’s type, and the type determines what operations we can perform on that object.
void*: Pointer type that can point to any nonconst type. Such pointers may not
be dereferenced.
My question is that if we're not allowed to use a void* to operate on the object it addressess then why do we need a void*. Also, i am not sure if the above quoted statement from C++ Primer is technically correct because i am not able to understand what it is conveying. Maybe some examples can help me understand what the author meant when he said that "we cannot use a void* to operate on the object it addresses". So can someone please provide some example to clarify what the author meant and whether he is correct or incorrect in saying the above statement.
My question is that if we're not allowed to use a void* to operate on the object it addressess then why do we need a void*
It's indeed quite rare to need void* in C++. It's more common in C.
But where it's useful is type-erasure. For example, try to store an object of any type in a variable, determining the type at runtime. You'll find that hiding the type becomes essential to achieve that task.
What you may be missing is that it is possible to convert the void* back to the typed pointer afterwards (or in special cases, you can reinterpret as another pointer type), which allows you to operate on the object.
Maybe some examples can help me understand what the author meant when he said that "we cannot use a void* to operate on the object it addresses"
Example:
int i;
int* int_ptr = &i;
void* void_ptr = &i;
*int_ptr = 42; // OK
*void_ptr = 42; // ill-formed
As the example demonstrates, we cannot modify the pointed int object through the pointer to void.
so since a void* has no size(as written in the answer by PMF)
Their answer is misleading or you've misunderstood. The pointer has a size. But since there is no information about the type of the pointed object, the size of the pointed object is unknown. In a way, that's part of why it can point to an object of any size.
so how can a int* on the right hand side be implicitly converted to a void*
All pointers to objects can implicitly be converted to void* because the language rules say so.
Yes, the author is right.
A pointer of type void* cannot be dereferenced, because it has no size1. The compiler would not know how much data he needs to get from that address if you try to access it:
void* myData = std::malloc(1000); // Allocate some memory (note that the return type of malloc() is void*)
int value = *myData; // Error, can't dereference
int field = myData->myField; // Error, a void pointer obviously has no fields
The first example fails because the compiler doesn't know how much data to get. We need to tell it the size of the data to get:
int value = *(int*)myData; // Now fine, we have casted the pointer to int*
int value = *(char*)myData; // Fine too, but NOT the same as above!
or, to be more in the C++-world:
int value = *static_cast<int*>(myData);
int value = *static_cast<char*>(myData);
The two examples return a different result, because the first gets an integer (32 bit on most systems) from the target address, while the second only gets a single byte and then moves that to a larger variable.
The reason why the use of void* is sometimes still useful is when the type of data doesn't matter much, like when just copying stuff around. Methods such as memset or memcpy take void* parameters, since they don't care about the actual structure of the data (but they need to be given the size explicitly). When working in C++ (as opposed to C) you'll not use these very often, though.
1 "No size" applies to the size of the destination object, not the size of the variable containing the pointer. sizeof(void*) is perfectly valid and returns, the size of a pointer variable. This is always equal to any other pointer size, so sizeof(void*)==sizeof(int*)==sizeof(MyClass*) is always true (for 99% of today's compilers at least). The type of the pointer however defines the size of the element it points to. And that is required for the compiler so he knows how much data he needs to get, or, when used with + or -, how much to add or subtract to get the address of the next or previous elements.
void * is basically a catch-all type. Any pointer type can be implicitly cast to void * without getting any errors. As such, it is mostly used in low level data manipulations, where all that matters is the data that some memory block contains, rather than what the data represents. On the flip side, when you have a void * pointer, it is impossible to determine directly which type it was originally. That's why you can't operate on the object it addresses.
if we try something like
typedef struct foo {
int key;
int value;
} t_foo;
void try_fill_with_zero(void *destination) {
destination->key = 0;
destination->value = 0;
}
int main() {
t_foo *foo_instance = malloc(sizeof(t_foo));
try_fill_with_zero(foo_instance, sizeof(t_foo));
}
we will get a compilation error because it is impossible to determine what type void *destination was, as soon as the address gets into try_fill_with_zero. That's an example of being unable to "use a void* to operate on the object it addresses"
Typically you will see something like this:
typedef struct foo {
int key;
int value;
} t_foo;
void init_with_zero(void *destination, size_t bytes) {
unsigned char *to_fill = (unsigned char *)destination;
for (int i = 0; i < bytes; i++) {
to_fill[i] = 0;
}
}
int main() {
t_foo *foo_instance = malloc(sizeof(t_foo));
int test_int;
init_with_zero(foo_instance, sizeof(t_foo));
init_with_zero(&test_int, sizeof(int));
}
Here we can operate on the memory that we pass to init_with_zero represented as bytes.
You can think of void * as representing missing knowledge about the associated type of the data at this address. You may still cast it to something else and then dereference it, if you know what is behind it. Example:
int n = 5;
void * p = (void *) &n;
At this point, p we have lost the type information for p and thus, the compiler does not know what to do with it. But if you know this p is an address to an integer, then you can use that information:
int * q = (int *) p;
int m = *q;
And m will be equal to n.
void is not a type like any other. There is no object of type void. Hence, there exists no way of operating on such pointers.
This is one of my favourite kind of questions because at first I was also so confused about void pointers.
Like the rest of the Answers above void * refers to a generic type of data.
Being a void pointer you must understand that it only holds the address of some kind of data or object.
No other information about the object itself, at first you are asking yourself why do you even need this if it's only able to hold an address. That's because you can still cast your pointer to a more specific kind of data, and that's the real power.
Making generic functions that works with all kind of data.
And to be more clear let's say you want to implement generic sorting algorithm.
The sorting algorithm has basically 2 steps:
The algorithm itself.
The comparation between the objects.
Here we will also talk about pointer functions.
Let's take for example qsort built in function
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
We see that it takes the next parameters:
base − This is the pointer to the first element of the array to be sorted.
nitems − This is the number of elements in the array pointed by base.
size − This is the size in bytes of each element in the array.
compar − This is the function that compares two elements.
And based on the article that I referenced above we can do something like this:
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
int main () {
int n;
printf("Before sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
qsort(values, 5, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return(0);
}
Where you can define your own custom compare function that can match any kind of data, there can be even a more complex data structure like a class instance of some kind of object you just define. Let's say a Person class, that has a field age and you want to sort all Persons by age.
And that's one example where you can use void * , you can abstract this and create other use cases based on this example.
It is true that is a C example, but I think, being something that appeared in C can make more sense of the real usage of void *. If you can understand what you can do with void * you are good to go.
For C++ you can also check templates, templates can let you achieve a generic type for your functions / objects.
At xdn-project/digitalnote ./src/crypto/crypto.cpp file there is an error at line 338 when compiling (using cmake):
return sizeof(rs_comm) + pubs_count * sizeof(rs_comm().ab[0]);
^
error: value-initialization of incomplete type
‘Crypto::rs_comm:: []’
I found the solution on cryptonotefoundation/cryptonote:
return sizeof(rs_comm) + pubs_count * sizeof(((rs_comm*)0)->ab[0]);
I can play with Java JDK quite well, but currently at C++ need help :) It would be nice to see detail explanation of this code part:
sizeof(((rs_comm*)0)->ab[0]);
My questions are:
Asterisk after rs_comm - what its for?
0) - what is the purpose of 0 here?
The fragment of code:
struct rs_comm {
Hash h;
struct {
EllipticCurvePoint a, b;
} ab[];
};
static inline size_t rs_comm_size(size_t pubs_count) {
return sizeof(rs_comm) + pubs_count * sizeof(rs_comm().ab[0]);
}
sizeof is an operator that return the size of a specific type. It can work directly with a type or with an expression.
This part (rs_comm*)0 is taking 0 (0 is a valid null pointer constant) and casting it to a pointer of the struct rs_comm (or the class, I don't know the definition of rs_comm, but I am guessing).
Now, it is accessing using the -> operator to the data-member ab. ab has to be define as array, so it can get the first item in the array.
Because, sizeof doesn't really evaluate the expression but just figuring out the type and get the size of it.
So, the final result is the size of the first element in the array ab for the class/struct rs_comm.
So ab is an member of struct rs_comm, and is an array.
If you have a rs_comm object, i.e. rs_comm rs;, but you don't know the type of ab, you want to know its size, sizeof(rs.ab[0]) will do.
If you have a pointer to rs_comm, i.e. rs_comm *p_rs;, then sizeof(p_rs->ab[0]) will do the same thing.
If you don't have a rs_comm object nor a pointer to rs_comm, you can change a NULL pointer to a pointer to rs_comm, this is what ((rs_comm *)0) do.
Replace the p_rs in sizeof(p_rs->ab[0]) with ((rs_comm *)0), you get sizeof(((rs_comm *)0)->ab[0]).
sizeof(variable) .
return the size variable data type .
like
char x ;
cout << sizeof(x) ;
the result would be
I'm not sure if this is a good question by community standards (let me know if there is a better way or place for this question please).
I'm working on understanding a piece of code which I've come across while trying to learn C++. Code is as follows:
MessageHdr *msg;
size_t msgsize = sizeof(MessageHdr) + sizeof(joinaddr->addr) + sizeof(long) + 1;
msg = (MessageHdr *) malloc(msgsize * sizeof(char));
// create JOINREQ message: format of data is {struct Address myaddr}
msg->msgType = JOINREQ;
memcpy((char *)(msg+1), &memberNode->addr.addr, sizeof(memberNode->addr.addr));
memcpy((char *)(msg+1) + 1 + sizeof(memberNode->addr.addr), &memberNode->heartbeat, sizeof(long));
emulNet->ENsend(&memberNode->addr, joinaddr, (char *)msg, msgsize);
What is the point of casting to MessageHdr * in line 3?
I feel like we're building a char[]. We're just using MessageHdr* to refer (to point) to it but I am not sure why? Wouldn't a char* be a better choice?
Receiving code is as follows (shortened):
int EmulNet::ENsend(Address *myaddr, Address *toaddr, char *data, int size) {
en_msg *em;
...
em = (en_msg *)malloc(sizeof(en_msg) + size);
em->size = size;
memcpy(&(em->from.addr), &(myaddr->addr), sizeof(em->from.addr));
memcpy(&(em->to.addr), &(toaddr->addr), sizeof(em->from.addr));
memcpy(em + 1, data, size);
...
I'm beyond confused at this point - sorry for the vague question. Is this idiomatic C++? I feel as if this could have been done in much cleaner ways instead of passing around a char[] and referencing it via pointers of random struct types.
I guess what I'm ultimately trying to ask is, while I kind of understand the code, it feels very unnatural. Is this a valid/common approach of doing things?
EDIT
MessageHdr is a struct as follows:
typedef struct MessageHdr {
enum MsgTypes msgType;
}MessageHdr;
joinaddr is a class intances:
class Address {
public:
char addr[6];
Address() {}
// Copy constructor
Address(const Address &anotherAddress);
// Overloaded = operator
Address& operator =(const Address &anotherAddress);
bool operator ==(const Address &anotherAddress);
Address(string address) {
size_t pos = address.find(":");
int id = stoi(address.substr(0, pos));
short port = (short)stoi(address.substr(pos + 1, address.size()-pos-1));
memcpy(&addr[0], &id, sizeof(int));
memcpy(&addr[4], &port, sizeof(short));
}
string getAddress() {
int id = 0;
short port;
memcpy(&id, &addr[0], sizeof(int));
memcpy(&port, &addr[4], sizeof(short));
return to_string(id) + ":" + to_string(port);
}
void init() {
memset(&addr, 0, sizeof(addr));
}
};
The code is really confusing. I'll try to explain the first part as I understand it. The intention definitely was to create a (structured) char buffer to send it over. This was probably initially created in c, or by a c programmer.
MessageHdr *msg;
this calculates size of the resulting send buffer
size_t msgsize = sizeof(MessageHdr) + sizeof(joinaddr->addr) + sizeof(long) + 1;
allocates the buffer. The cast is needed to allow c++ to compile it, otherwise it will error-out.
msg = (MessageHdr *) malloc(msgsize * sizeof(char));
This is used to set up a field in the buffer. Since it is of Type MessageHdr, it writes the value in the correct place of the buffer
// create JOINREQ message: format of data is {struct Address myaddr}
msg->msgType = JOINREQ;
These commands use pointer arithmetic with (MessageHdr) type to write data in the buffer beyond the MessagHdr itself. msg + 1 will skip the size of the MessageHdf in the char* buffer.
memcpy((char *)(msg+1), &memberNode->addr.addr, sizeof(memberNode->addr.addr));
memcpy((char *)(msg+1) + 1 + sizeof(memberNode->addr.addr), &memberNode->heartbeat, sizeof(long));
this will send the buffer by casting it to char* first, as a simple set of bytes.
emulNet->ENsend(&memberNode->addr, joinaddr, (char *)msg, msgsize);
The receiving code seems to add yet address header to the data to send it further (tcp-ip like)
This allocates another buffer with the size of the en_msg header + size of the data.
em = (en_msg *)malloc(sizeof(en_msg) + size);
em->size = size; // keeps data size in the en_msg struct
fills out address fields in the en_msg part of the buffer
memcpy(&(em->from.addr), &(myaddr->addr), sizeof(em->from.addr));
memcpy(&(em->to.addr), &(toaddr->addr), sizeof(em->from.addr));
and this copies the data in the buffer starting just beyond the en_msg header
memcpy(em + 1, data, size);
.
You didnt give details about MessageHdr, Address and en_msg. But some of them might be structs, and not simple types.
For the first question:
malloc returns a void*, but in line 3 the allocated memory is assigned to a pointer of type MessageHdr*, thus the return value of malloc needs to be casted to the correct type.
It is quite common to use structs in this way, as it provides a simple way of dealing with lets say multiple variables of different type, which shall belong together (e. g. Address could be a struct with some int variable for the port, and a char[] for the hostname).
Example:
struct Data
{
int something;
char somethingElse[10];
};
void* foo = malloc(100); // allocate 100 bytes of memory
void* bar = malloc(sizeof(struct Data)); // allocate a piece of memory with the size of struct Data
Data* data = (Data*)bar; // use the piece of memory
data->something = 10; // as Data struct
strcpy(data->something, "bla");
Note that of course you could use the piece of allocated memory in any way you want. E. g. in the above you could just do memcpy(foo, someSource, 100) to copy 100 bytes into the allocated buffer.
In C++ you would use the new operator, which works slightly different. In addition to allocating memory for a given class, it would also call the classes constructor.
For question 2:
Again you didn't give details about MessageHdr. In case it is not a struct, but only a typedef to e. g. char[10], you are right in that you could just use char[10] instead.
However, imagine throughout your program or library you need to deal with "MessageHdr" (Message-Header?) over and over again, and every time it is a char array with the length 10. Using a typedef you gain the benefit of:
Having a named type, which others might instantly recognize and understand what it does.
The possibility to easily change the size of the char array in case at some later point it needs to change.
This code is invalid C++ code. The pointer is cast to `(MessageHDR*) in order that the compiler does not complain about this code:
msg->msgtype=JOINREQ
But this code is undefined behaviour if MessageHDR has vacuous initialization(see below): this is invalid C++ code (access object member out of its life-time period). n.m. in is comment propose you to read a book, this is the best solution, and if you read code, it would be better to read well written C++ code: stdlibc++, libc++ for exemple.
According to the c++ standard [basic.life]/1
The lifetime of an object or reference is a runtime property of the object or reference. An object is said to have
non-vacuous initialization if it is of a class or aggregate type and it or one of its subobjects is initialized by a
constructor other than a trivial default constructor. [ Note: Initialization by a trivial copy/move constructor
is non-vacuous initialization. — end note ] The lifetime of an object of type T begins when:
(1.1) — storage with the proper alignment and size for type T is obtained, and
(1.2) — if the object has non-vacuous initialization, its initialization is complete
So if MessageHDR has a non-vacuous initialization (which is the point of using C++) then [basic.life]/6
Before the lifetime of an object has started but after the storage which the object will occupy has been
allocated or, after the lifetime of an object has ended and before the storage which the object occupied is
reused or released, any pointer that represents the address of the storage location where the object will be or
was located may be used but only in limited ways. For an object under construction or destruction, see 15.7.
Otherwise, such a pointer refers to allocated storage (6.7.4.2), and using the pointer as if the pointer were of
type void*, is well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only
be used in limited ways, as described below. The program has undefined behavior if:[...]
(6.2) — the pointer is used to access a non-static data member or call a non-static member function of the
object, o
Here's my code:
#include <iostream>
using namespace std;
int main()
{
void *x;
int arr[10];
x = arr;
*x = 23; //This is where I get the error
}
As you can see, the code is very simple. It just creates a void pointer x which points to the memory address of the array 'arr' and puts the integer 23 into that memory address. But when I compile it, I get the error message "'void*' is not a pointer-to-object type". When I use an 'int' pointer instead of a void pointer and then compile it, I don't get any errors or warnings. I wanna know why I get this error.
Thank you.
As the compiler message says, void* is not a pointer to object type. What this means is that you cannot do anything with void*, besides explicitly converting it back to another pointer type. A void* represents an address, but it doesn’t specify the type of things it points to, and at a consequence you cannot operate on it.
The compiler needs the type of the variable to to dereference the pointer.
only example no malloc:
*int myPtnr = 0x12345;
When you write
*myPtr = NUMBER:
The compiler looks at the type and say .. okay here we have a int ... the Information i need are in the next 4 bytes starting with the adress of the pointer.
Thats the reason why you have to tell the compiler the type. When you use void the compiler dont know how much bytes he has to use for dereference.
you cant derefrence void*, and that is what the coder is doing.
*x = 23; // this cant be done with void*
instead :
x = &arr[index] ; // this is correct
This is just a simple question. I've been reading the source of something which attaches to a memory address of a subroutine using DetourAttach(&(PVOID &)BindKeyT, BindKeyD); where BindKeyT is the address to a subroutine in memory. I'm curious, what exactly does (&(PVOID &) mean in english? I understand that PVOID is a void pointer, but how does this get translated into a function which can be used to attach a detour to?
Terry Mahaffey is right, what you are passing is a pointer to a pointer to the function. This is commonly used whenever the function you are passing the pointer to (in this case, DetourAttach) wants to return more than one value, and one of those returned values is a pointer. Since functions in C/C++ can only return a single value, the only way to obtain multiple values from them is via pointers.
A simple example would be when one wishes to return a pointer to a block of allocated memory. Then one can write a function like:
int allocstr(int len, char **retptr)
{
char *p = malloc(len + 1); /* +1 for \0 */
if(p == NULL)
return 0;
*retptr = p;
return 1;
}
To answer your other question, of how to setup a memory address to be used as a function, one can do it like so:
void* (void * BindKeyT)(const char* key) = actual_BindKeyT;
// actual_BindKeyT is a pointer to a function that will be defined elsewhere,
// and whose declaration you will include in your project through a header file
// or a dll import
void * BindKeyD(const char* key)
{
// Code for your hook function
}
DetourAttach(&(PVOID&)BindKeyT, BindKeyD);
(taken from http://zenersblog.blogspot.com/2008/04/api-hooking-with-detours-part-1.html)
Bear in mind that the declarations for BindKeyT and BindKeyD should match.
The C++ parser in my head (which is not bug free) says that it is a C style cast of BindKeyT to a reference to a pointer to void - the (PVOID&) part - and then taking the address of that - the & in front. So the result of the expression is a pointer to a pointer to the function.
There is an introduction to Detours here: api-hooking-with-detours-part-1