What does this code do ? (About pointers) - c++

I have this code and im stuck at second line
unsigned long check_password(const char* p){
int* ip = (int*)p;
int i;
int res=0;
for(i=0; i<5; i++){
res += ip[i];
}
return res;
}
int* ip = (int*)p; What does this line mean ?

int* ip = (int*)p; What does this line mean ?
It means, "create a pointer to integers which starts at the same address as p."
The function is expecting p to be pointing to a sequence of bytes that represents 5 integers.
The behaviour of this function is only defined if p really was pointing to a sequence of integers before being cast to a const char*
In practice, the author of this code is assuming:
That the sequence of bytes has been encoded in such a way that they truly represent 5 integers on this machine (taking into account word size and endian-ness of the architecture).
that the alignment of the address represented by p is correct for addressing memory as integers (some processors have restrictions in this regard).
It's probably not code you want to copy or learn from, other than as a cautionary tale.

unsigned long check_password(const char* p){
int* ip = (int*)p; // line 2, non-const not required
int i;
int res=0;
for(i=0; i<5; i++){
res += ip[i]; // line 6
}
return res;
}
Line 2 declares ip as a pointer to integer and initializes it to (int*)p. (int*)p is a C-style cast, which is in this case resolved to reinterpret_cast<int*>(const_cast<char*>(p)). See
When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?
ip now points to the memory location of p. When using ip, the memory at that location is interpreted as holding an integer, even though it holds a char; and it can be modified, even though it was initially declared const.
Line 6 treats ip as if it was pointing to the first element of an array of int and adds the ith element of that array to res. It's likely that ip actually points to the first element of an array of char. That means, that each iteration sizeof(int) consecutive elements of that array are interpreted as the representation of a single int.
The intention of this code is probably, that a sequence of 5 ints is passed as an array of char of length sizeof(int)*5.
Note that this code is UB if p doesn't actually point to memory of a size of at least sizeof(int)*5, since the memory in that region is read. I.e. the char-array must be at least of length sizeof(int)*5.
Casting away the const in your code is not required
unsigned long check_password(const char* p){
const int* ip = reinterpret_cast<const int*>(p);
int res = 0;
for (int i = 0; i < 5; ++i){
res += ip[i];
}
return res;
}

Related

Assign address of number to a pointer

int *n=(int *)5;//Valid
cout<<*n;//Invalid
Why pointer n can point to an address although 5 is not a memory location.
Why I can not print out the screen the value of n.
You are attempting to dereference memory address 0x5, which is probably restricted memory.
int *n=(int *)5;
You are casting the integer literal 5 as an int*. What that means is you are saying 0x5 is an address. When attempting to dereference that pointer with *n, you will get an error.
Instead, you would need to do something like:
int five = 5;
int *n = &five;
cout << *n;
Don't use (int *), use the address-of operator &. Also keep in mind you cannot take the address of a literal other than string literals.
Short answer: because the value of n is n. *n is the value at n: i.e., what it's pointing to.
If you want n to point to the value 5 rather than the address 5, you have to make it do so:
int x = 5;
int* n = &x;
Now n is the address of a stack location that has 5 as its value.

How to convert a byte array of size 64 to a list of double values in Arduino C++?

