Is this C code wrong? - c

I know that pointers contain the addresses of variables, for example:
int c = 5;
int *p;
p = &c;
printf("%d",*p); // Outputs 5.
But what if I want to send an address to a function:
void function (int *p)
{
p++;
}
int c;
function (&c);
When function is called, the value of &c is assigned to int *p. I guess that the exact instruction is: *p = &c;, but I don't understand what this means.

I prefer to write int* p = &c;, that is, a pointer to type int is being assigned the address of c.
Pointer notation can be confusing, as you've noticed, because these two are equivalent:
int *p = &c;
and
int *p;
p = &c;
Hope this helps!
EDIT: The confusion comes because * is used both as the dereference operator, and for declaring a pointer. So when p contains the address of c, *p dereferences the pointer and returns the value of c. But when you say int *p = &c;, the * is saying "p is a pointer to an int", but is not doing any dereferencing.

*p = &c; means:
Get the address of c in memory which is determined at compile-time link-time (Thanks Mikeage) e.g, 0x1234 as an example. The pointer to type int, i.e. *p is assigned to 0x1234, which does not sound right to me, I think you should be doing it this way, p = &c then *p would have the value pointed to by the address of c. And therefore *p would have the value of what c was assigned to (that is called dereferencing - by putting a * before the pointer variable then you can obtain the value).
In your function you are trying to increment the value pointed to by p.
void function (int *p)
{
*p++;
}
// It would be called like this
int c = 5;
function(&c); // Now c would have 6!
The key point is you want to pass by reference which is what the parameter &c does.
If you omit the passing by reference like this:
void function (int p)
{
p++;
}
// And call it like this
int c = 5;
function(c); // c is still 5
Now c would still be 5, but within the function itself c is 6, but no copy is passed back out as it is incremented within the local stack for the function itself.

I can't really make out your question, but the function looks like bug to me and what you meant is, perhaps,
++(*p)
Otherwise it's a no-op.

If you want the function to increment c when called with &c, then write this:
void function(int *p) { ++(*p); }
function(int *p) means that p is the function parameter. So whatever value the caller gives, that will be assigned to p (not to *p).
The type of p is int *. That is, p is a pointer-to-int.
If p is a pointer-to-int, then *p is the int it points to.
c is an int. Therefore &c is a pointer-to-int, and the int it points to is c. Therefore, if p is &c, then *p is c.
With my version of the function, this code:
int c = 5;
function(&c);
Does the same as this code:
int c = 5; // same as before
int *p; // parameter of the function
p = &c; // assign the caller's value to the parameter
++(*p); // body of the function, increments *p, which is the same as c.
Which does the same as this code:
int c = 5;
++c;

Are you sure p++; is what you mean to do in your function? That's incrementing the location pointed to by p, it's not incrementing the value at the current location. If you're wanting to increment the value (i.e. make c become 6), then what you want is (*p)++;.

Others have answered your question. I will just add that a helpful way of reading pointer declarations is this. Let's say I have the following declaration:
int i;
This is really easy. Here, i is an int. Now, let's say I have this:
int *pi;
Here, you can either say that pi is a pointer to an int (which is correct). Another way to look at it would be that *pi is an int, i.e., when you have *pi in your code, that *pi will be of type int. Having understood that, I think it's easy to see that ++pi or pi++ doesn't increment the int, because pi is the wrong type. You want (*pi)++. The parentheses are needed because in C, the operator ++ has higher precedence than the unary operator *. Since you don't use any of the side effects of the increment, you can as well do: ++*p.
Of course, as with all the pointers, pi has to point to something useful for the above to make sense.

Related

Is "int *x" a pointer to the type int or is it a pointer to an integer value?

