Different ways to assign pointer in C , using & or *? - c

In C , if i want a pointer reference to a variable
int c = 12 ;
int *p ;
p = &c ;
or i can do it this way
int c = 12;
int p;
p=&c;
in both case value of p is the address of c , can you please tell the problems i will be facing .

You cannot do it this way:
int c = 12;
int p;
p = &c;
This is not valid C to assign a pointer value to an integer object. Enable all your compiler warnings, the compiler has to give a diagnostic message for the invalid assignment.

In the first case, there is no problem as p is a special type of variable which can contain address. Thus here p is called a pointer variable.
In second case, p is normal scalar variable which cannot contain address. So there is a problem. Compiler implicitly will not be able to assign the address of c variable to the variable p

& and * mean different things in different contexts.
& in a variable declaration (including in a function parameter) means "reference" or "by reference" in C++, and is not allowed in C. In C++, the type of j below is "int". It doesn't modify the type, but says "this is another name for existing data" rather than "create a space for new data".
int i = 5;
int &j = i; //C++ only: j is another name for i
int f(int & x); //f is a function that takes in an int by reference
* in a variable declaration means "pointer". The type of int* is "pointer to an int", while, again, the type of int& (C++ only) is int. It modifies the type.
int *p = NULL; //p is a pointer to an int, that currently points to nothing.
int f(int & x); //f is a function that takes in an int by reference
& in front of an existing variable means "a pointer to", or "address of". It's an operator, which can be thought of as a special kind of function. It takes in anything and returns a pointer to that thing.
int i = 5;
int *p = &i; //p points to i
int **pp = &p; //pp points to p
* in front of an existing variable means "what this is pointing to", also known as the dereference operator. Like &, it's an operator. It can only be applied to a pointer, and it returns what the pointer is pointing to.
int i = 5;
int *p = &i; //p points to i
int j = *p; //j copies what p is pointing to
So if I say *&var, that is the same as var, because it means "dereference the pointer to var".

int c = 12; int p; p=&c;
introduces the risk of losing bits from the address of c.
If you really need to store an address as integer then use uintptr_t as target integer type, as it's guaranteed by the C standard to be wide enough to store an address:
int c = 12; uintptr_t p; p = (void*)&c;
uintptr_t comes in <stdint.h>.
7.18.1.4 Integer types capable of holding object pointers
1
The following type designates a signed integer type with the property that any valid
pointer to void can be converted to this type, then converted back to pointer to void,
and the result will compare equal to the original pointer:
intptr_t
The following type designates an unsigned integer type with the property that any valid
pointer to void can be converted to this type, then converted back to pointer to void,
and the result will compare equal to the original pointer:
uintptr_t
These types are optional.
However to have this integer converted back to a pointer to an integer it casting needs to go via (void*):
int * pi = (void*)p;

Related

How can I distinguish a pointer from a dereference in C?

int value =5;
void testPointer( int* pa, int* pb) {
*pa = *pb +5;
*pb = value;
value += 10;
}
How can I distingush both from each other? I dont get it
A unary * always indicates a dereference.
This may feel familiar and intuitive in an expression: *pb + 5 means to get the value pb points to and add five. In contrast, you may find a declaration less intuitive; what does * mean in int *pa?
The way to think of this is that a declaration gives a picture of how something will be used. The declaration int *pb says *pb will be used as an int. In other words, when we get the value pb points to, it is an int. The * in a declaration represents the same thing that happens in an expression: dereferencing the pointer.
Kernighan and Ritchie tell us this in The C Programming Language, 1978, page 90:
The declaration of the pointer px is new.
int *px;
is intended as a mnemonic; it says the combination *px is an int, that is, if px occurs in the context *px, it is equivalent to a variable of the type int. In effect, the syntax of the declaration for a variable mimics the syntax of expressions in which the variable might appear.
As a more involved example, consider int (*p)[];. This tells us that (*p)[] is an int. Since [] is used to access array elements, this means (*p) must be an array of int. And that means p must be a pointer to an array of of int. Just like *, [] does not have a reversed meaning in declarations. It does not mean “is an array of” instead of “access an element of”; it is still an image of how the thing will be used in an expression.
When specifying a type, for example inside a declaration, the * means "pointer". Otherwise, the * means "dereference" or "multiplication" (depending on the context).
For example, when initializing a variable inside a declaration, all * before the = means "pointer", and all * after the = means "dereference" or "multiplication":
int i = 80;
int *p = &i; // In this case, * means "pointer"
int j = *p; // In this case, * means "dereference", so j gets the value 80

I thought that i can print value of variable by using its actual address . but i can't instead address is being printed