void Manager::byteArrayToDoubleArray(byte ch[]) {
int counter = 0;
// temp array to break the byte array into size of 8 and read it
byte temp[64];
// double result values
double res[8];
int index = 0;
int size = (sizeof(ch) / sizeof(*ch));
for (int i = 0; i < size; i++) {
counter++;
temp[i] = ch[i];
if (counter % 8 == 0) {
res[index] = *reinterpret_cast<double * const>(temp);
index++;
counter = 0;
}
}
}
Here result would be a list of double values with count = 8.
Your problem is two things. You have some typos and misunderstanding. And the C++ standard is somewhat broken in this area.
I'll try to fix both.
First, a helper function called laundry_pods. It takes raw memory and "launders" it into an array of a type of your choice, so long as you pick a pod type:
template<class T, std::size_t N>
T* laundry_pods( void* ptr ) {
static_assert( std::is_pod<std::remove_cv_t<T>>{} );
char optimized_away[sizeof(T)*N];
std::memcpy( optimized_away, ptr , sizeof(T)*N );
T* r = ::new( ptr ) T[N];
assert( r == ptr );
std::memcpy( r, optimized_away, sizeof(T)*N );
return r;
}
now simply do
void Manager::byteArrayToDoubleArray(byte ch[]) {
double* pdouble = laundry_pods<double, 8>(ch);
}
and pdouble is a pointer to memory of ch interpreted as an array of 8 doubles. (It is not a copy of it, it interprets those bytes in-place).
While laundry_pods appears to copy the bytes around, both g++ and clang optimize it down into a binary noop. The seeming copying of bytes around is a way to get around aliasing restrictions and object lifetime rules in the C++ standard.
It relies on arrays of pod not having extra bookkeeping overhead (which C++ implementations are free to do; none do that I know of. That is what the non-static assert double-checks), but it returns a pointer to a real honest to goodness array of double. If you want to avoid that assumption, you could instead create each doulbe as a separate object. However, then they aren't an array, and pointer arithmetic over non-arrays is fraught as far as the standard is concerned.
The use of the term "launder" has to do with getting around aliasing and object lifetime requirements. The function does nothing at runtime, but in the C++ abstract machine it takes the memory and converts it into binary identical memory that is now a bunch of doubles.
The trick of doing this kind of "conversion" is to always cast the double* to a char* (or unsigned char or std::byte). Never the other way round.
You should be able to do something like this:
void byteArrayToDoubleArray(byte* in, std::size_t n, double* out)
{
for(auto out_bytes = (byte*) out; n--;)
*out_bytes++ = *in++;
}
// ...
byte ch[64];
// .. fill ch with double data somehow
double res[8];
byteArrayToDoubleArray(ch, 64, res);
Assuming that type byte is an alias of char or unsigned char or std::byte.
I am not completly sure what you are trying to achieve here because of the code (sizeof(ch) / sizeof(*ch)) which does not make sense for an array of undefined size.
If you have a byte-Array (POD data type; something like a typedef char byte;) then this most simple solution would be a reinterpret_cast:
double *result = reinterpret_cast<double*>(ch);
This allows you to use result[0]..result[7] as long as ch[] is valid and contains at least 64 bytes. Be aware that this construct does not generate code. It tells the compiler that result[0] corresponds to ch[0..7] and so on. An access to result[] will result in an access to ch[].
But you have to know the number of elements in ch[] to calculate the number of valid double elements in result.
If you need a copy (because - for example - the ch[] is a temporary array) you could use
std::vector<double> result(reinterpret_cast<double*>(ch), reinterpret_cast<double*>(ch) + itemsInCh * sizeof(*ch) / sizeof(double));
So if ch[] is an array with 64 items and a byte is really an 8-bit value, then
std::vector<double> result(reinterpret_cast<double*>(ch), reinterpet_cast<double*>(ch) + 8);
will provide a std::vector containing 8 double values.
There is another possible method using a union:
union ByteToDouble
{
byte b[64];
double d[8];
} byteToDouble;
the 8 double values will occupie the same memory as the 64 byte values. So you can write the byte values to byteToDouble.b[] and read the resultingdouble values from byteToDouble.d[].

Display contents (in hex) of 16 bytes at the specified address

