I am coding for re-implementing malloc function. I saw a man's example code , which has some strange code like this
struct s_block{
size_t size; // size per block
int free; // whether free flag exist
t_block pre;
t_block next;
void *magic_ptr;
int padding; // bytes for padding
char data[1]; // first byte of data, i.e. the address returned from malloc
};
typedef struct s_block *t_block;
t_block get_block(void *p) {
char *tmp;
tmp = p;
...
}
but I use gcc or g++ to compile this code, the error is "can't use void* pointer to char* pointer".
I want to know where the question arise? gcc or g++ ? code is error?
In C++ you must explicitly cast a void* to another type:
char *tmp = static_cast<char*>(p);
In C this isn't the case and you can assign a void* to any pointer type without casting.
You have to use explicit cast to cast void* to any other pointer whereas other way is implicit.
char* temp = static_cast<char*> (p);
One thing to note here is your initial pointer ( which currently is represented by void* ) should be of type char* to avoid any issues.
That is valid C code, the error you're getting is from the (more strict) C++ standard. If you want to compile that in C++, simply cast the pointer to char * explicitly.
Related
Ok - so I'll preface this by saying I'm not entirely sure how to describe the question and my current confusion, so I'll do my best to provide examples.
Question
Which of the two approaches to using the typedef-ed, fixed-length array in a memcpy call (shown below in "Context") is correct? Or are they equivalent?
(I'm starting the think that they are equivalent - some experimentation under "Notes", below).
Context
Consider the following typedef typedef uint8_t msgdata[150]; and the library interface const msgdata* IRead_GetMsgData (void); .
In my code, I use IRead_GetMsgData and memcpy the result into another uint8_t buffer (contrived example below).
//Included from library:
//typedef uint8_t msgdata[150];
//const msgdata* IRead_GetMsgData (void);
uint8_t mBuff[2048];
void Foo() {
const msgdata* myData = IRead_GetMsgData();
if(myData != nullptr) {
std::memcpy(mBuff, *myData, sizeof(msgdata));
}
}
Now, this works and passes our unit tests fine but it started a discussion between our team about whether we should dereference myData in this case. It turns out, not dereferencing myData also works and passes all our unit tests
std::memcpy(mBuff, myData, sizeof(msgdata)); //This works fine, too
My thought when writing the memcpy call was that, because myData is of type msgdata*, dereferencing it would return the pointed-to msgdata, which is a uint8_t array.
E.g.
typedef uint8 msgdata[150];
msgdata mData = {0u};
msgdata* pData = &mData;
memcpy(somePtr, pData, size); //Would expect this to fail - pData isn't the buffer mData.
memcpy(somePtr, *pData, size); //Would expect this to work - dereferencing pData returns the buffer mData
memcpy(somePtr, mData, size); //Would expect this to work - mData is the buffer, mData ==&mData[0]
I've tried searching for discussion of similar questions but haven't yet found anything that felt relevant:
Using new with fixed length array typedef - how to use/format a typedef
How to dereference typedef array pointer properly? - how to dereference a typedef-ed array and access its elements
typedef fixed length array - again how to format the typedef.
The last one in that list felt most relevant to me, as the accepted answer nicely states (emphasis mine)
[this form of typedef is] probably a very bad idea
Which, having now tried to understand what's actually going on, I couldn't agree with more! Not least because it hides the type you're actually trying to work with...
Notes
So after we started thinking on this, I did a bit of experimentation:
typedef uint8_t msgdata[150];
msgdata data = {0};
msgdata* pData = &data;
int main() {
printf("%p\n", pData);
printf("%p\n", *pData);
printf("%p\n", &data);
printf("%p\n", data);
return 0;
}
Outputs:
0x6020a0
0x6020a0
0x6020a0
0x6020a0
And if I extend that to include a suitable array, arr and a defined size value, size, I can use various memcpy calls such as
std::memcpy(arr, data, size);
std::memcpy(arr, pData, size);
std::memcpy(arr, *pData, size);
Which all behave the same, leading me to believe they are equivalent.
I understand the first and last versions (data and *pData), but I'm still unsure of what is happening regarding the pData version...
This code is, IMO, plain wrong. I'd also accept the alternative view "the code is very misleading"
//Included from library:
//typedef uint8_t msgdata[150];
//const msgdata* IRead_GetMsgData (void);
uint8_t mBuff[2048];
void Foo() {
const msgdata* myData = IRead_GetMsgData();
if(myData != nullptr) {
std::memcpy(mBuff, *myData, sizeof(msgdata));
}
}
When you dereference *myData, you mislead the reader. Obviously, memcpy requires a pointer to a msgdata, so the dereferencing star is not needed. myData is already a pointer. Introducing an extra dereference would break the code.
But it doesn't... Why?
That's where you specific use case kicks in. typedef uint8_t msgdata[150]; msgdata is an array that decays into a pointer. So, *msgdata is the array, and an array is(decays into) a pointer to its beginning.
So, you could argue: no big deal, I can leave my extra * in, right ?
No.
Because someday, someone will change the code to:
class msgdata
{
int something_super_useful;
uint8_t msgdata[150];
};
In this case, the compiler will catch it but, in general, an indirection level error might compile to a subtle crash. It would take you hours or days to find the extraneous *.
Syntax for std::fread :
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
we can call std::fread with a character pointer and get the read data with the same character pointer.
eg:
char* data;
fread(data,5,10,file);
What i tried is to create a similar function which accepts a character pointer as a void* pointer.
#include <iostream>
#include<string.h>
using namespace std;
void modify(void* ptr)
{
char* temp = new char[50];
strcpy(temp,"testing");
__ptr=(void*)temp;
std::cout<<"__ptr="<<(char*)__ptr<<endl;
}
int main()
{
char* str;
modify(str);
cout<<"str="<<str;
return 0;
}
I tried the above code with http://www.compileonline.com/compile_cpp11_online.php and I got the output as
__ptr=testing
str=
(a)Why str is not printing the string "testing"?
I am assigning the address of a dynamically allocated variable to ptr.
So the value "testing" must be available in the heap even after the control returns from the method.
(b)How can i modify the function so that i will get the output as
__ptr=testing
str=testing
But function prototype cannot be modified.
Please help.
Hope the question is clear.
The problem is that the function modify() takes a reference to a void* but you are actually passing a char*. This is not valid C++ and should not compile.
That said, there are some old C++ compilers out there (Visual C++ 6?) that have a kind of extension, that allows you to do that. That is when you are calling modify(str), the compiler is creating a temporary value of type void* and initializing it to the value of str. Then the temporary is passed to the function and taking the address of the allocated memory. But, obviously, the str original value is never modified, so it remains uninitialized.
That's the main reason why the original C++ rule forbidding this is there: to protect you from this kind of bugs.
You have two solutions:
Declare the function with the proper pointer type: void modify(char*& ptr).
Change the compiler!
If you really wanted the function as is you could call it with modify(reinterpret_cast<void*&>(str)) but I do not recommend that!
By the way, never name your identifier with two underscores (__ptr) these names are reserved for the compiler writers only·
Ah! I understand now the OP problem: his idea is to write a wrapper to fread that allocates memory, reads into it from a file and returns the pointer. It is easier if you just return the pointer the usual way. Using your modify() simplified example:
void* modify()
{
char* temp = new char[50];
strcpy(temp,"testing");
return temp;
}
And then, to call it:
char *ptr = static_cast<char*>(modify());
From the valuable answer and comments from #rodrigo, i was able to solve my problem.
I modified the function.
void modify(void* ptr)
{
char* temp;
temp = (char *)ptr;
strcpy(temp,"testing");
}
This solved all the issues!
This question already has answers here:
Need of Pointer to pointer
(5 answers)
Closed 9 years ago.
I am new to C/ C++.
I was going through some of the coding questions related to trees and came across this double pointer notation. Can we do the same things using single pointer as first argument in the below function as we can do with double pointers.
void operate(struct Node *root, struct Node **head_ref){ //do something}
There are two ways of interpreting a pointer; a reference to something, or an array. Considering this is a tree, this is probably the first: a reference to another pointer.
Every argument to a function in C is passed by value, which means that if you change the pointer inside the function, it won't be changed outside. To guarantee it is also changed outside, you can use a reference to the pointer: double pointers. You can consider the following example.
void function(int a) {
a = 5;
}
Even if a is changed above, it is not changed outside of the function. But in this other case,
void function(int * a) {
*a = 5;
}
the value a is changed outside the function as well. The same thought process can be applied to a pointer(which is also a value).
When you want a function to take care of malloc, free is the main reason.
This is useful if you want to encapsulate memory allocation.
For example some init(struct some_struct **), free(struct some_struct **).
And let functions take care of malloc, free. Instead of allocating on stack.
For example a function that packs a string of unknown length.
size_t pack_struct(char** data, const struct some_struct * some_struct)
{
/**
* #brief buffer
* #note verify the needed buffer length
*/
char buffer [256]; // temporary buffer
*data = 0;
//const char* package_pattern = "%cW ;%u.%u;%s%c";
size_t len = sprintf(buffer, weight_package_pattern,
START_CHARACTER,
some_struct->ts.tv_sec,
some_struct->ts.tv_usec,
some_struct->string_of_unknown_length, // but no more then buffer
STOP_CHARACTER);
if(len == 0) {
perror("sprintf failed!\n");
return len;
}
// len++; // for end character if wanna some, see sprintf description
*data = (char*)malloc(len*sizeof(char)); // memory allocation !
strncpy(*data, buffer, len);
return len;
}
However such technic should be avoided when programming in C++.
Double pointer is normally used when allocating memory.
#include <stdlib.h>
void new_malloc(void **p, size_t s) {
*p = malloc(s);
/* do something */
}
int main() {
int *p;
new_malloc((void **)&p, sizeof(int) * 10);
}
I have the following structure in C++ :
struct wrapper
{
// Param constructor
wrapper(unsigned int _id, const char* _string1, unsigned int _year,
unsigned int _value, unsigned int _usage, const char* _string2)
:
id(_id), year(_year), value(_value), usage(_usage)
{
int len = strlen(_string1);
string1 = new char[len + 1]();
strncpy(string1, _string1, len);
len = strlen(_string2);
string2 = new char[len + 1]();
strncpy(string2, _string2, len);
};
// Destructor
~wrapper()
{
if(string1 != NULL)
delete [] string1;
if(string2 != NULL)
delete [] string2;
}
// Elements
unsigned int id;
unsigned int year;
unsigned int value;
unsigned int usage;
char* string1;
char* string2;
};
In main.cpp let's say I allocate memory for one object of this structure :
wrapper* testObj = new wrapper(125600, "Hello", 2013, 300, 0, "bye bye");
Can I now delete the entire object using pointer arithmetic and a pointer that points to one of the structure elements ?
Something like this :
void* ptr = &(testObj->string2);
ptr -= 0x14;
delete (wrapper*)ptr;
I've tested myself and apparently it works but I'm not 100% sure that is equivalent to delete testObj.
Thanks.
Technically, the code like this would work (ignoring the fact that wrapper testObj should be wrapper* testObj and that the offset is not necessarily 0x14, e.g. debug builds sometimes pad the structures, and maybe some other detail I missed), but it is a horrible, horrible idea. I can't stress hard enough how horrible it is.
Instead of 0x14 you could use offsetof macro.
If you like spending nights in the company of the debugger, sure, feel free to do so.
I will assume that the reason for the question is sheer curiosity about whether it is possible to use pointer arithmetic to navigate from members to parent, and not that you would like to really do it in production code. Please tell me I am right.
Can I now delete the entire object using pointer arithmetic and a pointer that points to one of the structure elements ?
Theoretically, yes.
The pointer that you give to delete needs to have the correct value, and it doesn't really matter whether that value comes from an existing pointer variable, or by "adjusting" one in this manner.
You also need to consider the type of the pointer; if nothing else, you should cast to char* before performing your arithmetic so that you are moving in steps of single bytes. Your current code will not compile because ISO C++ forbids incrementing a pointer of type 'void*' (how big is a void?).
However, I recommend not doing this at all. Your magic number 0x14 is unreliable, given alignment and padding and the potential of your structure to change shape.
Instead, store a pointer to the actual object. Also stop with all the horrid memory mess, and use std::string. At present, your lack of copy constructor is presenting a nasty bug.
You can do this sort of thing with pointer arithmetic. Whether you should is an entirely different story. Consider this macro (I know... I know...) that will give you the base address of a structure given its type, the name of a structure member and a pointer to that member:
#define ADDRESS_FROM_MEMBER(T, member, ptr) reinterpret_cast<T*>( \
reinterpret_cast<unsigned char *>(ptr) - (ptrdiff_t)(&(reinterpret_cast<T*>(0))->member))
I have a void pointer called ptr. I want to increment this value by a number of bytes. Is there a way to do this?
Please note that I want to do this in-place without creating any more variables.
Could I do something like ptr = (void *)(++((char *) ptr)); ?
You cannot perform arithmetic on a void pointer because pointer arithmetic is defined in terms of the size of the pointed-to object.
You can, however, cast the pointer to a char*, do arithmetic on that pointer, and then convert it back to a void*:
void* p = /* get a pointer somehow */;
// In C++:
p = static_cast<char*>(p) + 1;
// In C:
p = (char*)p + 1;
No arithmeatic operations can be done on void pointer.
The compiler doesn't know the size of the item(s) the void pointer is pointing to. You can cast the pointer to (char *) to do so.
In gcc there is an extension which treats the size of a void as 1. so one can use arithematic on a void* to add an offset in bytes, but using it would yield non-portable code.
Just incrementing the void* does happen to work in gcc:
#include <stdlib.h>
#include <stdio.h>
int main() {
int i[] = { 23, 42 };
void* a = &i;
void* b = a + 4;
printf("%i\n", *((int*)b));
return 0;
}
It's conceptually (and officially) wrong though, so you want to make it explicit: cast it to char* and then back.
void* a = get_me_a_pointer();
void* b = (void*)((char*)a + some_number);
This makes it obvious that you're increasing by a number of bytes.
You can do:
++(*((char **)(&ptr)));