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.
Related
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
Is it legal to cast a pointer to an array of ints to an int pointer?
int arr[4];
int (*a)[4] = &arr;
int *p = (int*)a;
C 2018 6.3.2.3 7 says we can convert an int (*)[4] to an int *:
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined…
The alignment is necessarily correct since an array of int must have the alignment required for an int.
However, the only thing the C standard says about the value resulting from this conversion is:
… when converted back again, the result shall compare equal to the original pointer.
This means that an int * can temporarily hold the value of an int (*)[4]. If we execute:
int arr[4];
int (*x)[4] = &arr;
int *y = (int *) x;
int (*z)[4] = (int (*)[4]) y;
then we know x == z is true because the standard tells us that. But we do not know what y is. Because the standard permits different types of pointers to have different representations (use the bits that represent their values in different ways), it is possible that y has no useful meaning as an int *. The C standard does not say the converted pointer can be used to access objects.
Most C implementations either support this deliberately or as an artifact of how they are designed. However, in terms of what the C standard specifies, no guarantee is given.
If the original pointer's initialized to either NULL or a valid pointer to an int[4], then yes. Pointer casts must not violate alignment requirements lest you get UB. A cast such as what I've described won't violate such requirement ̶a̶n̶d̶ ̶f̶u̶r̶t̶h̶e̶r̶m̶o̶r̶e̶ ̶i̶t̶ ̶w̶i̶l̶l̶ ̶b̶e̶ ̶u̶s̶a̶b̶l̶e̶ ̶f̶o̶r̶ ̶d̶e̶r̶e̶f̶e̶r̶e̶n̶c̶i̶n̶g̶ ̶b̶e̶c̶a̶u̶s̶e̶ ̶i̶f̶ ̶t̶h̶e̶ ̶̶i̶n̶t̶(̶*̶a̶)̶[̶4̶]̶̶ ̶i̶s̶ ̶v̶a̶l̶i̶d̶ ̶a̶n̶d̶ ̶n̶o̶n̶n̶u̶l̶l̶ ̶t̶h̶e̶n̶ ̶t̶h̶e̶r̶e̶ ̶i̶n̶d̶e̶e̶d̶ ̶i̶s̶ ̶a̶n̶ ̶̶i̶n̶t̶̶ ̶a̶t̶ ̶̶(̶i̶n̶t̶*̶)̶a̶̶.
If you feel uneasy about pointer casts (as you should), you can effect the conversion in this case without casting by simply doing *a (will get int[4] which will decay to int*) or a[0] or &a[0][0] or &(*a)[0]. That way, you can also dereference the result while adhering to the letter of the standard.
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;
int num = 45,*ptr1,*ptr2;
ptr1=#
ptr2=&ptr1;
printf("%d\n",*ptr1);
I've been thinking about this question for a while, but couldn't find a way to understand it,why &ptr1 can not be assigned to ptr2 in line 3, &ptr1 is a pointer's address,this address is no different from other address like an address of an integer, say
int a=1;
ptr2=&a;
Which means that I can assign an integer's address to a pointer,but not a pointer's address to a pointer,what differences between these two "address" could possibly make them different? Address of common variables can be assigned to single pointer,but address of pointers can not be assigned to single pointer?
I know the right way to do it is use double pointer to declare ptr2,but why single pointer can't?
Simply put, pointers are not addresses, they are varibles representing an address with a type. So the types have be compatible for pointers to assign (with the exception of void * generic pointer).
ptr2 = &ptr1;
ptr1 has a type of int *, so &ptr1 has a type of int **, it's not the same with ptr2, which has a type of int *.
Reference: C99 6.5.16.1 Simple assignment
both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right.
Yes you can assign a pointer's address to a pointer, but it must be a pointer to a pointer variable.
int **ptr3;
ptr3 = &ptr1;
The reason you can't assign it the way you were trying is that a pointer to an int is not the same as an int. Pointers must be pointing to the same type to be compatible. If you really know what you're doing you can explicitly cast it, but that's a path to danger.
Your code is wrong. This expression:
ptr2 = &ptr1;
Attempts to make an int * out of an int ** without a cast. The C standard forbids such conversions without an explicit cast.
The reason it's not allowed is that pointer types aren't guaranteed by the standard to all be the same size - so the pointer to your pointer might not fit in the variable you declared to be a pointer to an int.
Since pointers to any type can be converted to and from void * implicitly, you could write (correct, but probably confusing) analogous code to that in your question:
int num = 45;
void *ptr1, *ptr2;
ptr1 = #
ptr2 = &ptr1;
But doing so will require you to carry around all of the type information in some other way:
printf("%d\n",*(int *)ptr1);
printf("%d\n",*(int **)ptr2);
The short answer is that type matters; a pointer to int is a different, incompatible type from pointer to pointer to int. As others have mentioned, different pointer types may have different sizes and representations.
A pointer value is not just an address; it has additional type semantics. For example, the expression ptr++ will advance the pointer to the address of the next object of the base type. If the base type is char, then the pointer is advanced 1 byte. If the base type is int, the pointer is advanced sizeof (int) bytes.
Simply put because it will confuse the compiler. The compiler can work only according to the language standard. It doesn't have a brain of its own.
The language standard tells the compiler that if there is a int *
go to the address stored in that variable and use it.
In case there is a int ** then it tells it
go to the address in that variable. You aren't done yet as that is also an address. Go there and use what is present there.
This goes on and on for int *** and so on.
Hope this helps you to get over this basic confusion.
If you could assign any address to any pointer regardless of type, on the grounds that one address is just like any other address, consider the trouble you could get yourself into if the following became legal:
int n = 40;
int * p = &n;
int ** pp = &n; /* Typeless address assignment as you would like */
printf("%d\n", **pp); /* Bad Things happen here */
or the other way round:
int n = 40;
int * p = &n;
int * p2 = &p; /* More typeless address assignment */
printf("%d\n", *p2); /* Definitely not what you want */
Even if one address was the same as any other, sensibly dereferencing a pointer would become somewhat troublesome if things worked the way you suggest.
The reason you can't do what you suggest is that the type information you'd lose under your proposal is needed for dereferencing to work. If all you wanted pointers to do was to store and retrieve addresses, you'd have a point, but they're not just used for this. If they were, we could just have void pointers and be done with it.
I completely agree to your statement that when pointer variable always would store a value that is integer, as the address to any variable/array would be an integer.
But still the data-type that is used to declare the pointer is the one of whose address it would be storing.
There are 3 points:
1. The bits that are used while storing integer values differ from machine to machine.
i.e. 32-bit, 64-bit and further more complications may add-up.
2. Memory occupied i.e. bytes of data stored in it. Reason is : somewhere even the pointer variable is stored in memory. Right?
3. There are certain operations associated with pointers like ++ or --.
Remember, pointer type is dependent on the type of variable it points to.
This is the reason/need for the pointer to pointer.
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.