I'm attempting to display the contents of a specific address, given a char* to that address. So far I had attempted doing it using the following implementation
int mem_display(char *arguments) {
int address = *arguments;
int* contents_pointer = (int*)address;
int contents = *contents_pointer;
printf("Address %p: contents %16x\n", contents_pointer, contents);
}
But I keep getting a "Segmentation Fault (Core Dumped)" error. I attempted to make a dummy pointer to test on
char foo = 6;
char *bar = &foo;
But the error still persists
I'm finding it hard to explain what the problem is because almost every single line in your code is wrong.
Here's what I would do:
void mem_display(const void *address) {
const unsigned char *p = address;
for (size_t i = 0; i < 16; i++) {
printf("%02hhx", p[i]);
}
putchar('\n');
}
You need to iterate over the contents of the address, and print each one separately, until you reach 16. Example code:
#include <stdio.h>
void mem_display(unsigned char *arguments) {
printf("Address %p: ", arguments);
int i =0;
unsigned char* byte_array = arguments;
while (i < 16)
{
printf("%02hhx", byte_array[i]);
i++;
}
}
int main(void) {
unsigned char foo = 6;
unsigned char *bar = &foo;
mem_display(bar);
return 0;
}
Output:
Address 0x7ffe5b86a777: 0677A7865BFE7F000060054000000000
If you already have a pointer to the address you want to print the contents of, you can feed that straight to printf, like this:
void print_16_bytes_at(const char *arguments)
{
printf("Address %p: contents", (const void *)arguments);
for (int i = 0; i < 16; i++)
printf(" %02x", (unsigned int)(unsigned char)arguments[i]);
putchar('\n');
}
If arguments isn't a pointer to the memory you want to print the contents of, then I don't understand what it actually is and I need you to explain better.
Notes on the above sample code:
To use %p without provoking undefined behavior, you must explicitly cast the pointer to [const] void * unless it is already [const] void *. Because printf takes a variable number of arguments, the compiler does not know the expected types of its arguments, so it doesn't insert this conversion for you, as it would with a normal function that takes a [const] void * argument.
The double cast (unsigned int)(unsigned char) forces the char read from arguments[i] to be zero-extended rather than sign-extended to the width of unsigned int. If you don't do that, values from 0x80 on up are liable to be printed with a bunch of leading Fs (e.g. ffffff80) which is probably not what you want.
This will still segfault if there aren't 16 bytes of readable memory at the supplied address. In your example
char foo = 6;
print_16_bytes_at(&foo);
there is only guaranteed to be one byte of readable memory at the address of foo. (It will probably work on any computer you can readily get at, but it's still allowed to crash per the letter of the C standard.)
There are a few issues with the original code. First, it is indirecting the passed in pointer twice. It is treating arguments as a pointer to a pointer to the contents to be printed. Since arguments is a pointer to char, this is definitely wrong. (It will end up reading from a very small address, which is a definite segmentation violation or other crash on most architectures.)
Second, unless you know the arguments pointer is aligned appropriately, loading an int via that pointer may crash due to an unaligned access. (Which may well show up as a segmentation violation.) You likely cannot assume proper alignment for this routine.
Third, if you need to print 16 bytes, then an int will (typically) only get 4 or 8 of them. It will be trickier to use standard printing routines to concatenate all the pieces than to write a byte by byte loop. (See above answer for an example of such a loop.)
I think you are either overcomplicating it, or you didn't describe enough what is the actual input. Is it pointer to pointer?
Anyway, to do it in simple way with some pointer to memory, you can do it like this for example (C-like C++, sorry, done in hurry online at web cpp.sh ):
#include <iostream>
const unsigned char fakeData[] = { 1, 13, 0, 255 };
void mem_display(
std::FILE* file,
const unsigned char* memoryPtr,
const size_t size)
{
fprintf(file, "Address %p:", (const void*)memoryPtr);
for (size_t i = 0; i < size; ++i) fprintf(file, " %02hhx", memoryPtr[i]);
fprintf(file, "\n");
}
int main()
{
mem_display(stdout, fakeData, 4);
}
Output:
Address 0x4008e6: 01 0d 00 ff
To print 16 bytes just change the size argument.
I can't think of common type having 16 bytes, so I'm not sure why you are trying to print it out as single number, usually the single-byte output like above is used in debuggers (until the user requests different size unit).
For quite a long time I use following function for printing content of memory area:
/*************************************************************/
/**
* Function to dump memory area
* \param address start address
* \param len length of memory area
*/
/*************************************************************/
void dump( void* address, int len ) noexcept{
int i;
printf("dump from 0x%lX (%d bytes)\n",(long)address, len);
printf("=============================================");
for(i=0; i<len; i++){
if(i%16==0){printf("\n");}
printf("%2X ",(*((char*)address+i))&0xFF);
}
printf("\n=============================================\n");
}
For C programs delete the noexcept keyword.

Dereferencing a double-level pointer results in different behaviour from dereferencing a single-level pointer

Version 1:
int* work(int** pointer, int offset)
{
return *pointer + (offset/sizeof(int));
}
int main()
{
int** pointer = (int**) 0x4df73c;
int offset = 0xf4;
int* healthLowestPointer = work(pointer, offset);
while(true) {
*healthLowestPointer = 1000;
Sleep(250);
}
}
Version 2:
int* work(int* pointer, int offset)
{
return (int*) (*pointer + (offset/sizeof(int)));
}
int main()
{
int* pointer = (int*) 0x4df73c;
int offset = 0xf4;
int* healthLowestPointer = work(pointer, offset);
while(true) {
*healthLowestPointer = 1000;
Sleep(250);
}
}
Version 1 works correctly, but version 2 doesn't seem to. I don't understand why version 2 is broken. Isn't dereferencing a a double-level pointer the same thing as dereferencing a single-level pointer i.e. it grabs the value at the memory address the pointer contains?
How would I write a function that takes a n-level pointer as input, and returns a 1-level pointer by dereferencing the n-level pointer n-1 times?
They are very different things. An int** is a pointer to a pointer to an int. If you dereference it, you get an int*. An int* is a pointer to an int. If you dereference it, you get an int.
In the first example, you pass an int** with value 0x4df73c as the first argument to work. You then dereference this, which should give you an int*. That is, 0x4df73c is the address of an address and doing *pointer has gotten you the second addess. You then do pointer arithmetic with this int* by adding (offset/sizeof(int)), which works out how many ints there are with offset bytes. So when you add this value, your int* will move along to point at the int at that offset. You then return this int* and all is well.
In the second example, you pass 0x4df73c as an int*. You then dereference it, which gives you an int. Now the + doesn't do pointer arithmetic - it does integer arithmetic. (offset/sizeof(int)) will still give you the number of ints in offset bytes, but the arithmetic won't do what you want. It won't increase the value of the int by the appropriate amount.
Let's say an int is 4 bytes on your machine. When you have an int* called p and you do p + 5, this doesn't just add 5 to the address in p. It adds 5 times the size of an int (20 bytes), so that it's now pointing at the 5th int. However, if you have an int called i and you do i + 5, this really does just add 5.
So that's your problem. When you add to the int, you're not doing the appropriate arithmetic. I imagine it would work if you change it to, assuming an int* and an int are the same size on your system (as you say they are):
return (int*) (*pointer + offset);
but I do not recommend this. Don't use an int as though it were a pointer. The cast to the (int*) involves a reinterpret_cast and is horrible. Stick to your first code.
Pointer arithmetic and integer arithmetic are not the same thing.
Ignoring the issue of whether writing to the locations you are using is valid, consider the result of these:
int i=5;
int j=i+1; // now j==6
int* pi = &i; // let's say pi is 0x1000
int* pj = &i+1 // now pj is 0x1000 + (sizeof int)

What does (int **array;) create?

I want to know what is happening in memory when you declare:
int **array;
If I am not mistaken...
You have a multidimensional array arr[i][j] and
**arr addresses to arr[0][0]
*((*arr)+1) addresses to arr[0][1]
*(*(arr+1)+1) addresses to arr[1][1]
Sample code in C++
#include <iostream>
using namespace std;
int main()
{
int **arr;
arr = new int*[5];
for(int i = 0; i < 5; i++)
arr[i] = new int[5];
arr[0][1] = 1;
cout << *((*arr)+1); // prints 1
cout << arr[0][1] = 1; // prints 1
}
It creates a variable to store a pointer to an int pointer.
The compiler reserves four bytes (on a 32bit system, eight bytes on 64bit) to store a pointer (that would point to another pointer, that would point to an int). No further memory allocation is done, it is left to the programmer to actually set the pointer to point to some other memory location where the int*/array/... is stored.
You're declaring a pointer variable, so you're allocating enough space for one memory address (depends on your platform/compiler/etc.)
The type system will ensure that the only addresses you assign into it contain other memory addresses, and that these addresses represent the actual address of an integer variable.
To use your pointer-to-pointer, you dereference it once (to get the address that actually points to the integer), and then a second time (to get the actual integer).
You can bypass the type system by explicitly casting to something else (e.g., i=&pDouble) but that is not recommended unless you're sure you know what you're doing.
If you have a two-dimensional array, you can think of it conceptually as one single-dimensional array of single-dimensional arrays representing rows. The first level of indirection would be to pick the row, and the other one to pick the cell in the row.
It's a pointer to an int pointer. This is often used to declare a 2D array, in which case each int pointer is an array and the double pointer is an array of arrays.