Memory address size

Pages: 12
So yeah this is a bit of a humiliating question to ask considering I am a computer science student but nonetheless,

how big are memory addresses? I know that this will depend on the machine if it's a 64 bit or 32 bit machine etc etc, but in C++ it seems like each address is 8 bits or one byte long,so an int on most systems is 4 bytes long and a pointer to an int is just one byte long,

but https://en.wikipedia.org/wiki/Memory_address

this says that the size of a memory address depends on the size of the system,8,16,32,64 etc,

so I want to put this to rest how big is a memory address

on both a 32 bit and 64 bit system?

thanks
C++ it seems like each address is 8 bits or one byte long
How did you calculate this? I sure hope I could use more than 255 addresses!

In just about any consumer system, a memory address (i.e. a pointer data type) is 64-bits for a 64-bit computer, and 32-bits for a 32-bit computer. Note that operating systems like Windows can still run 32-bit code in the 64-bit system, so on those programs it will still be 32-bit addresses. [Obligatory note that embedded world could be different, see your manual.]

Good source code doesn't care about how big a pointer (memory address) is.
It'll always just be sizeof(<pointer type>) bytes (chars).
Last edited on
The size of a pointer depends also on the data type. sizeof(int *) and sizeof(float *) need not be equal. A void * must be able to hold any given data pointer (not necessarily pointers to functions), so sizeof(void *) is the size of the largest data pointers on the platform, in bytes.
In just about any consumer system, a memory address (i.e. a pointer data type) is 64-bits for a 64-bit computer, and 32-bits for a 32-bit computer. Note that operating systems like Windows can still run 32-bit code in the 64-bit system, so on those programs it will still be 32-bit addresses. [Obligatory note that embedded world could be different, see your manual.]


so a memory address is not 8 bits? how come a char is only 8 bits,and an int is 4 bytes, I was almost sure the size of a memory address was 8 bits (256 possible values) in size

Last edited on
A memory address probably won't be 8 bits on most systems. Certainly not anything running a modern desktop environment.

Let's say we had an array of ints.
int arr[512];
If each memory address were only 8-bit, how would we ever access arr[256] or beyond?

how come a char is only 8 bytes
sizeof(char) is defined to be 1. On most operating systems, this means 8 bits.

To calculate the number of bits a type is:
sizeof(type) * CHAR_BIT (CHAR_BIT is defined in <climits>, and is usually 8)
Last edited on
for example

https://stackoverflow.com/questions/19597984/how-much-bytes-does-an-address-take

seems to say that each memory address is 8 bits long or one byte

Let's say we had an array of ints.
int arr[512];
If each memory address was only 8-bits, how would we ever access arr[256] or beyond?


but an int is 4 bytes long? how would that affect accessing arr[256] and beyond?

arr[512] is an array of ints each int being 4 bytes? so arr[1] would be 4 bytes + arr[0],arr[2] would be 8 bytes plus arr[0],how would this affect us going beyond 256?
Last edited on
Two different things. The size of an address vs the size of the data itself.

https://stackoverflow.com/questions/19597984/how-much-bytes-does-an-address-take
That link is talking about pointer arithmetic.

If you have a pointer type T,
T* ptr;
and you do
ptr++;
the address is incremented by sizeof(T).


1
2
char* ptr;
ptr++; // ptr will be increased by sizeof(char), which is 1 



1
2
int* ptr;
ptr++; // ptr will be increased by sizeof(int), which is probably 4 



but an int is 4 bytes long? how would that affect accessing arr[256] and beyond?

arr[512] is an array of ints each int being 4 bytes? so arr[1] would be 4 bytes + arr[0],arr[2] would be 8 bytes plus arr[0],how would this affect us going beyond 256?

