What is the difference between `*a =` and `= *a`? - c

In following function,
void swap(int * a, int * b) {
int t;
t = *a; // = *a
*a = *b; // a* =
*b = t;
}
What is the difference between = *a and *a =?
I've heard that the * operator in = *a is a de-referencing(or in-directing) operator which fetches(?) that value from the pointer.
Then, what is the actual meaning of *a =?
Yesterday, the day I asked this question, I explained about pointers to my colleague whose major field has nothing to do with pointers.
I quickly typed a source code like this.
#include <stdio.h>
void swap1(int a , int b) {
int t = a;
a = b;
b = t;
}
void swap2(int * a, int * b) {
int t = *a;
*a = *b;
*b = t;
}
int main(int argc, char * argv[]) {
int a = 10;
int b = 20;
swap1(a, b);
swap2(&a, &b);
}
I was even proud of myself for remembering things imprinted on my brain in 1996. (I've been with Java for almost 20 years.)
I used a bunch of printfs with %ds and %ps to show her what was happening.
Then I made a terrible mistake. I declared.
포인터 변수 앞에 별을 붙이면 값을 가져온다는 뜻이에요.
When you attach a STAR in front of a pointer variable, that means you fetches(retrieves) the value.
Well that could be applied to following statement.
int t = *a;
Which simply can be said,
int t = 10;
The big problem I faced came from the second statement.
*a = *b; // 10 = 20?
The root evil is that I didn't try to explain about the dereference operator or I didn't ask to myself of being aware of the meaning of a 별(star).
Here is what people would say.
for = *a,
the actual value at the address denoted by a is assigned to the left side.
for *a =
the value of the right side is stored in the address denoted by a.
That's what I'm confusing of. And that's why I should re-think about the meaning of `de-referencing'.
Thanks for answers.
Oh I think this problem is going deeper to the concepts of lvalues and rvalues.

The first one is reading from the memory a is pointing to. The second one is writing to that memory.
This is no different from x = and = x except that you do not access the variable directly but the object it is pointing to.

Here:
t = *a;
the pointer a is dereferenced and this value is assigned to t whereas here:
*a = *b;
both b and a are dereferenced and the value of *b is stored in the address a.

I've heard that the * operator in = *a is a de-referencing(or in-directing) operator which fetches(?)
In fact fetch happens when you dereference a pointer with operator * alone. Hence assignment = operator doesn't involve in dereferencing perhaps assigning the dereferenced value to LHS.

a is a pointer here, pointing to an int.
*a retrieves the integer value stored at memory pointed to by a. When you say *a = <some value>, assuming <some value> to be an int, <some value> gets stored at memory location pointed to by a.
*a = *b ==> Here b is again an int pointer, so integer value pointed to by b is read and written to memory location pointed to by a.

It has no relation with '=' operator .It(* operator) just means value at 'a's address.So
t = *a; assigns value at address a to t
*a = *b; assigns b's value in place of value at address a
*b = t; assigns t to b's value

What is the difference between = *a and *a =?
Well... look at this code:
int x;
t = x;
x = t;
If you have any plain variable int x; then you can read from it and write to it. That's the difference between your two lines as well.
* is the "contents of" operator. If a is a pointer to int, then *a simply means that you can use the contents of that variable as if it had been a plain int variable. And just like any variable you can either read or write to it.

Related

Proper way to read 'int * ptr=&x'

The following code is easily interpreted as
int x=4;
int *ptr; // ptr is a pointer to an int
ptr=&x; // the address of x is assigned to the pointer ptr
But the following equivalent code, may read misleadingly like
int *ptr=&x; // the address of x is assigned to *ptr, which is an integer
that is it seems to be interpreted as assigning the address of x to the pointed value *ptr (int *ptr )= &x
The correct interpretation as the one when declaration and initialization are separated should be written something like int *(ptr = &x),to make evident that the assignment is to the pointer and not to the pointed location but this gives an error, why is that? And what is the best way to read and think of int *ptr=&x?
This is, admittedly a weird part of C and it's mostly due to C's evolution.
In C's syntax, declarations aim to mirror use, so that after int *x;, *x resolves to an int and *x=42 assigns to that int. But initializations, which are started with = after the specifiers declarator part of a declaration, are syntactically and semantically different from an assignments.
(Initialization can "assign" to static/filescope variables and such an assignment generates no code: it simply contributes to the makeup of the resulting binary. Assignments always generate code unless optimizations can delete it)
Initializations and assignments used to be very differently looking in prehistoric C, where you'd initialize without the = sign as in int x 42;. (Even after the = was added to the syntax of initializations, it was long impossible to initialize local, nonstatic, variables which meant situations such as int *p = &x; didn't arise all that often.)
The old syntax had problems (would int x (42); also declare and initialize x or would it be a function declaration?) and that's why it was replaced, but I like how it emphasized that initializations are different from assignments.
Unfortunately with the new syntax (as in int x, *p = &x;) this distinction is not all that apparent, and you simply have to remember that when you have type specifiers (int) at the left end, then the = does not denote an assignment where you can just look at *p = &x but rather that it's an initialization where you have to look at the whole declaration and see what's declared (x as an int and p as a pointer to int) . The = in that context then initializes the declared identifier.
int * is the type, so it makes perfect sense. It's just that pointer notation in C can take some effort to get used to. But look at this code
typedef int* int_ptr;
int x;
int_ptr ptr = &x;
Same thing. However, it's often advised to NOT typedef pointers.
The confusion comes from that * serves two roles. It is BOTH to name a type AND to dereference a pointer. An example of the first is sizeof(int*)
If you declare several pointers at once it looks messier, but it's still the same. In general, it's recommended to not declare more than one pointer at once. Because if we would like to do the above thing with two pointers, it would look like this:
int *pa = &x, *pb = &x;
That's the same as
int *pa = &x;
int *pb = &x;
And this does something completely different and will generate a warning because you're assigning the address of a variable to the pb variable that has type int
int *pa = &x, pb = &x;
However, using the typedef from above, you can (but probably shouldn't) do this:
int_ptr pa=&x, pb = &x;
But one way to think of it is that it makes no sense at all in any situation to dereference an uninitialized pointer.
And what is the best way to read and think of int *ptr=&x?
Take the fact that it does not make sense to dereference an uninitialized pointer. And you're doing an initialization of a pointer, and therefore you should initialize it with a (valid) address.
Ok, I see that, another thing. If the type is int* why is it almost always written like with the * next to the pointer variable instead, like int *ptr?, it would make more sense, even if it is the same to write it like int* ptr.
Because, then it would be MUCH easier to forget the asterisk if you declare several pointers at once. That would give the impression that int* p,q; declares two pointers.
C pointer syntax is clunky. It's a very old language. Just get used to it. It will never change. Just for fun, here is a page that can tell what a declaration is https://cdecl.org/ so try these:
int (*p)[3]
int *p[3]
const int *p[3]
int *const p[3]
const int (*p)[3]
int (*const p)[3]
You could write
int ( *ptr ) = &x;
or even like
int ( * ( ptr ) ) = &x;
Though this record
int *ptr = &x;
is clear for each C programmer because it is a declaration and not an assignment statement. Moreover in C opposite to C++ declarations are not statements.
That is 1) you may not enclose a declaration in parentheses as you wrote (int *ptr )= &x and 2) you may enclose a declarator in parentheses.
If to follow your logic then you should write the declaration like
int *p = ( p = &x );
that makes the declaration more confusing.:)
Here is a demonstrative program that shows some examples of declarations and initializations of a pointer.
#include <stdio.h>
int main(void)
{
int x = 10;
int *p1 = &x;
int ( *p2 ) = &x;
int ( *( p3 ) ) = &x;
int typedef *T;
T ( p4 ) = &x;
printf( "*p1 = %d\n", *p1 );
printf( "*p2 = %d\n", *p2 );
printf( "*p3 = %d\n", *p3 );
printf( "*p4 = %d\n", *p4 );
return 0;
}
The program output is
*p1 = 10
*p2 = 10
*p3 = 10
*p4 = 10
Pay attention to that in C as in many other languages some symbols are overloaded and their meanings depend on the context. For example the symbol & can denote the address of operator and the bitwise AND operator and by the way in C++ this symbol also can denote a reference.
Compare the following.
int n = 5; // (a) defines 'int' variable 'n' and initializes it to '5'
int *p; // (b) defines 'int*' pointer variable 'p`
p = &n; // initializes 'p' to '&n'
int *p1 = p; // (c) defines 'int*' pointer variable 'p1' and initializes it to 'p'
// syntactically, it looks just like (a), but for a pointer type
int *p2 = &n; // (d) same as (b) and (c) combined into a one-liner
int n3 = 7, *p3 = &n3; // (e) same as (a), (b) and (c) combined into a one-liner
when declare a pointer, int p is equal to int p; int* is a type.

