I am looking at a code dump from IDA pro. There is a function which as this layout:
garbled_name(int this...
unsigned int v5 ;
v5 = *(_Byte *)(this + 4);
...
What I am really curious about is what exactly the '+ 4' is doing? Is this an addition or something else?
Thanks
The code takes the integer 'this', adds 4 to it, casts it to a pointer to a byte, and then sets 'v5' to the value of the byte at that address.
It's just a member function of a C++ class, this being pointer to the object. This signature of the object is probably:
class some_class {
int i; // int, void*, short, anything with sizeof() <= 4, and it's not char.
// It also can be absent if it's a virtual class (AFAIK it's compiler dependend)
unsigned char c; // or c[N]
...
};
The code in question is:
some_class::some_fn(...){
unsigned int v5 = c; // or c[0]
...
};
It is a reference to the fifth byte from the beginning of the object. Depending on what compiler generated that code, it is most likely the item in class order which is at the fifth byte in the object instance.
EDIT: Sigh, I missed the "IDA Pro" part. I'll just leave this here for entertainment value, in case someone is wondering what "this+4" does in normal C++ code.
"this+4" takes your current this pointer, moves forward four times its size. Then it casts that to a byte pointer and reads it.
Consider this:
struct A {
void foo();
int x;
int y;
};
sizeof(A), on a 32-bit system, is most likely 8 bytes.
A myArray[8];
A *pA = myArray;
Now pA points to &myArray[0].
pA++;
Now pA points to &myArray[1], i.e. it moved 8 bytes forward.
void A::foo() {
A *pA = this + 4;
}
If you call this on &myArray[0], it will point to &myArray[4], i.e. 32 bytes further down the road.
Related
What is the difference between int* i and int** i?
Pointer to an integer value
int* i
Pointer to a pointer to an integer value
int** i
(Ie, in the second case you will require two dereferrences to access the integer's value)
int* i : i is a pointer to a object of type int
int** i : i is a pointer to a pointer to a object of type int
int*** i : i is a pointer to a pointer to a pointer to object of type int
int**** i : i is a pointer to a pointer to a pointer to a pointer to object of type int
...
int* pi
pi is a pointer to an integer
int **ppi
ppi is a pointer to a pointer to an integer.
EDIT :
You need to read a good book on pointers. I recommend Pointers on C by Kenneth Reek.
Let's say you're a teacher and have to give notes to one of your students.
int note;
Well ... I meant the whole class
int *class_note; /* class_note[0]: note for Adam; class_note[1]: note for Brian; ... */
Well ... don't forget you have several classes
int **classes_notes; /* classes_notes[0][2]: note for Charles in class 0; ... */
And, you also teach at several institutions
int ***intitute_note; /* institute_note[1][1][1]: note for David in class 1 of institute 1 */
etc, etc ...
I don't think this is specific to opencv.
int *i is declaring a pointer to an int. So i stores a memory address, and C is expecting the contents of that memory address to contain an int.
int **i is declaring a pointer to... a pointer. To an int. So i contains an address, and at that memory address, C is expecting to see another pointer. That second memory address, then, is expected to hold an int.
Do note that, while you are declaring a pointer to an int, the actual int is not allocated. So it is valid to say int *i = 23, which is saying "I have a variable and I want it to point to memory address 23 which will contain an int." But if you tried to actually read or write to memory address 23, you would probably segfault, since your program doesn't "own" that chunk of RAM. *i = 100 would segfault. (The solution is to use malloc(). Or you can make it point to an existing variable, as in int j = 5; int *i = &j)
Imagine you have a few friends, one of them has to give you something (a treasure... :-)
Say john has the treasure
int treasure = 10000; // in USD, EUR or even better, in SO rep points
If you ask directly john
int john = treasure;
int you = john;
If you cannot join john, but gill knows how to contact him,
int john = treasure;
int *gill = &john;
int you = *gill;
If you cannot even join gill, but have to contact first jake who can contact gill
int john = treasure;
int *gill = &john;
int **jake = &gill;
int you = **jake;
Etc... Pointers are only indirections.
That was my last story for today before going to bed :-)
I deeply believe that a picture is worth a thousand words. Take the following example
// Finds the first integer "I" in the sequence of N integers pointed to by "A" .
// If an integer is found, the pointer pointed to by P is set to point to
// that integer.
void f(int N, int *A, int I, int **P) {
for(int i = 0; i < N; i++)
if(A[i] == I) {
// Set the pointer pointed to by P to point to the ith integer.
*P = &A[i];
return;
}
}
So in the above, A points to the first integer in the sequence of N integers. And P points to a pointer that the caller will have the pointer to the found integer stored in.
int Is[] = { 1, 2, 3 };
int *P;
f(3, &Is[0], 2, &P);
assert(*P == 2);
&P is used to pass the address of P to the function. This address has type int **, because it's the address of a pointer to int.
int* i is the address of a memory location of an integer
int** is the address of a memory location of an address of a memory location of an integer
int* i; // i is a pointer to integer. It can hold the address of a integer variable.
int** i; // i is a pointer to pointer to integer. It can hold address of a integer pointer variable.
Neither is a declaration. Declaration syntax does not allow () around the entire declaration. What are these () doing there? If this is supposed to be a part of function declaration, include the whole function declaration thing in your question, since in general case the actual meaning of a declaration might depend on that. (Not in this one though.)
As for the difference... There is one * in the first and there are two *s in the second. Does it help? Probably not. The first one declares ias a pointer to int. The second one declares i as a pointer to int *. Does this help? Probably not much either. Without a more specific question, it is hard to provide a more meaningful answer.
Provide more context, please. Or, if this is actually as specific as it can get, read your favorite C or C++ book about pointers. Such broad generic questions is not something you ask on the net.
Note that
int *i
is not fully interchangeable with
int i[]
This can be seen in that the following will compile:
int *i = new int[5];
while this will not:
int i[] = new int[5];
For the second, you have to give it a constructor list:
int i[] = {5,2,1,6,3};
You also get some checking with the [] form:
int *i = new int[5];
int *j = &(i[1]);
delete j;
compiles warning free, while:
int i[] = {0,1,2,3,4};
int j[] = {i[1]};
delete j;
will give the warnings:
warning C4156: deletion of an array expression without using the array form of 'delete'; array form substituted
warning C4154: deletion of an array expression; conversion to pointer supplied
Both of these last two examples will crash the application, but the second version (using the [] declaration type) will give a warning that you're shooting yourself in the foot.
(Win32 console C++ project, Visual studio 2010)
Textual substitution is useful here, but beware of using it blindly as it can mislead you (as in the advanced example below).
T var; // var has type T
T* var; // var has type "pointer to T"
This works no matter what T is:
int* var; // pointer to int
char* var; // pointer to char
double* var; // pointer to double
// advanced (and not pure textual substitution):
typedef int int3[3]; // confusing: int3 has type "array (of size 3) of ints"
// also known as "int[3]"
int3* var; // pointer to "array (of size 3) of ints"
// aka "pointer to int[3]"
int (*var)[3]; // same as above, note how the array type from the typedef
// gets "unwrapped" around the declaration, using parens
// because [] has higher precedence than *
// ("int* var[3];" is an array (size 3) of pointers to int)
This works when T is itself a pointer type:
typedef int* T; // T is a synonym for "pointer to int"
T* var; // pointer to T
// which means pointer to pointer to int
// same as:
int** var;
So I have a defined a 8 bytes data structure
typedef struct __attribute__((__packed__)) entry{
// something here total 64 bits;
}entry_t;
and I have a void* basewhich is a pointer pointing to the base of where I want to put the entry.
Will
entry_t a;
*base = a;
do the job?
or I have to cast base to pointer to entry_t?
UPDATE
Sorry I didn't mention I can't use memcpy, because the kernel I am using doesn't implement memcpy yet.
Either:
*((entry_t *)base) = a;
or
memcpy(base, &a, sizeof a);
Of course, make sure that there are in fact 8 bytes there to copy into.
Convert the pointer to unsigned char * and write the 8 bytes with 8 uses of the assignment operator (either in a loop, or unrolled).
IN the following C++ snippet, is a=b assigment possible ??:
unsigned int * a;
D3DCOLOR b[16];
a=(unsigned int)b;
Will this assignment copy all the elements of b array to a? Is the typecast fine?
First of all, it should have been:
a = (unsigned int *)b; // note the *
More importantly, this just makes a point to contents of b, and it does not copy it. If you want to copy arrays, you have to do it explicitly, for example with a for loop or std::copy, that is if you don't want to go with classes and stuff.
Side note: to copy into a, you need memory for a! You can do it either on the stack:
unsigned int a[16]; // 16 is an example
or dynamically (for example with new).
Your code will not work, with a pointer you get access to the same memory as the object you point it to.
What do you want to do, exactly? From your code, I'd guess that the array you have is a bit array and you want the corresponding unsigned integer.
In that case, do something like this:
unsigned int a;
unsigned int length = 16;
D3DCOLOR b[length];
for(int i = 0; i < length; i++)
{
a |= b[(length-1) - i] << i;
}
This will take each bit, shift it by the requisite amount and then write it to a. Take a look at bit operations in c / c++ if you want to know more.
(Note: This code assumes big endian bit order).
What is the difference between int* i and int** i?
Pointer to an integer value
int* i
Pointer to a pointer to an integer value
int** i
(Ie, in the second case you will require two dereferrences to access the integer's value)
int* i : i is a pointer to a object of type int
int** i : i is a pointer to a pointer to a object of type int
int*** i : i is a pointer to a pointer to a pointer to object of type int
int**** i : i is a pointer to a pointer to a pointer to a pointer to object of type int
...
int* pi
pi is a pointer to an integer
int **ppi
ppi is a pointer to a pointer to an integer.
EDIT :
You need to read a good book on pointers. I recommend Pointers on C by Kenneth Reek.
Let's say you're a teacher and have to give notes to one of your students.
int note;
Well ... I meant the whole class
int *class_note; /* class_note[0]: note for Adam; class_note[1]: note for Brian; ... */
Well ... don't forget you have several classes
int **classes_notes; /* classes_notes[0][2]: note for Charles in class 0; ... */
And, you also teach at several institutions
int ***intitute_note; /* institute_note[1][1][1]: note for David in class 1 of institute 1 */
etc, etc ...
I don't think this is specific to opencv.
int *i is declaring a pointer to an int. So i stores a memory address, and C is expecting the contents of that memory address to contain an int.
int **i is declaring a pointer to... a pointer. To an int. So i contains an address, and at that memory address, C is expecting to see another pointer. That second memory address, then, is expected to hold an int.
Do note that, while you are declaring a pointer to an int, the actual int is not allocated. So it is valid to say int *i = 23, which is saying "I have a variable and I want it to point to memory address 23 which will contain an int." But if you tried to actually read or write to memory address 23, you would probably segfault, since your program doesn't "own" that chunk of RAM. *i = 100 would segfault. (The solution is to use malloc(). Or you can make it point to an existing variable, as in int j = 5; int *i = &j)
Imagine you have a few friends, one of them has to give you something (a treasure... :-)
Say john has the treasure
int treasure = 10000; // in USD, EUR or even better, in SO rep points
If you ask directly john
int john = treasure;
int you = john;
If you cannot join john, but gill knows how to contact him,
int john = treasure;
int *gill = &john;
int you = *gill;
If you cannot even join gill, but have to contact first jake who can contact gill
int john = treasure;
int *gill = &john;
int **jake = &gill;
int you = **jake;
Etc... Pointers are only indirections.
That was my last story for today before going to bed :-)
I deeply believe that a picture is worth a thousand words. Take the following example
// Finds the first integer "I" in the sequence of N integers pointed to by "A" .
// If an integer is found, the pointer pointed to by P is set to point to
// that integer.
void f(int N, int *A, int I, int **P) {
for(int i = 0; i < N; i++)
if(A[i] == I) {
// Set the pointer pointed to by P to point to the ith integer.
*P = &A[i];
return;
}
}
So in the above, A points to the first integer in the sequence of N integers. And P points to a pointer that the caller will have the pointer to the found integer stored in.
int Is[] = { 1, 2, 3 };
int *P;
f(3, &Is[0], 2, &P);
assert(*P == 2);
&P is used to pass the address of P to the function. This address has type int **, because it's the address of a pointer to int.
int* i is the address of a memory location of an integer
int** is the address of a memory location of an address of a memory location of an integer
int* i; // i is a pointer to integer. It can hold the address of a integer variable.
int** i; // i is a pointer to pointer to integer. It can hold address of a integer pointer variable.
Neither is a declaration. Declaration syntax does not allow () around the entire declaration. What are these () doing there? If this is supposed to be a part of function declaration, include the whole function declaration thing in your question, since in general case the actual meaning of a declaration might depend on that. (Not in this one though.)
As for the difference... There is one * in the first and there are two *s in the second. Does it help? Probably not. The first one declares ias a pointer to int. The second one declares i as a pointer to int *. Does this help? Probably not much either. Without a more specific question, it is hard to provide a more meaningful answer.
Provide more context, please. Or, if this is actually as specific as it can get, read your favorite C or C++ book about pointers. Such broad generic questions is not something you ask on the net.
Note that
int *i
is not fully interchangeable with
int i[]
This can be seen in that the following will compile:
int *i = new int[5];
while this will not:
int i[] = new int[5];
For the second, you have to give it a constructor list:
int i[] = {5,2,1,6,3};
You also get some checking with the [] form:
int *i = new int[5];
int *j = &(i[1]);
delete j;
compiles warning free, while:
int i[] = {0,1,2,3,4};
int j[] = {i[1]};
delete j;
will give the warnings:
warning C4156: deletion of an array expression without using the array form of 'delete'; array form substituted
warning C4154: deletion of an array expression; conversion to pointer supplied
Both of these last two examples will crash the application, but the second version (using the [] declaration type) will give a warning that you're shooting yourself in the foot.
(Win32 console C++ project, Visual studio 2010)
Textual substitution is useful here, but beware of using it blindly as it can mislead you (as in the advanced example below).
T var; // var has type T
T* var; // var has type "pointer to T"
This works no matter what T is:
int* var; // pointer to int
char* var; // pointer to char
double* var; // pointer to double
// advanced (and not pure textual substitution):
typedef int int3[3]; // confusing: int3 has type "array (of size 3) of ints"
// also known as "int[3]"
int3* var; // pointer to "array (of size 3) of ints"
// aka "pointer to int[3]"
int (*var)[3]; // same as above, note how the array type from the typedef
// gets "unwrapped" around the declaration, using parens
// because [] has higher precedence than *
// ("int* var[3];" is an array (size 3) of pointers to int)
This works when T is itself a pointer type:
typedef int* T; // T is a synonym for "pointer to int"
T* var; // pointer to T
// which means pointer to pointer to int
// same as:
int** var;
I know that converting a pointer to one int is unsafe, because the pointer can be bigger than the int in some architectures (for instance in x86_64).
But what about converting the pointer to several ints, an array of them? If the pointer size is 2 times bigger than int then convert pointer* to int[2].
The number of needed ints then is ceil(sizeof(pointer*)/sizeof(int)).
I need to do this because there is a function which takes ints as arguments and I want to pass a pointer to it.
Doesn't your platform provide a intptr_t ?
Fairly robust & portable:
void* p = foo();
std::vector<int> buf(sizeof(p));
std::copy(reinterpret_cast<char*>(&p),
reinterpret_cast<char*>(&p) + sizeof(p),
buf.begin());
What about something like this:
void *pointer = (void*) 0x0123456789ABCDEFULL;
// 4 int's max, I don't know how to do it in a generic way
assert(sizeof(pointer) <= 4*sizeof(int));
int buffer[4]; // copy from pointer to buffer
memcpy(buffer, &pointer, sizeof(pointer));
// call the function
f(buffer[0], buffer[1], buffer[2], buffer[3]);
// how to recover the value of the pointer
void f(int b0, int b1, int b2, int b3) {
int buffer[4] = {b0, b1, b2, b3};
void *pointer; // copy from buffer to pointer
memcpy(&pointer, buffer, sizeof(test_pointer));
}
I can't think of a reason to do it like that, but thats up to you :).
Usually you should not do that in a generic way, so what I'd do is, coding the 2 or 3 ways the pointer has to be transformed.
if( sizeof(pointer) == sizeof(int16) ) //or short
{
transformShortToInt(pointer);
}
else if( sizeof(pointer) == sizeof(Int32) )
{
(int)pointer;
}
else if( sizeof(pointer) == sizeof(Int64) )
{
int[2] ar = new int[2];
ar[0] = (int)(pointer & 0x0000FFFF);
ar[1] = (int)((pointer>>32) & 0x0000FFFF);
}
Although the generic code would also not be that complex.
edit: generic:
int arSize = sizeof(pointer)/sizeof(int);
if(arSize < 1)
{
arSize = 1;
}
int[] args = new int[arSize];
for( int i = 0; i < arSize; i++ )
{
args[i] = (int)((pointer>>(i*32))&0x0000FFFF);
}
although I did not test what happens with pointer >> 0 i guess it should work :).
Yet another solution:
#define BIG_ENOUGH 4
typedef union {
int buffer[BIG_ENOUGH];
pointer_t* pointer;
} proxy_t;
static_assert(sizeof(pointer_t*) <= BIG_ENOUGH*sizeof(int));
// before calling the function
proxy_t proxy;
proxy.pointer = the_pointer;
// call to the function, cannot be generic here
f(proxy.buffer[0], proxy.buffer[1], proxy.buffer[2], proxy.buffer[3]);
// how to recover the value of the pointer
void f(int b0, int b1, int b2, int b3) {
proxy_t proxy = { { b0, b1, b2, b3 } };
the_pointer = proxy.pointer;
}
if a function takes an array of ints, then yes you can manually detect the size of void* versus the size of int on your machine and save your pointer to array[0] + array[1], etc.
It's a bit hard to tell what's really needed from your description. What will the function do? Will you have to handle big/little-endian difference, for example?
I have macros for this:
#define DIM_ARR(arr) (sizeof(arr) / sizeof(arr[0]))
Even if array is empty - this construction (sizeof(arr[0])) resolved on compile time - that is why you will get correct size
you said you want to pass a pointer to a function with int as arguments.
If your pointer points to an integer or character or float you can always dereference it, caste it and pass by value.
Or, if you really want to pass by address, then modify the function definition to take pointer as argument.
Or, if you are using some library function then you are on the wrong way man.
And even you convert it to an array of ints, how are going to pass the array?, array are always passed by address.