int num,address ;
address = &num ;
num = 2029 ;
printf("\n%d",address) ;
It is printing the address of num but address of num is being printed.
Is it possible to print value of variable by accessing its address not by name like we do in the scanf() function?
To output a variable value using the variable address you should write for example
int num = 2029;
int *address = &num;
printf( "\n%d",*address) ;
That is you need a pointer that will store the address of the variable and to get access to the variable itself you need to dereference the pointer.
Or if you want to use integer types then you can do the following
#include <stdio.h>
#include <stdint.h>
int main( void )
{
int num = 2029;
uintptr_t address = ( uintptr_t )( void * )&num;
printf( "num = %d\n", *( int * )( void * )address );
}
From the C Standard (7.20.1.4 Integer types capable of holding object pointers)
The following type designates an unsigned integer type with the
property that any valid pointer to void can be converted to this type,
then converted back to pointer to void, and the result will compare
equal to the original pointer:
uintptr_t
The same is valid for the type intptr_t.
You need to use a pointer:
int num, *address; // declares address as a *pointer* to int
address = &num; // assigns the address of num to address variable
num = 2029;
printf( "%d\n", *address ); // we *dereference* the address variable
// to access the contents of num
A pointer is any expression whose value is the location of an object or function in a running program's execution environment (i.e., an address). A pointer variable can be used to store the address of another object or function.
A simple pointer variable is declared as
T *ptr; // for any type T
The type of the variable ptr is "pointer to T", or T *, which is specified by the combination of the type specification T and the declarator *ptr. The "pointer-ness" of the variable is specified by the presence of the * operator in the declarator.
Because whitespace isn't significant in this case, you can declare that pointer as any of1
T *ptr;
T* ptr;
T*ptr;
T * ptr;
but it will always be parsed as
T (*ptr);
In the code above we declare address as a pointer to int:
int num, *address;
The "int-ness" of address is provided by the type specifier int and the "pointer-ness" of address is provided by the declarator *address.
The unary & operator is used to obtain a pointer value - in the statement
address = &num;
the expression &num yields a pointer to the variable num. The type of the expression &num is int * (pointer to int). The type of the variable address is also int *.
address == &num // int * == int *
To access the value stored in num from address, we dereference address using the unary * operator:
printf( "%d\n", *address );
The expression *address has type int, and acts as a kinda-sorta alias for the variable num:
*address == num // int == int
Pointer types and declarations can get arbitrarily complex:
T *aptr[N]; // aptr is an array of pointers to T
T (*ptra)[N]; // ptra is a pointer to an array of T
T *fptr(); // fptr is a function returning a pointer to T
T (*ptrf)(); // ptrf is a pointer to a function returning T
T *(*(*p[N])())[M] // p is an array of pointers to functions returning
// pointers to M-element arrays of pointers to T
In both declarations and expressions, the unary * operator has lower precedence than the postfix [] and () operators, so *a[i] will be parsed as *(a[i]) and *f() will be parsed as *(f()) (we're dereferencing the results of a[i] and f()).
C++ programmers tend to use the convention T* ptr;, because they want to emphasize that ptr has pointer type. However, it is always interpreted by the compiler as T (*ptr);.
I will spare you my usual rant on the practice.

a = &b vs *a = &b — pointer assignment

I have a pointer and a variable:
int *a;
int b;
Is there any difference between assignments
a = &b;
and
*a = &b;
and what are they called (like pointer declaration or something) ?
Types matter.
In case of a=&b, the assignment is valid. You're assigning the address of an integer (type: int *), to another variable of type int *, so this is legit.
In case of *a=&b, this is a constraint violation (for assignement operator, see chapter §6.5.16.1/p1, Constraints, for Simple assignment) and thus not a valid C syntax, thus not required to be compiled by any conforming compiler. To make it a valid C syntax, we need to enforce a typecast, something like
*a= (int) &b;
would make it a syntactically valid C statement which meets the required constraint.
Even, after that, the result is implementation defined.#note Here, you're basically trying to assign the the address of an integer (type: int *) to another variable of type int (*a is of type int). Conversion from a pointer to integer is implementation defined behaviour.
Quoting C11, chapter §6.3.2.3, Pointers
Any pointer type may be converted to an integer type. Except as previously specified, the
result is implementation-defined. If the result cannot be represented in the integer type,
the behavior is undefined. [....]
[....] And what are they called?
They both are assignment statements.
Note:
Considering a points to a valid memory location already. Otherewise, dererefencing an invalid pointer invokes undefined behavior on it's own.
Pay attention to types on the left and on the right of =.
&b is int *, a is also int * but *a is int.
It's a bit confusing that * has different meanings:
int *a; — here * means that a will be a pointer;
*a = ...; — here * means that we change not address stored in a but value which is located at the address.
So a = &b means "write the address of b to a",
but *a = &b means "write the address of b to *a, i.e. to the address which is stored in a".
Let's suggest that we have this situation:
Address Value
a 0x0001 0x0004
b 0x0002 70
0x0003 80
0x0004 90
At the moment a is 0x0004 and *a is 90.
If you do a = &b, a will be 0x0002 and *a will be 70.
But if you do *a = &b, a will not change, but *a, i.e. value at the address 0x0004, will change to 0x0002.
Given the types, the following assignments would be valid:
a = &b; // int * = int *
*a = b; // int = int
In the second case, a must point to a valid memory location or the behavior is undefined.
*a = &b; // int = int *
is a constraint violation and the compiler will yell at you.
Is there any difference between assignments
a = &b;
and
*a = &b;
Yes. In first case, a and &b (address of b) both are of type int *. They are assignable.
In case of *a = &b, *a is of type int while &b is of type int *. Bothe types are incompatible and type of &b is not converted explicitly to the type of *a. This is a constraint violation. That being said: int types are not capable of holding pointer objects. The only integer types that are capable of holding pointer object are intptr_t and uintptr_t.
7.20.1.4 Integer types capable of holding object pointers
1 The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:
intptr_t
The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:
uintptr_t
These types are optional.
and what are they called (like pointer declaration or something) ?
They are assignment statements.
One notable difference is that second assignment is ill-formed C (because of constraint violation):
*a = &b;
error: assignment makes integer from pointer without a cast
[-Wint-conversion]
C11 §6.5.4/3, Cast operators:
Conversions that involve pointers, other than where permitted by the
constraints of 6.5.16.1, shall be specified by means of an explicit
cast.
The requirement of explicit cast was introduced in C89, in order to to disallow bad practice of implicit conversion between integer and pointer types.
The only exception to this rule is that you can assign pointer value with 0 integer constant, which represents null pointer constant:
a = 0; // more idiomatically: a = NULL;
Like all the other answers have already pointed out, given the variables int *a and int b:
the assignment a = &b is valid (and assigns the address of b to the pointer a, so that *a can be used to access b), whereas
the assignment *a = &b is a constraint violation, since it tries to assign the address of b to the integer pointed to by a, which is not allowed without an explicit cast.
What might be confusing you, however, is that the variable declaration:
int b;
int *a = &b;
is valid, and does exactly the same thing as:
int b;
int *a;
a = &b; // not *a = &b!
That's a very convenient shorthand, since you nearly always want to initialize a variable as soon as you declare it (if only to make sure that you don't accidentally try to use it before it's initialized). But it can be confusing when you first encounter that syntax, since it looks as if you're assigning &b to *a, when it's actually a itself that is getting initialized with the value &b. This is just something that you'll have to learn: variable initialization is not the same as normal assignment, even though it looks confusingly similar.
The first, int a = &b; copies the address of the variable "b" to the
"a".
The second, int *a = &b; copies the address of the variable "b" to the
location "a" points to.
First one is ok but second one invokes UB. ( Unless a is pointing to some valid memory)
Sure there are differents between them
& represent pointer(from pointer you can get value)
* represent value
a=&b (represent a equal point of b)
*a=&b(represent value a equal point of b)
Helped Tutorial
First let me clear you the difference between integer variable and pointer variable:
(1) Integer variable ( e.g: int b, in this case ) is used to store the value of an integer ( of length 4 bytes ). The value of 'b' gets stored in some memory location ( say 0x00000001 ).
(2) Pointer variable (e.g: int * a, in this case) is used to store the memory location of an integer variable. That is, in 'a' we can store the address of an integer variable. The value pointed by a pointer variable can be dereferenced by using ' * ' operator. So 'a' will have the address and ' *a ' will have the value pointed by the value (address) contained in a.
Now answering to your question:
Let's assume that b = 4 and address of b ( &b ) is 0x00000001 ( hexadecimal notation ).
In first type assignment a = &b, the address of variable integer b gets stored in a ( since a is a pointer variable ). Now 'a' has the value 0x00000001 and ' *a ' will have 4.
In second type assignment *a = &b, the address of variable b gets stored in the memory location pointed by a, i.e, in 0x00000001 memory location will have the value 0x00000001 itself. Now 'a' has the value 0x00000001 and ' *a ' will also have the same value 0x00000001.
int *a;
int b;
Is there any difference between assignments `a = &b` and `*a = &b`.
Any variable var of type T has some location in memory, whose adress is either allocated by the compiler or by the static or dynamic linkers. The adress of some variables can be obtained by &var and has the type pointer to T. So, when you apply the & operator you nest the type inside another pointer. a=&b is correct.
On the other hand, *a=&b is not correct. You try to store in the variable *a (that has type int) a pointer to the base address of the variable b (that has type pointer to int). In the architectures where the pointer has 64 bits and int has 32 bits this will lead to failure. On the other hand, on the architectures where pointer and int have the same length, this is possible if you insert a cast. The compiler will not automatically insert a coercion from int* to int.

What is meant by void *p = &i ?

In below code, how can void pointer p store address of i? What is the meaning of "*(float *)p" inside printf() ?
#include
void main()
{
int i = 10;
void *p = &i;
printf("%f\n", *(float *)p);
}
A void* can store any address. It's a "generalized pointer" basically. You can cast back the void* to the type you saved into it to get a useful type out of it and do things with it like pointer arithmetic or dereferencing the pointer. The pointer itself doesn't know anything about what type it stores and thus you have to tell it what type it's pointing to so. It's lack of type makes it dangerous since it's the programmer's job to remember what type the pointer points to.
In your case, you make p point to the address of i which is an int and then you try to print out the pointee of p as a float while you didn't assign it to the address of a float in the first place. This is undefined behaviour and a good example of the dangers of a void* in inexperienced hands.
In C void* can point to any type of memory location. You can assign void* to a variable of type int*, double*, char*.., etc. Generally void* is used to pass parameters to the function who type is not know at the time of defining.
But You can have any variable of type void. So at the time of dereferencing you have to cast a void* to some pointer type but not void*.
so by *(float *)p (which is undefined) you are casting p(which is void* type) to float* type, then you are dereferencing it to double(But memory is actually int). So that it expects float type variable at the memory it is pointing to.
how can void pointer p store address of i?
A void pointer can point to any data pointer. See C11 draft, 6.3.2.3. So,
void *p = &i;
simply makes p point to the address of object i.
You can later safely convert it back to an int*. For example,
int i = 10;
void *p = &i;
int *j = p; /* j now point to &i */
or you can directly cast p and use it:
printf("%d\n", *((int*) p));
This is all fine.
What is the meaning of "*(float *)p" inside printf() ?
It's an attempt to reinterpret an int object as a float object which isn't allowed. In this statement:
printf("%f\n", *(float *)p);
You are casting p, a void*, to a float* which may be undefined because the object p points to is an int and you are attempting to
reinterpret it as if it's a float object. From C11 draft, 6.3.2.3:
A pointer to an object type may be converted to a pointer to a
different object type. If the resulting pointer is not correctly
aligned68) for the referenced type, the behavior is undefined.
Otherwise, when converted back again, the result shall compare equal
to the original pointer. When a pointer to an object is converted to a
pointer to a character type, the result points to the lowest addressed
byte of the object. Successive increments of the result, up to the
size of the object, yield pointers to the remaining bytes of the
object.
This also violates C11 draft, 6.5.7 as int* and float* are distinct types and are not compatible with each other.

