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

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.

Related

Why do we need int *ptr = NULL;?

I don't quite understand why in this example we need a part int *ptr = NULL;. I understand what pointers are, but why do we need this * (points at a value attached to an address) here? And why do we need NULL here?
#include <stdio.h>
int main() {
int a[5] = {22, 33, 44, 55, 66};
int *ptr = NULL;
int i;
ptr = a;
for (i = 0; i < 5; i++) {
printf("%d ", *(ptr + i));
}
}
This intermediate initialization
int *ptr = NULL;
is redundant. You could write at once
int *ptr = a;
Moreover such an initialization is a bad programming style. Each variable should be declared and initialized where it is used. Otherwise the code will confuses users as it confused you.
I would rewrite the program the following way
#include <stdio.h>
int main( void )
{
int a[] = { 22, 33, 44, 55, 66 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( const int *ptr = a; ptr != a + N; ++ptr )
{
printf( "%d ", *ptr );
}
putchar( '\n' );
}
There are cases when the same one pointer can be used in various contexts. In this case it makes sense to declare it and initialize with NULL. But your simple program is not the case.
In your case int *ptr = NULL is completely redundant as you could just write int *ptr = a as Vlad has already said, but more generally it is a good idea to initialise pointers to NULL because if for some reason you have an error in your code and you need to debug it, it is a lot easier to debug what is happening to the pointer if it starts as NULL than if you hadn't initialised it and it is filled with some garbage value.
I don't quite understand why in this example we need a part int *ptr = NULL;.
[...]
why do we need this * (points at a value attached to an address) here?
You are mistaking the significance of the *. In that context, it is not the unary * operator. Rather, it is part of the syntax for declaring a variable whose type is a pointer type. The declaration declares ptr as a variable of type int *, i.e. pointer-to-integer. Without the *, the declaration would be designating ptr's type as int, not as a pointer type.
And why do we need NULL here?
You don't. The = NULL is an initializer for variable ptr, defining its initial value, but you assign a different value to that variable before ever reading it, so the initializer has no practical significance.
Some people are inclined to provide such initializers as a matter of course, on the theory that it avoids accidental usage of wild pointers and / or allows (otherwise-)uninitialized pointers to be detected, but as Emerson wrote, "A foolish consistency is the hobgoblin of little minds." The initializer serves no useful purpose in this particular code. If one insists on providing an initializer then there's no reason not to initialize ptr directly to a:
int *ptr = a;
as your other answers also suggest.

Structures and linked list accessing.

#include <stdio.h>
int main(void)
{
typedef struct{
int a;
} cool;
cool x;
(&x)->a = 3;
x.a = 4;
}
I was wondering if the (&x)-> a does the same thing as the x.a. I coded both of them up, and it seemed that both of them changed the value of x.a. I know it must be a pointer on the left side of ->, but the (&x) seems to work without problem. Printing out x.a works for both of them, and gives me the correct answer. I looked up a lot about pointers, linked list, and structures and am still not able to find out the answer. Would it be possible to get an explanation? Thank you!
The -> operator expects a pointer on the left hand side. &x returns the address of x so it satisfies that requirement (even if it is totally redundant). To think about it another way...
cool *y = x;
y->a = 3;
The . operator expects a stack allocated struct on the left hand side. x is that, so x.a works fine.
You can also go the other way, if you have a pointer y you can dereference it with *y and use . on it: (*y).a. This is also totally redundant.
The & prefix operator returns the memory address of whatever object you put it in front of.
This means that you have to put it in front of objects that actually have a memory address. For example, literals and temporary expression results don't necessarily have an address. Variables declared with register storage class don't have an address, either.
Thus:
int i = 5;
&i; // works
&5; // Nope!
&(i + 1); // Nope!
&i + 1; // Works, because &i has higher precedence than +1.
So what does the address of an object give you? It is a pointer to the object. This is how you can do dynamic memory allocation using the heap. This is where functions like malloc() come in. And this is how you can build arbitrarily large data structures.
In C, arrays are represented as pointers. So arrays and pointers are often used interchangeably. For example:
char buffer[100]; // array
strcpy(buffer, "hello"); // strcpy is declared to take (char *, const char *)
The opposite of the address_of operator is the * dereference operator. If I declare a pointer to something, I can get "what it points at" using this syntax:
int i = 5;
int *pi = &i; // pointer to int. Note the * in the declaration?
i + i; // 10
i + *pi; // Also 10, because pi "points to" i
In the case where you have an aggregate type like a struct or union, you would have to do something like this:
struct {
int a;
} s;
s.a = 5;
/* ??? */ ps = &s; // pointer to s
s.a; // 5
(*ps).a; // Also 5, because ps points to s.
ps->a; // 5, because a->b is shorthand for (*a).b
This only works, of course, if you have a pointer to an object that CAN use the .member and that has an appropriately named member. For example, you can't do this:
i = 5;
pi = &i;
pi->a; // WTF? There is no i.a so this cannot work.
If you have a pointer, you can take the address of it. You then have a pointer to a pointer. Sometimes this is an array of pointers, as with the argv array passed to main:
int main(int argc, const char *argv[]);
int main(int argc, const char **argv); // Effectively the same.
You can do weird stuff with pointers to pointers:
int i = 5;
int j = 100;
int * pij;
for (pij = &i; i < j; ) {
if (i & 1) {
*pij *= 2;
pij = &j;
}
else {
i += 1;
*pij -= 1;
pij = &i;
}
}
Note: I have no idea what that code does. But it's the kind of thing you can wind up doing if you're working with pointers.

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

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.

C Putting code in one liner

I'm learning C and this is probably the most stupid question ever but here it goes!
My code:
char tmp = *x++;
char *g = &tmp;
Can I do this line of code in a one liner? With something like:
char *g = &(*x++);
More info:
char *x = "1234";
//Turn each 'number' to a int
while(*x != '\0'){
char tmp = *x++;
char *x = &tmp;
int t = atoi(x);
}
If x is a pointer to char (and points to an existing object), then the declaration char *g = &(*x++); is allowed in standard C and has defined behavior.
The result of the * operator is an lvalue, per C 2011 6.5.3.2 4, so its address may be taken with &.
In detail:
x++ increments x and produces the original value of x. (Note: Incrementing a pointer requires that the pointer point to an object. It does not require that it be an array element or that there be another object after it; you are allowed to increment to point one past an object, as long as you do not then dereference a pointer to a non-existent object.)
*x++ dereferences the pointer (the original value of x). The result is an lvalue.
&(*x++) takes the address of the lvalue, which is the original value of x.
Then this value is used to initialize g.
Additionally, C 2011 6.5.3.2 3 specifies that the combination of & and * cancel, except that the result is not an lvalue and the usual constraints apply, so the & and * operations are not actually evaluated. Thus, this statement is the same as char *g = x++;.
Just as a hint: Are you aware that you are shadowing the outer x variable?
What you are currently doing is:
char *x = "1234"; //declare c style string
while(*x != '\0'){ //for the conditional the "outer" x will be used for comparsion
char tmp = *x++; //increment x to point to whatever comes sizint atoi (const char * str);eof(char) bytes afterwards; dereference what x previously pointed to (postfix ++) and save it in local char tmp
char *x = &tmp; //take adress of the local char and save its adress in a new local/inner char*
int t = atoi(x); //call atoi on the inner x
Although this may work it may be confusing style to shadow variables like this. (Confusing for other developers especially)
Also take a look at the signature of atoi:
int atoi (const char * str);
Here you can see that you can safely pass the pointer like this:
int t = atoi(&x);
++x;
Or preferably:
int t = atoi(&x++);

Understanding C: Pointers and Structs

I'm trying to better understand c, and I'm having a hard time understanding where I use the * and & characters. And just struct's in general. Here's a bit of code:
void word_not(lc3_word_t *R, lc3_word_t A) {
int *ptr;
*ptr = &R;
&ptr[0] = 1;
printf("this is R at spot 0: %d", ptr[0]);
}
lc3_word_t is a struct defined like this:
struct lc3_word_t__ {
BIT b15;
BIT b14;
BIT b13;
BIT b12;
BIT b11;
BIT b10;
BIT b9;
BIT b8;
BIT b7;
BIT b6;
BIT b5;
BIT b4;
BIT b3;
BIT b2;
BIT b1;
BIT b0;
};
This code doesn't do anything, it compiles but once I run it I get a "Segmentation fault" error. I'm just trying to understand how to read and write to a struct and using pointers. Thanks :)
New Code:
void word_not(lc3_word_t *R, lc3_word_t A) {
int* ptr;
ptr = &R;
ptr->b0 = 1;
printf("this is: %d", ptr->b0);
}
Here's a quick rundown of pointers (as I use them, at least):
int i;
int* p; //I declare pointers with the asterisk next to the type, not the name;
//it's not conventional, but int* seems like the full data type to me.
i = 17; //i now holds the value 17 (obviously)
p = &i; //p now holds the address of i (&x gives you the address of x)
*p = 3; //the thing pointed to by p (in our case, i) now holds the value 3
//the *x operator is sort of the reverse of the &x operator
printf("%i\n", i); //this will print 3, cause we changed the value of i (via *p)
And paired with structs:
typedef struct
{
unsigned char a;
unsigned char r;
unsigned char g;
unsigned char b;
} Color;
Color c;
Color* p;
p = &c; //just like the last code
p->g = 255; //set the 'g' member of the struct to 255
//this works because the compiler knows that Color* p points to a Color
//note that we don't use p[x] to get at the members - that's for arrays
And finally, with arrays:
int a[] = {1, 2, 7, 4};
int* p;
p = a; //note the lack of the & (address of) operator
//we don't need it, as arrays behave like pointers internally
//alternatively, "p = &a[0];" would have given the same result
p[2] = 3; //set that seven back to what it should be
//note the lack of the * (dereference) operator
//we don't need it, as the [] operator dereferences for us
//alternatively, we could have used "*(p+2) = 3;"
Hope this clears some things up - and don't hesitate to ask for more details if there's anything I've left out. Cheers!
I think you are looking for a general tutorial on C (of which there are many). Just check google. The following site has good info that will explain your questions better.
http://www.cplusplus.com/doc/tutorial/pointers/
http://www.cplusplus.com/doc/tutorial/structures/
They will help you with basic syntax and understanding what the operators are and how they work. Note that the site is C++ but the basics are the same in C.
First of all, your second line should be giving you some sort of warning about converting a pointer into an int. The third line I'm surprised compiles at all. Compile at your highest warning level, and heed the warnings.
The * does different things depending on whether it is in a declaration or an expression. In a declaration (like int *ptr or lc3_word_t *R) it just means "this is a pointer."
In an expression (like *ptr = &R) it means to dereference the pointer, which is basically to use the pointed-to value like a regular variable.
The & means "take the address of this." If something is not a pointer, you use it to turn it into a pointer. If something is already a pointer (like R or ptr in your function), you don't need to take the address of it again.
int *ptr;
*ptr = &R;
Here ptr is not initialized. It can point to whatever. Then you dereference it with * and assign it the address of R. That should not compile since &R is of type lc3_word_t** (pointer to pointer), while *ptr is of type int.
&ptr[0] = 1; is not legal either. Here you take the address of ptr[0] and try to assign it 1. This is also illegal since it is an rvalue, but you can think of it that you cannot change the location of the variable ptr[0] since what you're essentially trying to do is changing the address of ptr[0].
Let's step through the code.
First you declare a pointer to int: int *ptr. By the way I like to write it like this int* ptr (with * next to int instead of ptr) to remind myself that pointer is part of the type, i.e. the type of ptr is pointer to int.
Next you assign the value pointed to by ptr to the address of R. * dereferences the pointer (gets the value pointed to) and & gives the address. This is your problem. You've mixed up the types. Assigning the address of R (lc3_word_t**) to *ptr (int) won't work.
Next is &ptr[0] = 1;. This doesn't make a whole lot of sense either. &ptr[0] is the address of the first element of ptr (as an array). I'm guessing you want just the value at the first address, that is ptr[0] or *ptr.

Resources