Swapping two integers using pointers

I am trying to swap the value of two integers using pointers, see code below:
void swapArgs(int *a, int *b) {
int *temp = &b;
b = &a;
a = &temp;
printf("Swapped Arguments: A=%d, B=%d\n", *a, *b);
}
When the printf is executed, the resulting values are huge numbers. Can anyone explain to me what is wrong with my code? Still new to pointers.
The problem is that you need to copy the values, not the pointers:
int temp = *b;
*b = *a;
*a = temp;
Note: Your code is assigning pointers of wrong type - &a is int**, while b is int* (i.e. the number of asterisks does not match). Your compiler should have given you warnings about that. Fixing them would fix the problem.
Remember that your a and b are already pointers - so inside the function you must not use the & (address operator), instead you must use the * (dereference operator):
int temp = *b;
*b = *a;
*a = temp;

Why do these pointers cause a crash?

I'm a bit confused as to why the following code crashes:
int main(){
int *a;
int *b;
*a = -2;
*b = 5; //This line causes a crash on my system.
return 0;
}
Shouldn't memory automatically be allocated for two pointers and two integers before run-time because of the declarations?
Or must you always explicitly allocate memory?
No. You've only declared the pointers, not what they point to. The pointers are allocated on the stack, and since you've not initialized them to anything, their values are garbage.
int main() {
int a = 7;
int *p_a; // p_a contains whatever garbage was on the stack at its
// location when main() is called. (Effectively points nowhere).
p_a = &a; // p_a points to (gets the address of) variable a, also on
// the stack.
printf("Before: a = %d\n", a); // prints 7
*p_a = -2;
printf("After: a = %d\n", a); // prints -2
return 0;
}
I would code up the above example, and step through it in a debugger. You'll see what I mean about what p_a is pointing to.
Shouldn't memory automatically be allocated for two pointers and two integers before run-time because of the declarations?
I only see you specifying two pointers. Where are the two integers?
Or must you always explicitly allocate memory?
Pointers have to point to something. Either local variables on the stack, or malloc'd memory from the heap.
In this code:
int* a;
*a = -2;
a is an uninitialized pointer, dereferencing of which produces undefined behavior, that you were luckily able to observe as a crash of your application.
You need to initialize the pointer (make it point to the valid memory) before you dereference it (i.e. before you use *, the dereference operator):
int a;
int* pA = &a;
*pA = -2;
Consider
int m;
int n;
m = n;
This is invalid because you're trying to use n but you haven't assigned a value to it. Now:
int *a;
*a = -2;
Likewise, this is invalid because you're trying to use a but you haven't assigned a value to it. The value of a is not an int, it's a pointer to int. For example,
int someint;
a = &someint;
*a = -2;
puts -2 into someint. Without the assignment to a, the place to put -2 is undeterminable. Also,
a = malloc(sizeof(int));
*a = -2;
Here, a is given the value of the address of some location in the heap; -2 goes into that heap location.
Perhaps an analogy would be helpful:
Consider the phrase "her dog". This is a reference to someone's' dog, but it won't do to tell me "give her dog a bone" if you haven't told me who she is. Similarly, "pointer to an int" doesn't tell the system which int it is.
Your *a and *b pointers are not initializated properly.
Try this one:
int my_a;
int my_b;
int *a;
int *b;
a = &my_a; // init the pointer a to the direction of my_a int variable
b = &my_b;
*a = 3; // set the my_a value via pointer
*b = 2;
You have just declared pointers but you haven't initialized them. So, you can't be sure that *b = 5 is causing the program to crash. It could be *a = -2 as well. To fix it, you should initialize your pointers as well.
int aval = -2;
int bval = 5;
int *a = &aval; // declared and initialized pointers
int *b = &bval;
// Now you can change the value using the pointer
*a = 15;
*b = 20;