In int *x x is a pointer to integer.
If we initialize with a statement something like this: int *x = &p now x is pointing to the address of "p".
The value that it produces is: 6422036
Does that mean in int *x x is a pointer to the type int or it's a pointer to an integer value?
Is it conceptually something like int *x = &int as default?
When I compile this:
#include <stdio.h>
main ()
{
int *x;
printf("%d", x);
return 0;
}
It gives the value 16.
What does it mean?
I think your question is based on a misunderstanding, so I am going to do some bean-counting on your phrasings. (Not contradicting ikegami by the way, just trying to provide a different approach or viewpoint.)
In int *x x is a pointer to integer.
Yes.
if we initialize the statement with something like this: int *x = &p now x is pointing to the address of p.
Not exactly, now x contains the address of p (which hopefully is an int). It is considered to point to p.
The value that it produces is: 6422036
If you say so, but that is not reproducable and you should probably never think or know about that value. Any other value at this point would means the same - or nothing.
Does that mean in int *x x is a pointer to the type int or it's a pointer to an integer value?
Yes.
To be precise, for a C programmer those are one and the same thing.
Whatever it is pointing to is an integer value, i.e. it is of int type. (Skipping the differences of unsigned int, long int, short etc., I am convinced you are not asking about that.)
If you see a difference between those two, then your understanding is not C (I suspect it comes from a different language, see introspection as discussed by ikegami.)
is it conceptually something like int *x = &int as default?
No. There is no such thing as &int in C. It is more like
int *x; /* Don't you dare dereference this before you assigned a decent address.
and be sure to assign an address of something you are actually allowed
to at least read - or expect little demons flying out of your nose. */
Note that "demons flying out of your nose" is practically a technical term used among programmers to describe that absolutely anything can happen, usually undesired things. Most undesired possible result is that it passes all tests and then fails catastrophically in the most inconvenient situation.
Actually it is called undefined behaviour.
C doesn't have reflection. There's no int type in memory, just values of that type. As such, x isn't a pointer to the type int. It is indeed a pointer to an integer value.
Given int *x, we can say:
*x is an int
x is an int*, which is to a pointer to an int.
That assumes x has been properly initialized and isn't NULL. This isn't the case in your program. Reading x before giving it a value is a bug.
Also, providing a pointer to %d is a bug. To display a pointer, you need
printf("%p\n", (void*)x); // One of the weird times when a `void*` cast is needed.
Again, this is only legit after you initialize x.
A valid program:
#include <stdio.h>
int main(void)
{
int i = 123;
int *p = &i;
printf("%p\n", (void*)p);
printf("%p\n", (void*)&i);
printf("%p\n", (void*)&p);
printf("%d\n", i);
printf("%d\n", *p);
return 0;
}
Does that mean in int *x x is a pointer to the type int or it's a pointer to an integer value?
x is an object stores values of type int *; that is, it stores the address of an int object.
It gives the value 16.
What does it mean?
It means you've invoked undefined behavior - you're using the wrong format specifier for the type.
The proper way to print a pointer value is
printf( "%p\n", (void *) x );
In the declaration
int *x;
the initial value of x is indeterminate - it could be anything, from 0x00000000 to 0x00000010 (16) to 0xDEADBEEF to anything else.
There's nothing magic about pointer variables - they store values of a specific type, like an int variable stores integer values and double variable stores floating-point values.
Pointer declaration syntax and operations on pointers are a little non-intuitive and hard to grasp at first, but pointer values themselves are relatively simple things to understand; they're just addresses1 of objects (or functions) in memory.
There's no single pointer type - an int * is a distinct type from a double *, which is a distinct type from a char *, etc. Different pointer types may have different sizes or representations, but on platforms like x86 they all have the same representation.
In a declaration, the presence of a unary * in the declarator means the variable has pointer type:
T *p; // p is a pointer to T
T *ap[N]; // ap is an array of pointers to T
T (*pa)[N]; // pa is a pointer to an array of T
T *fp(); // fp is a function returning a value of type pointer to T
T (*pf)(); // pf is a pointer to a function returning a value of type T
T **pp; // pp is a pointer to pointer to T - it stores the address of
// an object of type T *
In an expression, the presence of the unary * operator means we want to dereference the pointer and obtain the value of the thing it points to:
int x = 10;
int *p = &x; // save the address of x in p
printf( "%d\n", *p ); // print the value stored in x by dereferencing p
More properly, they're abstractions of addresses. Whether those addresses are physical or virtual depends on the environment you're operating in.

Pointers of pointer and pass by reference