My point with the array example was, if an address was only 8-bits, then 8-bits can only hold values from 0 to 255, inclusive. Trying to address an index of 256 is out of the range of 8-bits, regardless of sizeof(int). C++ allows us to have arrays greater than 256 in size.
Last edited on
I think you're mis-reading the stack overflow posting. One of the properties of a computer is its "addressablity" which refers to the smallest data unit that can be represented by an address. Most modern computers are byte-addressable, which means that a hardware instruction can refer to, and operate on, a single byte of data.

So it would be correct to say that the *target of* an address (what the address points to) is a byte in this context. But the actual data that constitutes the address is generally much larger on modern machines, generally 32 or 64 bits. The larger the address (or what we refer to as a "pointer" in C and C++), the greater range it can represent.

I hope this helps a little.
That link is talking about pointer arithmetic.


but lets say we have an char,

a char is only 8 bits or one byte. so it would be a waste of memory to store one char in one 32 bit memory address right? so wouldn't this mean we could have multiple chars stored in one 32 bit address??

Memory addresses are what's stored in pointers. They refer to the location of a byte in memory. The address of an int variable is the location in memory where the first byte of the int variable is stored.
Last edited on
a char is only 8 bits or one byte. so it would be a waste of memory to store one char in one 32 bit memory address right? so wouldn't this mean we could have multiple chars stored in one 32 bit address??

I like what mzimmers said, maybe sheds some light on this.

Let's say I have an array of char, starting at address 1000.
char arr[200];
&arr[0] will be 1000.
&arr[1] will be 1001, not 1004 or 1008, or anything else. Even if we're on a future computer where addresses are 128-bits, the address of arr[1] will still be 1001.

If we have an array of int, and assume sizeof(int) == 4, then it will look like this:
int arr[200];
&arr[0] == 1000
&arr[1] == 1004
&arr[2] == 1008
etc.


An address itself doesn't determine how large something is. Whether your object's sizeof is 4 or 4000, it can still have the same memory address.
Last edited on
Let's say I have an array of char, starting at address 1000.
char arr[200];
&arr[0] will be 1000.
&arr[1] will be 1001, not 1004 or 1008, or anything else. Even if we're on a future computer where addresses are 128-bits, the address of arr[1] will still be 1001.

If we have an array of int, and assume sizeof(int) == 4, then it will look like this:
int arr[200];
&arr[0] == 1000
&arr[1] == 1004
&arr[2] == 1008
etc.


An address itself doesn't determine how large something is. Whether your object's sizeof is 4 or 4000, it can still have the same memory address.




I must be missing something here,so lets say in the first example you gave we have an array of chars which are all one byte in size, as you said the address of the first char &arr[0] will be 1000 and [1] will be 1001, so this means the memory address 1000 is 8 bits or one byte not 32 bits(assuming we are on a 32 bit system)

