I have a buffer(contains audio data) which is void pointer. In 32bit system, it's size is 4 byte and in 64 bit system, it's size is 8 byte. So how can i convert 64bit void pointer into 32bit void pointer without loosing any data ?
As long as the value in your 64-bit pointer plus the size of your buffer is less than 2^32 you can just use the lower 32 bit of your pointer. For example uint32_ptr ptr32 = static_cast<uint32_ptr>(ptr64). It is, however, not a best practice to mess with pointers like this.
In addition, I assume you'll be using these pointers in the same process on the same machine. Any other application will fail!
Related
I'm trying to read (and eventually write) memory of another process. I have the address (found using cheat engine) and I want to read it's value from my program, but I don't get the expected value. The address is 274A88A1630, but when I convert it to LPCVOID (which is required by ReadProcessMemory) I only get A88A1630 (which doesn't point to the memory I want)
I've tried converting using (LPCVOID) and (void*), both give the same result
int val = 0;
ReadProcessMemory(handle, (void*)0x274A88A1630, &val, sizeof(val), 0);
cout << val <<endl;
That happens because you have compiled your app as an x86 (32 bit/Win32) binary. Pointers (void* in this case) are 32 bits on x86. Pointers on x64 (64 bit/Win64) are 64 bits. 0x274A88A1630 is a 64 bit value, so you will therefore not encounter this problem if you compile your app for x64 (64 bit/Win64).
TLDR; A pointer value over 32 bits gets truncated to 32 bits when compiled for x86.
I have learnt that while printing the address of a variable in c, we use unsigned int (%u in format string).
Its range is from 0 to 65535. Now an integer takes 4 bytes of memory, which means a maximum of 16384 (65536/4) integers can be stored. What will happen if we try to declare an array int a[20000] and get addresses of each of its element?
#include<stdio.h>
int main(void)
{
int a[20000];
for(i=0; i<19999; i++])
printf("%u", &a[i]);
}
In early times of C, a pointer and a int where similar types, and you could safely cast from one to the other and back again. In that early time, pointers and int were both 16 bits long. It is still true on 32 bits systems where int is now 32 bits. But it is false on 64 bits systems, because pointers are 64 bits long and int only 32 bits.
So I do not know where and how you learnt that while printing the address of a variable in c , we use unsigned int(%u), but forget it ASAP because in the general case it is wrong. The only foolproof way to print an adress is %p because system automatically adapt the size to 16, 32 or 64 bits.
And no longer convert pointers to int or opposite side, because it is highly non portable. From that other post, A more portable way (on the C99 standard variant) is to #include <stdint.h> and then cast pointers to intptr_t (and back). This integer type is guaranteed to be the size of a pointer.
And, I almost forgot 65536 = 0x10000 = 216, and 232 = 4294967296. So you were not that far from reality, and it is true that in older 16 bits system you could not have int array[40000] because int were 16 bits long and the array would exhaust all the available memory.
But on 32 bits systems, you can address 4 Gb of memory, so int array[20000] is harmless.
A pointer is a memory address where you can find some data. We can find the size the of a pointer variable using sizeof( ) operator. So its size doesn't depend on what it points at .It however depends on many bytes a memory address takes up on your system, which is 4 for a 32 bit compilers and 8 for 64-bit compiler.
If we have declared a pointer, double j, type of j is double, i.e. “a pointer to double".
%p is the correct format specifier for printing a pointer. %p outputs addresses in the hexadecimal notation.
Sometimes people use %u and %x (unsigned int in hexadecimal form) specifiers to print a pointer variable. It is however an undefined behavior to pass a pointer for a %x or %u argument.
However it works with 32 bit compilers like code blocks .This is because the size of unsigned int and the pointer is same here. (Both 4 bytes)
(It is false to assume that int and pointers have the same width . For both GCC 64 bit and MSVC 64 bit running on x64, sizeof(void *) == 8, while sizeof(unsigned int) == 4. It just so happens that on some architectures pointers and ints are the same size, e.g. the PDP-11/34a, or most 32 bit architectures nowadays. But it is extremely unwise to ever write code that relies on it.
You can do add extra 2 lines as below and verify:
printf("size of unsigned int is %lu\n", sizeof(unsigned int));
printf("size of pointer is %lu\n", sizeof(int *));
On a 64-bit GCC machine with a 64-bit operating system, this should give you 4 and 8 respectively )
On a GCC 64-bit machine-%x casts your pointer to an unsigned integer (32-bit length). The size of pointer is of 8-byte (64 bit) length. Printing with %p prints the whole pointer, in its complete size – 64 bits. But when you are printing with %x, only the lower 32 bits are printed. Hence it is always safe to print a pointer with %p.
Actually unsigned integers are having range of 0 to 65536 on older 16bit compilers like turbo c. Now a days all systems are having 32 or 64 bit architecture on which unsigned integers range is 0 to 4G (giga). So this code should work fine in latest compilers like gcc (under linux) or visual studio (under windows). Try switching to these compilers. They are very good and are widely used now a days. 16bit compilers are obsolete. Avoid using such compilers. If you are using windows then code blocks or dev c++ are some good programming IDEs for learning c.
P.S. avoid using %u for printing addresses. Use %p instead.
I was just wondering how can I know if my laptop is 64 or 32 bit machine. (it is a 64).
So, I thought about printing the following:
int main()
{
printf("%d",sizeof(int));
}
and the result was 4, which seemed weird (since it is a 64 bit machine)
But, when I printed this:
int main()
{
printf("%d",sizeof(int*));
}
the result was 8, which made more sense.
The question is:
Since I'm using a 64 bit machine, shouldn't a primitive type such as int should use 8 bytes
(64 bit) and by that sizeof int should be 8? Why isn't it so?
And why is the int* size is 8?
A bit confused here,
so thanks in advance.
No, the sizeof(int) is implementation defined, and is usually 4 bytes.
On the other hand, in order to address more than 4GB of memory (that 32bit systems can do), you need your pointers to be 8 bytes wide. int* just holds the address to "somewhere in memory", and you can't address more than 4GB of memory with just 32 bits.
Size of a pointer should be 8 byte on any 64-bit C/C++ compiler, but the same is not true for the size of int.
Wikipedia has a good explanation on that:
In many programming environments for C and C-derived languages on
64-bit machines, "int" variables are still 32 bits wide, but long
integers and pointers are 64 bits wide. These are described as having
an LP64 data model. Another alternative is the ILP64 data model in
which all three data types are 64 bits wide, and even SILP64 where
"short" integers are also 64 bits wide.[citation needed] However, in
most cases the modifications required are relatively minor and
straightforward, and many well-written programs can simply be
recompiled for the new environment without changes. Another
alternative is the LLP64 model, which maintains compatibility with
32-bit code by leaving both int and long as 32-bit. "LL" refers to the
"long long integer" type, which is at least 64 bits on all platforms,
including 32-bit environments.
The sizeof(int), sizeof(int*), and "machine size", though often correlated to each other, can each be independently smaller, the same or larger than the others. About the only C requirement is that they be at least 16 bits (or so) - other than that, it compiler dependent for the sizeof(int), sizeof(int*).
(Although maybe a pointer must be at least an int size. Hmmm)
Programmers like to have integer types of 1, 2, 4 and 8 bytes or 8, 16, 32 and 64 bits. There are only two integer types that could be smaller than int: char and short. If int was 64 bits, then you couldn't have all three of the sizes 8, 16 and 32 bits. That's why compilers tend to make int = 32 bits, so you can have char = 8 bit, short = 16 bit, int = 32 bit, long long = 64 bit and long = 32 bit or 64 bit.
Because of size_t was define as
typedef unsigned int size_t;
You should display it with %zu, %u or %lu instead of %d.
printf("%zu\n", sizet);
printf("%u\n", sizet);
printf("%lu\n", sizet);
I compile the application for 64 bit Windows operating system.
The application should save 64 bit addresses, I have to decide about variable type, to save them. I thought to save them in long. But sizeof(long) == 4.Where and how can I save the addresses
You should store memory addresses in pointers:
void *myaddr = 0x0123456789ABCDEF; // memory address
int *myaddr2 = 0x0123456789ABCDEF; // pointer to int in memory, dereferencable
You can get the address of a variable like this:
int myvar;
int *addrofmyvar = &myvar;
printf("%p", addrofmyvar); // use %p to print pointers
Note: there are some differences between C and C++ regarding pointers (esp. void pointers). See the C and C++ standards. There is no such thing as "C/C++".
If you intend to store a pointer as a number, use uintptr_t or intptr_t. They are guaranteed to match the size and the representation of a pointer.
Otherwise you are not writing portable code.
You should use actual pointers (to whatever type is in the address) to store addresses.
I did'nt try it but maybe with long long will work.
Please check this link: http://msdn.microsoft.com/en-us/library/s3f49ktz%28v=vs.80%29.aspx
unsigned long long, 8 bytes,equivalent to unsigned __int64
range: from 0 to 18,446,744,073,709,551,615
Do not use LONG or LONG LONG when writing cross-platform code. LONG does not have the same size on different platforms/different compilers.
This question already has answers here:
Do all pointers have the same size in C++?
(10 answers)
Closed 5 months ago.
Is the size of a pointer the same as the size as the type it's pointing to, or do pointers always have a fixed size? For example...
int x = 10;
int * xPtr = &x;
char y = 'a';
char * yPtr = &y;
std::cout << sizeof(x) << "\n";
std::cout << sizeof(xPtr) << "\n";
std::cout << sizeof(y) << "\n";
std::cout << sizeof(yPtr) << "\n";
What would the output of this be? Would sizeof(xPtr) return 4 and sizeof(yPtr) return 1, or would the 2 pointers actually return the same size?
The reason I ask this is because the pointers are storing a memory address and not the values of their respective stored addresses.
Function Pointers can have very different sizes, from 4 to 20 bytes on an x86 machine, depending on the compiler. So the answer is no - sizes can vary.
Another example: take an 8051 program. It has three memory ranges and thus has three different pointer sizes, from 8 bit, 16 bit, 24 bit, depending on where the target is located, even though the target's size is always the same (e.g., char).
Pointers generally have a fixed size, for ex. on a 32-bit executable they're usually 32-bit. There are some exceptions, like on old 16-bit windows when you had to distinguish between 32-bit pointers and 16-bit... It's usually pretty safe to assume they're going to be uniform within a given executable on modern desktop OS's.
Edit: Even so, I would strongly caution against making this assumption in your code. If you're going to write something that absolutely has to have a pointers of a certain size, you'd better check it!
Function pointers are a different story -- see Jens' answer for more info.
On 32-bit machine sizeof pointer is 32 bits ( 4 bytes), while on 64 bit machine it's 8 byte. Regardless of what data type they are pointing to, they have fixed size.
To answer your other question. The size of a pointer and the size of what it points to are not related. A good analogy is to consider them like postal addresses. The size of the address of a house has no relationship to the size of the house.
Pointers are not always the same size on the same architecture.
You can read more on the concept of "near", "far" and "huge" pointers, just as an example of a case where pointer sizes differ...
http://en.wikipedia.org/wiki/Intel_Memory_Model#Pointer_sizes
They can be different on word-addressable machines (e.g., Cray PVP systems).
Most computers today are byte-addressable machines, where each address refers to a byte of memory. There, all data pointers are usually the same size, namely the size of a machine address.
On word-adressable machines, each machine address refers instead to a word larger than a byte. On these, a (char *) or (void *) pointer to a byte of memory has to contain both a word address plus a byte offset within the addresed word.
http://docs.cray.com/books/004-2179-001/html-004-2179-001/rvc5mrwh.html
Recently came upon a case where this was not true, TI C28x boards can have a sizeof pointer == 1, since a byte for those boards is 16-bits, and pointer size is 16 bits. To make matters more confusing, they also have far pointers which are 22-bits. I'm not really sure what sizeof far pointer would be.
In general, DSP boards can have weird integer sizes.
So pointer sizes can still be weird in 2020 if you are looking in weird places
The size of a pointer is the size required by your system to hold a unique memory address (since a pointer just holds the address it points to)