Why the type doesn't match in this value swap code in C?

void swap(char *a,char *b){
char t;
t = *a;
*a = *b;
*b = t;
}
int main(void){
char a = '1';
char b = '2';
swap(&a,&b);
printf("The value is %c and %c respectively\n",a,b);
return 0;
}
in the above code, there's a spot that confuse me
I think if a is a pointer, and *a is the value it points to
int *ptr, a = 1;
ptr = &a;
printf("The value of *ptr should be a: %d\n",*ptr);
printf("The value of *a should be an hex address: %p\n",ptr);
so in the swap(char *a, char *b) function,it takes the value not pointer( *a not a),
swap(&a, &b)
but it actually pass the pointer value to it as the parameter, and the code works. Anybody can explain it to me?(I think for swap(char *a){...} part, the declaration doesn't mean it require *a to pass in, it means declare a pointer value a, not the value a points to as *ain elsewhere means).
* is confusing because it means two different, but closely related, things. In a variable declaration, * means "pointer". In an expression, * means "dereference the pointer".
It's intended to be a helpful mnemonic: if you have char *a in your code it means that *a is a char.
Your function
swap(char *a, char *b)
takes two parameters, both of which are of type char *. Quite literally that means they point to a character somewhere in memory.
When you dereference the pointer
t = *a;
You are saying "grab whatever a is pointing to and put it in t.
Perhaps the confusion is from the fact that * means two related but different things. In the case char *, it's defining a type, specifically one that points to a character somewhere in memory. In the case *a, the * means "look at the character being pointed to by a and let me know what it is".
In main:
a is a char
&a is a pointer to the char a.
In swap:
a is a pointer to a char
*a is the char pointed to by a.
You passed a pointer to a pointer, and it worked beautifully. Try drawing a picture with boxes and errors. Clears things up every time. Just remember your code has two as and two bs.
Yes, the asterisk * has multiple meanings related to pointers:
It be used in a declaration to introduce a variable that contains an address - a pointer:
int *ptr = NULL;
Similarly in an argument list, such as void swap(char *, char *).
It can also be used to dereference an existing pointer, or get the value pointed to, as within the function swap:
t = *a;
This generally causes a good deal of confusion for students who are new to C, but it's actually quite simple.
In this our aim is to swap the value
when you write char a='1'; i.e you are putting '1' at address 662442(suppose &a=662442).
char b='2'; i.e you are putting '2' at address 662342(suppose &b=662342).
now consider swapping a and b,here our aim is to change value at 662442(&a) to value at 662342(&b) and value at 662342(&b) to value at 662442(&a).
now for swapping we take a temporary variable char temp and will do the following
temp=*a; i.e assigning value at address 662442(&a) to temp.
*a = *b; i.e assigning value at address 662342(&b) to value at address 662442(&a).
now we will put previous value of a (i.e value kept in variable temp) at address 662342(&b)
*b = temp; i.e assigning temp to address 662442(&a)

Simple swap function...why doesn't this one swap?

I'm new to C and still trying to grasp the concept of pointers. I know how to write a swap function that works...I'm more concerned as to why this particular one doesn't.
void swap(int* a, int* b)
{
int* temp = a;
a = b;
b = temp;
}
int main()
{
int x = 5, y = 10;
int *a = &x, *b = &y;
swap(a, b);
printf(“%d %d\n”), *a, *b);
}
You're missing *s in the swap function. Try:
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
That way, instead of just swapping the pointers, you're swapping the ints that the pointers are pointing to.
Your swap() function does work, after a fashion - it swaps the values of the variables a and b that are local to swap(). Unfortunately, those are distinct from the a and b in main() - so you don't actually see any effect from swapping them.
When thinking about pointers, you need to be clear on a few abstractions.
An object in memory. This can be of any type (and size). An integer object, for example, will occupy 4 bytes in memory (on 32 bit machines). A pointer object will occupy 4 bytes in memory (on 32 bit machines). As should be obvious, the integer object holds integer values; a pointer object holds addresses of other objects.
The C programming language lets symbols (variables) represent these objects in memory. When you declare,
int i;
the symbol (variable) i represents some integer object in memory. More specifically, it represents the value of this object. You can manipulate this value by using i in the program.
&i will give you the address of this object in memory.
A pointer object can hold the address of another object. You declare a pointer object by using the syntax,
int* ptr;
Just like other variables, the pointer variable represents the value of an object, a pointer object. This value just happens to be an address of some other object. You set the value of a pointer object like so,
ptr = &i;
Now, when you say ptr in the program, you are referring to its value, which is the address of i. But if you say *ptr, you are referring to not the value of ptr, but rather the value of the object whose address is in ptr i.e. i.
The problem with your swap function is that you are swapping values of pointers, not the values of objects that these pointers hold addresses for. To get to the values of objects, you would have to use *ptr.
C is a pass-by-value language. Your swap routine doesn't dereference the pointers passed to it, so from main's perspective nothing has happened.
The pointers are passed by value. This means a & b are still a and b when the come back from the function;
try something like this
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
The right way to do it:
void swap(int* a, int* b)
{
int temp = *a; // Temp is set to the value stored at a (5)
*a = *b; // value stored at a is changed to the value stored at b (10)
*b = temp; // value stored in address b is changed to 5.
}
It does swap. It swaps local pointers a and b inside swap function. It swaps them perfectly fine, as it should.
If you want to swap the values these pointers are pointing to, you should re-implement your swap function accordingly, i.e. make it swap the pointed values, not the pointers.
Umm maybe using this
void swap(int** a, int** b)
{
int** temp = a;
a = b;
b = temp;
}
int main()
{
int x = 5, y = 10;
int *a = &x, *b = &y;
swap(&a, &b);
printf(“%d %d\n”), *a, *b);
}
Without using a third variable (temp)
void swap(int* a,int* b)
{
// a = 10, b = 5;
*a = *a + *b; // a now becomes 15
*b = *a - *b; // b becomes 10
*a = *a - *b; // a becomes 5
}
zildjohn1's answer is the easiest and clearest way to do it. However if you insist on swapping the pointers, then you have to pass the pointer to the pointer because the pointer itself is passed by value.
You need to send the address of a and b for swap function so while calling swap function you must call ass swap (&a,&b)
So that you pass the address, and alter the address
#define SWAP(a,b) ((a)=(b)+(a),(b)=(a)-(b),(a)=(a)-(b))
Works good.

Resources