How to understand the pointer star * in C?

I'm struggling with the pointer sign *, I find it very confusing in how it's used in both declarations and expressions.
For example:
int *i; // i is a pointer to an int
But what is the logic behind the syntax? What does the * just before the i mean? Let's take the following example. Please correct me where I'm wrong:
char **s;
char *(*s); // added parentheses to highlight precedence
And this is where I lose track. The *s between the parantheses means: s is a pointer? But a pointer to what? And what does the * outside the parentheses mean: a pointer to what s is pointing?
So the meaning of this is: The pointer pointing to what s is pointing is a pointer to a char?
I'm at a loss. Is the * sign interpreted differently in declarations and expressions? If so, how is it interpreted differently? Where am I going wrong?
Take it this way:
int *i means the value to which i points is an integer.
char **p means that p is a pointer which is itself a pointer to a char.
int i; //i is an int.
int *i; //i is a pointer to an int
int **i;//i is a pointer to a pointer to an int.
Is the * sign interpreted differently in declarations and expressions?
Yes. They're completely different. in a declaration * is used to declare pointers. In an expression unary * is used to dereference a pointer (or as the binary multiplication operator)
Some examples:
int i = 10; //i is an int, it has allocated storage to store an int.
int *k; // k is an uninitialized pointer to an int.
//It does not store an int, but a pointer to one.
k = &i; // make k point to i. We take the address of i and store it in k
int j = *k; //here we dereference the k pointer to get at the int value it points
//to. As it points to i, *k will get the value 10 and store it in j
The rule of declaration in c is, you declare it the way you use it.
char *p means you need *p to get the char,
char **p means you need **p to get the char.
Declarations in C are expression-centric, meaning that the form of the declaration should match the form of the expression in executable code.
For example, suppose we have a pointer to an integer named p. We want to access the integer value pointed to by p, so we dereference the pointer, like so:
x = *p;
The type of the expression *p is int; therefore, the declaration of p takes the form
int *p;
In this declaration, int is the type specifier, and *p is the declarator. The declarator introduces the name of the object being declared (p), along with additional type information not provided by the type specifier. In this case, the additional type information is that p is a pointer type. The declaration can be read as either "p is of type pointer to int" or "p is a pointer to type int". I prefer to use the second form, others prefer the first.
It's an accident of C and C++ syntax that you can write that declaration as either int *p; or int* p;. In both cases, it's parsed as int (*p); -- in other words, the * is always associated with the variable name, not the type specifier.
Now suppose we have an array of pointers to int, and we want to access the value pointed to by the i'th element of the array. We subscript into the array and dereference the result, like so:
x = *ap[i]; // parsed as *(ap[i]), since subscript has higher precedence
// than dereference.
Again, the type of the expression *ap[i] is int, so the declaration of ap is
int *ap[N];
where the declarator *ap[N] signifies that ap is an array of pointers to int.
And just to drive the point home, now suppose we have a pointer to a pointer to int and want to access that value. Again, we deference the pointer, then we dereference that result to get at the integer value:
x = **pp; // *pp deferences pp, then **pp dereferences the result of *pp
Since the type of the expression **pp is int, the declaration is
int **pp;
The declarator **pp indicates that pp is a pointer to another pointer to an int.
Double indirection shows up a lot, typically when you want to modify a pointer value you're passing to a function, such as:
void openAndInit(FILE **p)
{
*p = fopen("AFile.txt", "r");
// do other stuff
}
int main(void)
{
FILE *f = NULL;
...
openAndInit(&f);
...
}
In this case, we want the function to update the value of f; in order to do that, we must pass a pointer to f. Since f is already a pointer type (FILE *), that means we are passing a pointer to a FILE *, hence the declaration of p as FILE **p. Remember that the expression *p in openAndInit refers to the same object that the expression f in main does.
In both declarations and expressions, both [] and () have higher precedence than unary *. For example, *ap[i] is interpreted as *(ap[i]); the expression ap[i] is a pointer type, and the * dereferences that pointer. Thus ap is an array of pointers. If you want to declare a pointer to an array, you must explicitly group the * with the array name, like so:
int (*pa)[N]; // pa is a pointer to an N-element array of int
and when you want to access a value in the array, you must deference pa before applying the subscript:
x = (*pa)[i];
Similarly with functions:
int *f(); // f is a function that returns a pointer to int
...
x = *f(); // we must dereference the result of f() to get the int value
int (*f)(); // f is a pointer to a function that returns an int
...
x = (*f)(); // we must dereference f and execute the result to get the int value
My favorite method to parse complicated declarators is the clockwise-spiral rule.
Basically you start from the identifier and follow a clockwise spiral. See the link to learn exactly how it's used.
Two things the article doesn't mention:
1- You should separate the type specifier (int, char, etc.) from the declarator, parse the declarator and then add the type specifier.
2- If you encounter square brackets which denote an array, make sure you read the following square brackets (if there are any) as well.
int * i means i is a pointer to int (read backwards, read * as pointer).
char **p and char *(*p) both mean a pointer to a pointer to char.
Here's some other examples
int* a[3] // a is an array of 3 pointers to int
int (*a)[3] //a is a pointer to an array of 3 ints
You have the answer in your questions.
Indeed a double star is used to indicate pointer to pointer.
The * in declaration means that the variable is a pointer to some other variable / constant. meaning it can hold the address of variable of the type. for example: char *c; means that c can hold the address to some char, while int *b means b can hold the address of some int, the type of the reference is important, since in pointers arithmetic, pointer + 1 is actually pointer + (1 * sizeof(*pointer)).
The * in expression means "the value stored in the address" so if c is a pointer to some char, then *c is the specific char.
char *(*s); meaning that s is a pointer to a pointer to char, so s doesn't hold the address of a char, but the address of variable that hold the address of a char.
here is a bit of information
variable pointer
declaring &a p
reading/ a *p
processing
Declaring &a means it points to *i. After all it is a pointer to *int. An integer is to point *i. But if consider j = *k is the pointer to the pointer this, means &k will be the value of k and k will have pointer to *int.

Resources