with the int array example we have an array of ints each integer is 4 bytes(of course this can vary but for the most part holds true) so this takes up memory address 1000 to 1004,the first 8 bits of the integer( ofcourse depending on if the system is big or little but endian but let's ignore that here )is stored in 1000 and the next 8 bits stored in address 1002 and so on, so again this means that a memory address is 8 bits or a byte??


thanks for sticking with me
It seems this is a problem of communication.

What you're calling a memory address is actually called a memory position. A memory position holds a value, while a memory address is used to locate a position in memory. As an analogy, if memory is a hotel, a memory position is a hotel room, while an address is a room number. If your hotel had a million single bed rooms, your room numbers would have a size of 7 digits, while the rooms would have a size of "one bed".
If you had a bit-addressable memory (individual bits can be accessed independently) with 65536 bits, your addresses would have 16 bits, while the positions would have a single bit.
As helios said, perhaps we should say memory position instead.
It doesn't matter how big the int datatype is itself -- it can still start at memory position of 1000.

Let's forget about specific data types. We have a computer, and it has a lot of data loaded on it. We need to access that data. Each piece of data that we want starts at a certain position in memory.
If we're in a game, and the game has one million unique trees in it, we need a way to access each tree. To do this, we access each tree at an position in memory.
If we only had 8 bits to work with in this game, we could only have 256 trees accessible. We could only address trees 1 to 256. There would be no way to access tree #257, because our memory addresses could only go up to 256.

To access all 1 million trees, we would need our memory address to be at least 20 bits long, because 220 is greater than one million.

Does that part make sense, at least on its own? If not, don't read the rest of this post.

___________________________________________

Now, let's say we have the million trees, and then we also have a player's name. We already used the first million memory positions to store our tree data. So, we can store the player's name starting at position 1,000,001.

Now, whether my name is "Bill" or "Nebuchadnezzar", I can still say that the player's name is stored starting at position 1,000,001. But "Bill" would take up 4 units, while "Nebuchadnezzar" would take up 14 units.

address 1,000,001 : B
address 1,000,002 : i
address 1,000,003 : l
address 1,000,004 : l

___________________________________________

Going back to actual data types, let's say I want to store a 2-byte int.
A 2-byte int might look like this: 1100 0011 1010 0111.
We're going to store this at the memory position 2 million, because we're already using the lower addresses for other objects. Since we need to address at least 2 million positions, we need to store this address using at least 21-bits (because 220 > 2 million) -- regardless of how big an int is.

Now, since sizeof(my 2-byte int) == 2, that means 2 positions in memory will "belong" to the int.
Memory position 2,000,000 will hold "1100 0011".
Memory position 2,000,001 will hold "1010 0111".

Different memory positions are addressable in byte-sized increments, but that doesn't mean that a memory address itself is a byte (in our case, the memory address itself needed to be at least 20 bits to hold 2 million+ possible addresses).

___________________________________________

as you said the address of the first char &arr[0] will be 1000 and [1] will be 1001, so this means the memory address 1000 is 8 bits

No, the memory address 1000 -- i.e. the actual number needed to say "this object is at the following position" -- is not 8-bits. (1000 couldn't even fit into 8 bits).
The address 1000 (which would incidentally need at least 10 bits to represent), only refers to the starting position of the data.
Last edited on
If we only had 8 bits to work with in this game, we could only have 256 trees accessible. We could only address trees 1 to 256. There would be no way to access tree #257, because our memory addresses could only go up to 256.


but why couldn't we store more than 256 trees? I understand that 8 bits can only store 0 to 256 values,but what is stopping us from creating an array larger than 256? I'm assuming for this example each tree is one bit so a memory address( if it was 8 bits) could store 256 trees,so why couldn't we just have an array of those memory address so lets say trees[500]


So if what I'm understanding is correct lets say a memory address is 32 bits long which in a lot of cases it is we can only 2^32 values in our array? we can't exceed this number? so lets say we wanted a large array of ints arr[1000000000] which is 2 digits longer than the limit,this wouldn't be possible? so we couldn't have an array of memory addresses but rather just memory positions?

hat you're calling a memory address is actually called a memory position. A memory position holds a value, while a memory address is used to locate a position in memory. As an analogy, if memory is a hotel, a memory position is a hotel room, while an address is a room number. If your hotel had a million single bed rooms, your room numbers would have a size of 7 digits, while the rooms would have a size of "one bed".
If you had a bit-addressable memory (individual bits can be accessed independently) with 65536 bits, your addresses would have 16 bits, while the positions would have a single bit.



also so if an int is 4 bytes long this means that byte 1000 is not the actual address(well it is but position in the address) but the position of where the data starts in that address or we could use the term offset?


hopefully I'm on the right track
if what I'm understanding is correct lets say a memory address is 32 bits long which in a lot of cases it is we can only 2^32 values in our array? we can't exceed this number?

Yes, almost, assuming you have that much memory, and that each value only takes up 1 byte. You won't actually be able to reach the limit because some of the memory will be used by other things.

so lets say we wanted a large array of ints arr[1000000000] which is 2 digits longer than the limit,this wouldn't be possible?

You are correct except that 4000000000 is actually not above the limit of 232 (assuming sizeof(int) == 4).

This problem is the reason why most new computers use 64 bits, because we want to be able to address more than 4 GB of memory.
Last edited on
Memory addresses are what's stored in pointers. They refer to the location of a byte in memory. The address of an int variable is the location in memory where the first byte of the int variable is stored.


going back to the above,

so for example lets use a sample program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

#include <iostream>

using namespace std;

int main()
{
    int first = 5; // 4 bytes
    char second = 'A'; // 1 byte

    int third[200]; // 4 * 200 bytes

    int* fourth = new int[300];
    char* fifth = new char[1000]; // 1000 bytes
}


ok so lets say first will be placed in memory address 1000 and is 4 bytes, so does this int first get it's own memory address?

now second will store a char or a byte,will second get it's own memory address or will it share the memory address with first and instead point to position 1004 starting in memory address starting at 1000?

will third be one memory address 4 * 200 bytes in size? or will it also share the memory address of either one or two or both?

same goes for fourth and fifth

thanks
if an int is 4 bytes long this means that byte 1000 is not the actual address(well it is but position in the address) but the position of where the data starts in that address or we could use the term offset?

I don't quite understand everything you say here. It seems like you have a misunderstanding of what an address really is.

Your program has access to a memory space. If it's a 32-bit application this memory space will consist of 232 memory addresses. Not all memory addresses will be mapped to anything so if you try to read or write to such an address you will probably get a segmentation fault which causes your program to crash.

Everything in your program share the same memory space. When you create an object it will be located somewhere in this memory space. The address is just a number that tells you the position where the object is stored in that memory space.
also so if an int is 4 bytes long this means that byte 1000 is not the actual address
No, 1000 in the previous example would be an address.
1
2
3
4
int *address = (int *)1000;
std::cout << "The int at address 1000 contains: " << *address << std::endl;
byte * raw_memory = (byte *)1000;
std::cout << "The memory position whose address is 1000 contains the byte value: " << *raw_memory << std::endl;

but the position of where the data starts
That's exactly what an address is. The address of an object is a reference to the first memory position where that object can be found.

Memory: $$%&&&&&&####
Address of $: 0 (size: 2)
Address of %: 2 (size: 1)
Address of &: 3 (size: 5)
Address of #: 8 (size: 4)
Size of memory: 12

This problem is the reason why most new computers use 64 bits, because we want to be able to address more than 4 GB of memory.
It's actually possible to design an architecture capable of using more memory than could be addressed by its addresses.

Imagine a 16-bit system whose memory consists of four 32 KiB RAM chips, labeled 0 to 3. Addresses 0x0000 to 0x7FFF are always mapped to chip 0, but the CPU can instruct the motherboard to enable or disable any of the other three chips (only one of them being enabled at any time). Such a system could use 16-bit addresses, which would normally only allow 64 KiB of RAM, to use 128 KiB of RAM.
For example, a program to clear the entire RAM might look like this:
1
2
3
4
5
6
switch_to_bank(1);
memset(0, 0, 0x10000);
switch_to_bank(2);
memset(0x8000, 0, 0x8000);
switch_to_bank(3);
memset(0x8000, 0, 0x8000);
You're using the word "in", but you should be using the word "at":
Data is placed at, not in a particular memory address. The address is merely a label, not storage.

If the four-byte int is placed at memory address 1000, then it occupies the region in memory from the beginning of location 1000 through the end of location 1003 - four bytes.

The size of the address (1000) itself is immaterial - it might be four, eight, or n bytes, but the only thing that matters is the size of the object at address 1000. In this case, it's a four byte int, but the address doesn't record that, it only says where the object is in the memory space.

If you were here I'd draw you a picture, but I can't do that so easily through a text box. Maybe a video can help?
https://www.youtube.com/watch?v=h-HBipu_1P0

Pages: 12