I'm struggling to understand how pointers work.
The way I got it is that, when I declare a pointer to, say, int, I create both a variable that'll contain an address (that must be initialized to even operate on the int) and an int variable. Visually, I'd represent this this way (address;int). For example, if I declared
int* number;
I'd have "number" being the address variable and "*number" being the int variable.
Likewise, declaring something such as int** d should mean to create a pointer to (address;int). That'd be [address;(address;int)].
With this in mind, I was trying to modify the int value of **d by using an external function, incrementer_3, and this so called pass by reference, but I get an error on runtime. So, I was wondering what I'm missing.
#include <stdio.h>
void incrementer(int* a) {
(*a)++;
}
void incrementer_2(int** a) {
(**a)++;
}
void incrementer_3(int*** a) {
(***a)++;
}
int main() {
int b = 7;
incrementer(&b);
printf("%d\n", b);
int* c = (int*)malloc(sizeof(int));
*c = 4;
incrementer_2(&c);
printf("%d\n", *c);
int** d = (int**)malloc(sizeof(int*));
**d = 6;
incrementer_3(&d);
printf("%d\n", **d);
system("pause");
}
FYI the part when I increase b and c works fine.
On a side note, I was also wondering if it's possible to modify the value of *c by using the function "incrementer" and not "incrementer_2". In fact I was just thinking that I could have simply written from main
incrementer(&(*c));
or, in a simpler way
incrementer(c);
but none of them work on runtime.
You need to keep in mind that a pointer need not actually refer to anything, and even if it does refer to something that something need not be valid. Keeping track of those things is your job as a programmer.
By convention an invalid pointer will be given the value 0 (which is what NULL eventually comes to) but that is only convention, other values might be used in some circumstances.
So, with "int* number;" you have declared a pointer-to-int but because it is not initialized you have absolutely no idea what value it contains, dereferencing it at this point is undefined behavior - meaning that most anything could happen if you tried doing so, though in reality it will likely simply crash your program.
The problem with:
int** d = (int**)malloc(sizeof(int*));
**d = 6;
is that while d is initialized *d is not. You could do:
*d = malloc(sizeof(int));
or
*d = c;
but *d needs to be pointed at something before you can use **d.
int b
b is an int. We can refer to it by writing b.
b = 7;
Here we assign a number to b.
int* c
c is a pointer that should point to an int. We can refer to that int by writing *c.
c = (int*)malloc(sizeof(int));
We have found a piece of memory that can hold an int, and made a pointer that points to that piece, and assigned it to c. All is well.
*c = 4;
Here we assign a number to *c. See? *c behaves just like b. But that's only because we have initialised it with a valid pointer! Without that, *c = 4; would be invalid.
int** d
d is a pointer that should point to a thing of type int*, which we can refer to by writing *d. That int* thing, in turn, should point to an int, which we can refer to by writing **d.
d = (int**)malloc(sizeof(int*));
We have found a piece of memory that can hold an int*, and made a pointer that points to that piece, and assigned it to d. All is well. Now that int* we call *d, what does it point to?
Nothing. In order to point it to something, we could have found a piece of memory that can hold an int, and made a pointer that points to that piece, and assigned it to our *d, just as we have done earlier with c. See? *d behaves just like c. In order to use *c we had to initialise c with a valid pointer first. In order to use **d we need to initialise *d with a valid pointer first.
*d = (int*)malloc(sizeof(int));
The problem is that you allocate memory for the int* but you don't allocate any memory for the int or set the pointer of the int.
Should be:
int** d = (int**)malloc(sizeof(int*));
*d = (int*)malloc(sizeof(int));
**d=6;
The way I got it is that, when I declare a pointer to, say, int, I create both a variable that'll contain an address (that must be initialized to even operate on the int) and an int variable.
No, when you declare a pointer you create a variable that knows how to contain an address. When you use malloc() you allocate memory. malloc() returns an address that you may assign to your pointer.
P.S. - incrementer(c) should work just fine

