Carefullcars
Carefullcars

Reputation: 181

What can a pointer do that a variable can't do?

I'm learning about pointers and have been told this: "The purpose of pointers is to allow you to manually, directly access a block of memory."

Say I have int var = 5;. Can't I use the variable 'var' to access the block of memory where the value 5 is stored, since I can change the value of the variable whenever I want var = 6;? Do I really need a pointer when I can access any variable's value just by using its variable, instead of using a pointer that points to the address where the value is stored?

Upvotes: 6

Views: 382

Answers (5)

Schnitte
Schnitte

Reputation: 1217

One possible advantage is that it can make it easier to have one function modify a variable that will be used by many other functions. Without pointers, your best option is for the modifying function to return a value to the caller and then to pass this value to the other functions. That can lead to a lot of passing around. Instead, you can give the modifying function a pointer where it stores its output, and all the other functions directly access that memory address. Kind of like global variables.

Upvotes: 0

edmz
edmz

Reputation: 8492

"The purpose of pointers is to allow you to manually, directly access a block of memory."

This is not always true. Consider

*(int*)(0x1234) = some_value;

this is "direct" memory access. Though

int a = some_value, *ptr = &a;
*ptr = some_other_value;

you are now accessing a indirectly.

Can't I use the variable 'var' to access the block of memory where the value 5 is stored, since I can change the value of the variable whenever I want var = 6; ?

Surely; but the semantics is different.

Do I really need a pointer when I can access any variable's value just by using its variable, instead of using a pointer that points to the address where the value is stored?

No, you don't. Consider the first example: within the scope where a has been declared, modifying its value through ptr is rather pointless! However, what if you are not within the scope of a? That is

void foo(int x)
{
     x = 5;
}

int main(void)
{
    int x = 10;
    foo(x);
}

In foo, when you do x = 5, there is an ambiguity: do you want to modify foo::x or main::x? In the latter case that has to be "requested" explicitly and the fact that happens through pointers -or, better, through indirection- is a coincidence and a language choice. Other languages have others.

Upvotes: 2

BobRun
BobRun

Reputation: 754

You call a function from main() or from another function, the function you called can only return 1 value. Let say you want 3 values changed, you pass them to the called function as pointers. That way you don't have to use global values.

Upvotes: 1

alain
alain

Reputation: 12047

You can compare a memory address to a street address:

If you order something, you tell the shop your address, so that they can send you what you bought. If you don't want to use your address, you have to send them your house, such that they can place the parcel inside. Later they return your house to you. This is a bit more cumbersome than using the address!
If you're not at home, the parcel can be delivered to your neighbor if they have your address, but this is not possible if you sent them your house instead.

The same is true for pointers: They are small and can be transported easily, while the object they point to might be large, and less easily transportable.
With pointer arithmetics, pointers can also be used to access other objects than the one they originally pointed to.

Upvotes: 1

Dachschaden
Dachschaden

Reputation: 134

Pointer types have some traits that make them really useful:

  1. It's guaranteed that a pointer will be so large that it can hold any address that is supported by the architecture (on x86, that is 32 bits a.k.a. 4 bytes, and an x64 64 bits a.k.a. 8 bytes).
  2. Dereferencing and indexing the memory is done per object, not per byte.

    int buffer[10];
    char*x = buffer;
    int*y  = (int*)buffer;
    

That way, x[1] isn't y[1]

Both is not guaranteed if you use simple ints to hold your values. The first trait is at least guaranteed by uintptr_t (not by size_t though, although most of the time they have the same size - except that size_t can be 2 bytes in size on systems with segmented memory layout, while uintptr_t is still 4 bytes in size).

While using ints might work at first, you always:

  1. have to turn the value into a pointer
  2. have to dereference the pointer
  3. and have to make sure that you don't go beyond certain values for your "pointer". For a 16 bit int, you cannot go beyond 0xFFFF, for 32 bit it's 0xFFFF FFFF - once you do, your pointer might overflow without you noticing it until it's too late.

That is also the reason why linked lists and pointers to incomplete types work - the compiler already knows the size of the pointers you are going to you, and just allocates memory for them. All pointers have the same size (4 or 8 bytes on 32-bit/64-bit architectures) - the type that you assign them just tells the compiler how to dereference the value. char*s take up the same space as void*s, but you cannot dereference void*s. The compiler won't let you.

Also, if you are just dealing with simple integers, there's a good chance that you will slow down your program significantly do to something called "aliasing", which basically forces the compiler to read the value of a given address all the time. Memory accesses are slow though, so you want to optimized these memory accesses out.

Upvotes: 1

Related Questions