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

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

Related

Pointers in C: why is the * needed in *address_of_x = &x when getting the address of x?

Suppose we have the following code, which takes x, stores the value 4 in it, then stores the address of x in a pointer variable:
int x = 4;
int *address_of_x = &x;
What is the purpose of the * in int *address_of_x?
I understand * to be used for dereferencing a pointer - it takes an address and tells you what's stored there. But if an address is being stored, then what are we dereferencing? Or are we not dereferencing anything at all? Why isn't it written as:
int address_of_x = &x;
* in int *address_of_x = &x; is not de-referencing #Eugene Sh.
It is part of the type declaration: pointer to int.
int x = 4;
int *address_of_x = &x;
same as
int x = 4; // declare x as int
int *address_of_x; // declare address_of_x as pointer to int
address_of_x = &x; // Assign the address of x to address_of_x
Why isn't it written as: int address_of_x = &x;
&x is not an int. &x is an int *, a pointer (or address). A pointer is not an integer.
In an expression, the * is the dereference operator. In a declaration (which you have here), it's part of the syntax of a pointer declarator. You're declaring address_of_x to be a pointer to int rather than just an int.
The idea that was behind this syntax is that declarations and usage of identifiers should look similar (you typically use a pointer by dereferencing it) for convenience.
Also note that the * is needed for every identifier declared as a pointer, even if you declare multiple identifiers in a single declaration, like this:
int *a, *b;
If you write
int *a, b;
instead, b would not be a pointer. In general, it's best practice to avoid declaring more than one identifier per declaration, though.
int *address_of_x = &x; isn't an assignment. int *address_of_x = &x; is a declaration (int *address_of_x) with initialization (= &x) (note that in pre-historic C, initializations (as opposed to assignments) were done without the =, which made them even more distinct from assignments).
Declarations in C mirror usage. int *address_of_x declares that *address_of_x is of type int, ergo address_of_x is of type pointer to int. The = &x part then initializes this pointer to int to &x (address of x).
That's the definition of a pointer, the type for address_of_x variable is int *, a pointer to int. There's no "dereference" happening there.
Why isn't it written as:
int address_of_x = &x;
Well, two things
C is a strongly typed language.
the variable names do not carry any connection with their type
Simple answer: The asterisk in a variable declaration or definition statement is NOT a dereference operator. Instead it's a modifier.
In the given context, an asterisk means "Define the mext identifier as a pointer to the base type".
You surely won't ask why [10] doesn't mean "take the 10th element of the array" in int a[10]. Well, so-so. The brackets here also aren't the bracket operator, for exactly the same reason.
Why isn't it written as:
int address_of_x = &x;
The compiler never tries to interpret the literal meaning of identifiers. It only looks for modifiers when determining the type of an iddentifier in a declaration statement.
i.e., this code will not work as what it looks like:
int *not_a_pointer, not_an_array[10];
float a_character;
int *address_of_x = &x; declares a variable of type "pointer to int" (int *address_of_x) and then initializes it with the address of x (= &x).
So this * is not the dereferencing but is part of the declaration.
These two snippets are functionally the same:
int *address_of_x = &x;
and
int *address_of_x;
address_of_x = &x;
In the first case you defined and initialised the pointer all in one statement, but it can look like the wrong syntax. In the second example the definition and the value assignment are separate statements, and the code is clearer.
There is no dereferencing (yet).

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.

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

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;

C pointer to pointer

Does
int **p
and
int *p[1]
mean the same thing? as both can be passed to functions allowing the change the pointer object, also both can be accessed via p[0], *p ?
Update, thanks for your help, tough Memory management seems different. does the access mechanism remain the same
*eg: p[0] becomes *(p+0) & *p (both pointing to something)
Thanks
Not quite.
int **p;
declares a pointer p, which will be used to point at objects of type int *, ie, pointers to int. It doesn't allocate any storage, or point p at anything in particular yet.
int *p[1];
declares an array p of one pointer to int: p's type can decay to int ** when it's passed around, but unlike the first statement, p here has an initial value and some storage is set aside.
Re. the edited question on access syntax: yes, *p == p[0] == *(p+0) for all pointers and arrays.
Re. the comment asking about sizeof: it deals properly with arrays where it can see the declaration, so it gives the total storage size.
void foo()
{
int **ptr;
int *array[10];
sizeof(ptr); // just the size of the pointer
sizeof(array); // 10 * sizeof(int *)
// popular idiom for getting count of elements in array:
sizeof(array)/sizeof(array[0]);
}
// this would always discard the array size,
// because the argument always decays to a pointer
size_t my_sizeof(int *p) { return sizeof(p); }
To simplify things, you could factor out one level of pointers since it's not relevant to the question.
The question then becomes: what's the difference between T* t and T t[1], where T is some type.
There are several differences, but the most obvious one has to do with memory management: the latter allocates memory for a single value of type T, whereas the the former does not (but it does allocate memory for the pointer).
They are not the same thing, although in many cases they can appear to behave the same way.
To make the discussion below flow better, I'm going to take the liberty of renaming your variables:
int **pp; // pointer to pointer
int *ap[1]; // array of pointer
If an expression of type "N-element array of T" appears in most contexts, it will be converted to an expression of type "pointer to T" whose value is the address of the first element in the array (the exceptions to this rule are when the array expression is an operand of either the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration).
So, suppose you write something like
foo(ap);
The expression ap has type "1-element array of pointer to int", but by the rule above it will be converted to an expression of type "pointer to pointer to int"; thus, the function foo will receive an argument of type int **, not int *[1].
On the other side of the equation, subscripting is defined in terms of pointer arithmetic: E1[E2] is defined as *(E1 + E2) where one of the expressions is a pointer value and the other is an integral value. Thus you can use a subscript operator on pp as though it were an array. This is why we can treat dynamically-allocated buffers as though they were regular arrays:
pp = malloc(sizeof *pp * N); // allocate N pointers to int (type of *pp == int *)
if (pp)
{
size_t i;
for (i = 0; i < N; i++)
pp[i] = ...; // set pp[i] to point to some int value
}
Now for some major differences. First of all, array expressions may not be the target of an assignment; for example, you can't write something like
ap = some_new_pointer_value();
As mentioned above, array expressions will not be converted to pointer types if they are the operands of either the sizeof or unary & operators. Thus, sizeof ap tells you the number of bytes required to store a 1-element array of type int *, not a pointer to a pointer to int. Similarly, the expression &ap has type int *(*)[1] (pointer to 1-element array of pointer to int), rather than int *** (which would be the case for &pp).
No, they are not the same.
int **p is a pointer to a pointer to int.
int *p[1] is an array (of length 1) of pointers to int.
They are not same:
int **p
Is a pointer which points to another pointer whose type is int *
while,
int *p[1];
Is an array of size 1 to the type int *
They are different.
int **p
means a pointer to a pointer to an int.
int *p[1]
means an array containing one element, with that element being a pointer to an int.
The second form can be treated the same as the first in some situations, e.g. by passing it to a function.

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