When to use * in pointer assignment? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
As I'm learning C I often see pointers.
I get that a pointer is holding the hexadecimal value of a distinct location in memory. So a pointer is nothing other than e.g.:0x7fff5fbff85c
Every pointer is also of a distinct type.
int var = 10;
int *ptr = &var;
Ptr here points to the location of var. To get the value of var I have to dereference the pointer with *ptr.
Like
printf("Var = %d", *ptr);
would print `Var = 10;
However If I do a non inline declaration of a pointer like:
int var = 10;
int *ptr;
ptr = &var;
I don't have to use the * in the third line when I'm actually assigning the memory adress to the pointer.
But when I got a function that takes a pointer:
int var = 10;
void assignPointer(int *ptr) {
*ptr = 10;
}
Oh, wait! As I'm writing this I recognized that there are two different assignments for pointers:
*ptr = 10;
and
ptr = &var;
What is the difference? Am I in the first case first dereferencing the pointer, assigning 10 to the location that its holding?
And in the second case I'am assigning the actual location to the pointer.
I'm a little bit confused when to use the * and when not to in terms of assignment.
And if I'm working with arrays, why do I need pointers at all?
int array[];
"array" here is already holding the hexadecimal memory location. Doesn't that make it a pointer? So If I wanted to assign something to array wouldn't I write:
*array = [10, 2];
First I'm dereferencing, then I'm assigning.
I'm lost :(
EDIT: Maybe it's a bit unclear.
I don't know when you have to use a * when you are working with pointers an when not.
Everything that is carrying a hexadecimal is a pointer right?
The variable name of an array is carrying it's hexadecimal memory location. So why isn't it a pointer?
EDIT2: Thank you people you helped me a lot!
I don't know when you have to use a * when you are working with pointers an when not. Everything that is carrying a hexadecimal is a pointer right? The variable name of an array is carrying it's hexadecimal memory location. So why isn't it a pointer?
Last thing first - the name of an array is not a pointer; it does not store an address anywhere. When you define an array, it will be laid out more or less like the following:
+---+
arr: | | arr[0] Increasing address
+---+ |
| | arr[1] |
+---+ |
... |
+---+ |
| | arr[n-1] V
+---+
There is no storage set aside for an object arr separate from the array elements arr[0] through arr[n-1]. C does not store any metadata such as length or starting address as part of the array object.
Instead, there is a rule that says if an array expression appears in your code and that expression is not the operand of the sizeof or unary & operators, it will be converted ("decay") to a pointer expression, and the value of the pointer expression will be the address of the first element of the array.
So given the declaration
T arr[N]; // for any type T
then the following are true:
Expression Type Decays to Value
---------- ---- --------- -----
arr T [N] T * Address of first element
&arr T (*)[N] n/a Address of array (same value
as above
*arr T n/a Value of arr[0]
arr[i] T n/a Value of i'th element
&arr[i] T * n/a Address of i'th element
sizeof arr size_t Number of storage units (bytes)
taken up by arr
The expressions arr, &arr, and &arr[0] all yield the same value (the address of the first element of the array is the same as the address of the array), but their types aren't all the same; arr and &arr[0] have type T *, while &arr has type T (*)[N] (pointer to N-element array of T).
Everything that is carrying a hexadecimal is a pointer right?
Hexadecimal is just a particular representation of binary data; it's not a type in and of itself. And not everything that can be written or displayed in hex is a pointer. I can assign the value 0xDEADBEEF to any 32-bit integer type; that doesn't make it a pointer.
The exact representation of a pointer can vary between architectures; it can even vary between different pointer types on the same architecture. For a flat memory model (like any modern desktop architecture) it will be a simple integral value. For a segmented architecture (like the old 8086/DOS days) it could be a pair of values for page # and offset.
A pointer value may not be as wide as the type used to store it. For example, the old Motorola 68000 only had 24 address lines, so any pointer value would only be 24 bits wide. However, to make life easier, most compilers used 32-bit types to represent pointers, leaving the upper 8 bits unused (powers of 2 are convenient).
I don't know when you have to use a * when you are working with pointers an when not.
Pretty simple - when you want to refer to the pointed-to entity, use the *; when you want to refer to the pointer itself, leave it off.
Another way to look at it - the expression *ptr is equivalent to the expression var, so any time you want to refer to the contents of var you would use *ptr.
A more concrete example might help. Assume the following:
void bar( T *p )
{
*p = new_value(); // write new value to *p
}
void foo( void )
{
T var;
bar( &var ); // write a new value to var
}
In the example above, the following are true:
p == &var
*p == var
If I write something to *p, I'm actually updating var. If I write something to p, I'm setting it to point to something other than var.
This code above is actually the primary reason why pointers exist in the first place. In C, all function arguments are passed by value; that is, the formal parameter in the function definition is a separate object from the actual parameter in the function call. Any updates to the formal parameter are not reflected in the actual parameter. If we change the code as follows:
void bar( T p )
{
p = new_value(); // write new value to p
}
void foo( void )
{
T var;
bar( var ); // var is not updated
}
The value of p is changed, but since p is a different object in memory from var, the value in var remains unchanged. The only way for a function to update the actual parameter is through a pointer.
So, if you want to update the thing p points to, write to *p. If you want to set p to point to a different object, write to p:
int x = 0, y = 1;
int *p = &x; // p initially points to x
printf( "&x = %p, x = %d, p = %p, *p = %d\n", (void *) &x, x, (void *) p, *p );
*p = 3;
printf( "&x = %p, x = %d, p = %p, *p = %d\n", (void *) &x, x, (void *) p, *p );
p = y; // set p to point to y
printf( "&y = %p, y = %d, p = %p, *p = %d\n", (void *) &y, y, (void *) p, *p );
At this point you're probably asking, "why do I use the asterisk in int *p = &x and not in p = y?" In the first case, we're declaring p as a pointer and initializing it in the same operation, and the * is required by the declaration syntax. In that case, we're writing to p, not *p. It would be equivalent to writing
int *p;
p = &x;
Also note that in a declaration the * is bound to the variable name, not the type specifier; it's parsed as int (*p);.
C declarations are based on the types of expressions, not objects. If p is a pointer to an int, and we want to refer to the pointed-to value, we use the * operator to dereference it, like so:
x = *p;
The type of the expression *p is int, so the declaration is written as
int *p;
C syntax is weird like this. When you declare a variable, the * is only there to indicate the pointer type. It does not actually dereference anything. Thus,
int *foo = &bar;
is as if you wrote
int *foo;
foo = &bar;
Pointers are declared similar to regular variables.The asterisk character precede the name of the pointer during declaration to distinguish it as a pointer.At declaration you are not de-referencing,e.g.:
int a = 0;
int *p = &a // here the pointer of type int is declared and assigned the address of the variable a
After the declaration statement,to assign the pointer an address or value,you use it's name without the asterisk character,e.g:
int a;
int *p;
p = &a;
To assign the target of the pointer a value,you dereference it by preceding the pointer name with *:
int a = 0;
int *p;
p = &a;
*p = 1;
Dereferenced pointer is the memory it points to. Just don't confuse declaring the pointer and using it.
It may be a bit easier to understand if you write * in declaration near the type:
int* p;
In
int some_int = 10;
int* p = &some_int; // the same as int *p; p = &some_int;
*p = 20; // actually does some_int = 20;
You are pretty much correct.
Am I in the first case first dereferencing the pointer, assigning 10 to the location that its holding? And in the second case I'am assigning the actual location to the pointer.
Exactly. These are two logically different actions as you see.
"array" here is already holding the hexadecimal memory location. Doesn't that make it a pointer?
And you got the grasp of it as well here. For the sake of your understanding I would say that arrays are pointers. However in reality it is not that simple -- arrays only decay into pointers in most circumstances. If you are really into that matter, you can find a couple of great posts here.
But, since it is only a pointer, you can't "assign to array". How to handle an array in pointer context is usually explained in a pretty good way in any C book under the "Strings" section.
You are right about the difference between assignment and dereferencing.
What you need to understand is that your array variable is a pointer to the first element of your continuous memory zone
So you can access the first element by dereferencing the pointer :
*array = 10;
You can access the nth element by dereferencing a pointer to the nth element :
*(array + (n * sizeof(my_array_type)) ) = 10;
Where the address is the pointer to the first element plus the offset to the nth element (computed using the size of an element in this array times n).
You can also use the equivalent syntax the access the nth element :
array[n] = 10;
One of your examples isn't valid. *ptr = 10;. The reason is that 10 is a value but there is no memory assigned to it.
You can think of your examples as "assigning something to point at the address" or "the address of something is". So,
int *ptr is a pointer to the address of something. So ptr = &val; means ptr equals the address of val. Then you can say *ptr = 10; or val = 10; cause both *ptr and val are looking at the same memory location and, therefore, the same value. (Note I didn't say "pointing").

Confusion about how pointers are declared in C

The syntax commonly used in C to initialize pointers is
int *p = &x;
where p is our pointer and x is a previously declared variable. I unfortunately don't understand this syntax: *p is not equal to &x, but is instead equal to x. So why isn't the correct syntax
int *p = x;?
Does the compiler simply make an exception to the normal rules of variable assignment when dealing with pointers?
read it this way
int* p = &x;
ie int* is a type - a pointer to an int;
C declaration syntax is admittedly confusing. It generally follows the rule that "declaration follows use", but that's not a hard and fast rule.
The type name int* means "pointer to int", but to define an object p of type "pointer to int", we don't simply write that type name followed by the name of the object:
int* p;
Instead, we write:
int *p;
which means that *p is of type int; it follows from that that p must be of type int*.
You've probably noticed that both declarations are the same except for the spacing -- and the compiler doesn't care about spacing. In fact, some programmers prefer to write int* p;, even though it doesn't strictly follow the grammar, because it's clearer in this case.
The distinction becomes important if you want to define multiple objects in a single declaration:
int *p, *q;
means that *p and *q are both of type int. And
int *x, y;
means that *x and y are of type int -- which means that x is an int* and y is an int. Programmers who prefer to place the * next to the int need to split this up into two lines (which is a good idea anyway).
So for an object declaration, the extra specifiers are associated with the name being defined, not with the type. But an initializer applies to the newly created object. So this:
int *p;
means that *p is of type int, but this:
int *p = &x;
means that p itself is initialized with the value &x.
I won't try to argue that this is how C's declaration syntax should have been defined. It has its own consistent logic to it, but it's caused a lot of confusion. But it is the way it is.
The * character has a different meaning depending on where you find it. I can think of three meaning off the top of my head:
1. In a declaration
int *x;
Here, we are writing a variable declaration. We are creating a variable named x with type int *.
2. As a dereference in an expression
int *x = malloc(sizeof(int));
int y = *x;
Here we are using the same token but note that it is now inside an expression! (The right hand side of the equal sign is an expression). Here it means dereference.
3. As multiplication
int *x = malloc(sizeof(int));
int y = *x * *x;
Here we are using the same character for multiplication!
So what gives?
The compiler is able to use the context around the * character to determine which of these three cases we are in. It's certainly arguable that we should have different characters to represent these three things, but that's not the language that we have.
Going back to your declaration.
int *p = &x;
Let's take the first half. The "int *p" tells the compiler that the variable 'p' has a location in memory as a value and it should be interpreted as an 'int'. The second half, '&x', means to get me the location in memory of the variable x. So you can save 'location in memory of variable x' into a variable that represents 'location in memory.'
A real world analogy would be if you have houses on a street, each with an address (one of the houses would be 'x' in your example), and you also have a postcard, 'p,' on which you can write the address of a house. You can't put the house, x, on the postcard. You can only put the address of the house, &x, on the postcard.
int *p = &x;
When prefixed with a * in a declaration, an identifier is defined to be a pointer to the given type. For example, p is a pointer to x; Read it like this:
declare a pointer to an int called p
to the pointer p, assign the following value: the address of x
If we want to use p to get the value of x, we do what is called dereferencing: *p
For example:
int x = 35;
int *p = &x;
printf("x = %d\n", *p); // Prints x = 35
printf("%p\n", p); // Prints the address of x (which is the same as the value of p)
printf("%p\n", &p); // Prints the address of the variable p
int x = 5; // Declaring an integer 'x' and initializing it with the value 5.
int *p1 = &x; // Declaring Pointer 'p1' & Initializing it with address of 'x'.
printf("x = %d\n", *p1); // De-referencing Pointer 'p1' to get value of 'x'.
int *p2 = NULL; // Declaraing a Pointer to an int. Initialize it to NULL.
p2 = &x; // Assigning address of 'x' to pointer 'p2'.
printf("x = %d\n", *p2); // De-referencing Pointer 'p2' to get value of 'x'.

Strange (for me) behavior of pointers

I'm reading about pointers, but i'm confused about their nature. Here is what I mean.
int x = 4;
//Here I declare p as integer pointer
int *p;
// Here I assign memory address of x to pointer p
p = &x;
// The line below prints result 4 which is expected. If I miss asterisk before p I'll get memory address instead of data which that memory address holds.
printf("%d", *p)
Summarizing when asterisk is mising before pointer it "points" to memory address. If asterisk preceded pointer it "points" to actual data.
So far so good.
But why that segment of code works correctly ?
int someIntVariable = 10;
const int *p = &someIntVariable;
printf("%d", *p);
If I miss asterisk the compiler gives me an warning " warning: initialization makes integer from pointer without a cast"
I expected p (if the compiler allows me to use p without asterisk) to hold memory address of someIntVariable instead of it's "value";
What is happening here ?
In the declaration:
const int *p = &someIntVariable;
The asterisk is not the dereference operator. It simply states p is a pointer. That line has the same effect as
const int *p;
p = &someIntVariable;
Here you are declaring a pointer and assigning a value to the pointer in one step.
It is equivalent to the following code:
const int *p;
p = &someIntVariable;
Here the * is not used as a de-referencing operator. It is used in the context of pointer declaration.
The const int * is a datatype - i.e. pointer to a const int. p is the name of the variable. It is on the LHS.
When asterik is on the RHS it has a different meaning. It means dereference.
I belive you got the warning:initialization makes integer from pointer without a cast,
when you tried these way
int someIntVariable = 10;
const int p = &someIntVariable;
printf("%d", p);
What your trying to do is , Your assigning a address to a normal variable and your expecting it to work but that is not how the normal variables used thats why pointers came into act to do that job and your trying to replace a pointer with normal variable
I still did not find the real answer to it but Just check out these question that I asked I wonder what really the &a returns?

Resources