I am trying to learn C. The reading I've been doing explains pointers as such:
/* declare */
int *i;
/* assign */
i = &something;
/* or assign like this */
*i = 5;
Which I understand to mean i = the address of the thing stored in something
Or
Put 5, or an internal representation of 5, into the address that *i points to.
However in practice I am seeing:
i = 5;
Should that not cause a mismatch of types?
Edit: Semi-colons. Ruby habits..
Well, yes, in your example setting an int pointer to 5 is a mismatch of types, but this is C, so there's nothing stopping you. This will probably cause faults. Some real hackery could be expecting some relevant data at the absolute address of 5, but you should never do that.
The English equivalents:
i = &something
Assign i equal to the address of something
*i =5
Assign what i is pointing to, to 5.
If you set i = 5 as you wrote in your question, i would contain the address 0x00000005, which probably points to garbage.
Hope this helps explain things:
int *i; /* declare 'i' as a pointer to an integer */
int something; /* declare an integer, and set it to 42 */
something = 42;
i = &something; /* now this contains the address of 'something' */
*i = 5; /* change the value, of the int that 'i' points to, to 5 */
/* Oh, and 'something' now contains 5 rather than 42 */
If you're seeing something along the lines of
int *i;
...
i = 5;
then somebody is attempting to assign the address 0x00000005 to i. This is allowed, although somewhat dangerous (N1256):
6.3.2.3 Pointers
...
3 An integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant.55) If a null pointer constant is converted to a
pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
...
5 An integer may be converted to any pointer type. Except as previously specified, the
result is implementation-defined, might not be correctly aligned, might not point to an
entity of the referenced type, and might be a trap representation.56)
...
55) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.17.
56) The mapping functions for converting a pointer to an integer or an integer to a pointer are intended to be consistent with the addressing structure of the execution environment.
Depending on the architecture and environment you're working in, 0x00000005 may not be a valid integer address (most architectures I'm familiar with require multibyte types to start with even addresses) and such a low address may not be directly accessible by your code (I don't do embedded work, so take that with a grain of salt).
I understand to mean i = the address of the thing stored in something
Actually i contains an address, which SHOULD be the address of a variable containing an int.
I said should because you can't be sure of that in C:
char x;
int *i;
i = (int *)&x;
if i is a pointer, than assign to it something different to a valid address accessible from you program, is an error an I think could lead to undefined behavior:
int *i;
i = 5;
*i; //undefined behavior..probably segfault
here's some examples:
int var;
int *ptr_to_var;
var = 5;
ptr_to_var = var;
printf("var %d ptr_to_var %d\n", var, *ptr_to_var); //both print 5
printf("value of ptr_to_var %p must be equal to pointed variable var %p \n" , ptr_to_var, &var);
I hope this helps.
This declares a variable name "myIntPointer" which has type "pointer to an int".
int *myIntPointer;
This takes the address of an int variable named "blammy" and stores it in the int pointer named "myIntPointer".
int blammy;
int *myIntPointer;
myIntPointer = &blammy;
This takes an integer value 5 and stores it in the space in memory that is addressed by the int variable named "blammy" by assigning the value through an int pointer named "myIntPointer".
int blammy;
int *myIntPointer;
myIntPointer = &blammy;
*myIntPointer = 5;
This sets the int pointer named "myIntPointer" to point to memory address 5.
int *myIntPointer;
myIntPointer = 5;
assignment of hard-coded addresses, is something that shouldn't be done (even in the embedded world, however there are some cases where it's suitable.)
when declaring a pointer, limit yourself to only assign a value to it with dynamiclly allocated memory(see malloc()) or with the & (the address) of a static (not temporary) variable. this will ensure rebust code, and less chance to get the famous segmentation fault.
good luck with learning c.
Related
In int *x x is a pointer to integer.
If we initialize with a statement something like this: int *x = &p now x is pointing to the address of "p".
The value that it produces is: 6422036
Does that mean in int *x x is a pointer to the type int or it's a pointer to an integer value?
Is it conceptually something like int *x = &int as default?
When I compile this:
#include <stdio.h>
main ()
{
int *x;
printf("%d", x);
return 0;
}
It gives the value 16.
What does it mean?
I think your question is based on a misunderstanding, so I am going to do some bean-counting on your phrasings. (Not contradicting ikegami by the way, just trying to provide a different approach or viewpoint.)
In int *x x is a pointer to integer.
Yes.
if we initialize the statement with something like this: int *x = &p now x is pointing to the address of p.
Not exactly, now x contains the address of p (which hopefully is an int). It is considered to point to p.
The value that it produces is: 6422036
If you say so, but that is not reproducable and you should probably never think or know about that value. Any other value at this point would means the same - or nothing.
Does that mean in int *x x is a pointer to the type int or it's a pointer to an integer value?
Yes.
To be precise, for a C programmer those are one and the same thing.
Whatever it is pointing to is an integer value, i.e. it is of int type. (Skipping the differences of unsigned int, long int, short etc., I am convinced you are not asking about that.)
If you see a difference between those two, then your understanding is not C (I suspect it comes from a different language, see introspection as discussed by ikegami.)
is it conceptually something like int *x = &int as default?
No. There is no such thing as &int in C. It is more like
int *x; /* Don't you dare dereference this before you assigned a decent address.
and be sure to assign an address of something you are actually allowed
to at least read - or expect little demons flying out of your nose. */
Note that "demons flying out of your nose" is practically a technical term used among programmers to describe that absolutely anything can happen, usually undesired things. Most undesired possible result is that it passes all tests and then fails catastrophically in the most inconvenient situation.
Actually it is called undefined behaviour.
C doesn't have reflection. There's no int type in memory, just values of that type. As such, x isn't a pointer to the type int. It is indeed a pointer to an integer value.
Given int *x, we can say:
*x is an int
x is an int*, which is to a pointer to an int.
That assumes x has been properly initialized and isn't NULL. This isn't the case in your program. Reading x before giving it a value is a bug.
Also, providing a pointer to %d is a bug. To display a pointer, you need
printf("%p\n", (void*)x); // One of the weird times when a `void*` cast is needed.
Again, this is only legit after you initialize x.
A valid program:
#include <stdio.h>
int main(void)
{
int i = 123;
int *p = &i;
printf("%p\n", (void*)p);
printf("%p\n", (void*)&i);
printf("%p\n", (void*)&p);
printf("%d\n", i);
printf("%d\n", *p);
return 0;
}
Does that mean in int *x x is a pointer to the type int or it's a pointer to an integer value?
x is an object stores values of type int *; that is, it stores the address of an int object.
It gives the value 16.
What does it mean?
It means you've invoked undefined behavior - you're using the wrong format specifier for the type.
The proper way to print a pointer value is
printf( "%p\n", (void *) x );
In the declaration
int *x;
the initial value of x is indeterminate - it could be anything, from 0x00000000 to 0x00000010 (16) to 0xDEADBEEF to anything else.
There's nothing magic about pointer variables - they store values of a specific type, like an int variable stores integer values and double variable stores floating-point values.
Pointer declaration syntax and operations on pointers are a little non-intuitive and hard to grasp at first, but pointer values themselves are relatively simple things to understand; they're just addresses1 of objects (or functions) in memory.
There's no single pointer type - an int * is a distinct type from a double *, which is a distinct type from a char *, etc. Different pointer types may have different sizes or representations, but on platforms like x86 they all have the same representation.
In a declaration, the presence of a unary * in the declarator means the variable has pointer type:
T *p; // p is a pointer to T
T *ap[N]; // ap is an array of pointers to T
T (*pa)[N]; // pa is a pointer to an array of T
T *fp(); // fp is a function returning a value of type pointer to T
T (*pf)(); // pf is a pointer to a function returning a value of type T
T **pp; // pp is a pointer to pointer to T - it stores the address of
// an object of type T *
In an expression, the presence of the unary * operator means we want to dereference the pointer and obtain the value of the thing it points to:
int x = 10;
int *p = &x; // save the address of x in p
printf( "%d\n", *p ); // print the value stored in x by dereferencing p
More properly, they're abstractions of addresses. Whether those addresses are physical or virtual depends on the environment you're operating in.
See the two codes below!
int main() {
int a = 12;
int *p;
*p = a;
}
and the this code,
int main() {
int a = 12;
int *p;
p = &a;
}
In the first piece of code dereferenced the pointer as this *p = a, and in the second piece of code, the address of variabe a is set to the pointer variable.
My question is what is the difference between both pieces of codes?
In your first piece of code:
int main() {
int a = 12;
int *p;
*p = a;
}
you have a serious case of undefined behaviour because, what you are trying to do is assign the value of a to the int variable that p currently points to. However, p has not been assigned an 'address', so it will have an arbitrary - and invalid - value! Some compilers may initialise p to zero (or NULL) but that is still an invalid address (on most systems).
Your second code snippet is 'sound' but, as it stands, doesn't actually achieve anything:
int main() {
int a = 12;
int *p;
p = &a;
}
Here, you are assigning a value (i.e. an address) to your pointer variable, p; in this case, p now points to the a variable (that is, it's value is the address of a).
So, if you appended code like this (to the end of your second snippet):
*p = 42;
and then printed out the value of a, you would see that its value has been changed from the initially-given 12 to 42.
Feel free to ask for further clarification and/or explanation.
Declaring *p and a is reserving some space in memory, for a pointer in first case, for what a is in the 2nd case (an int).
In these both cases, their values are not initialized if you don't put anything in it. That doesn't mean there is nothing in it, as that is not possible. It means their values are undetermined, kind of "random" ; the loader just put the code/data in memory when requested, and the space occupied by p, and the one occupied by a, are both whatever the memory had at the time of loading (could be also at time of compilation, but anyway, undetermined).
So you take a big risk in doing *p = a in the 1st case, since you ask the processeur to take the bytes "inside" a and store them wherever p points at. Could be within the bounds of your data segments, in the stack, somewhere it won't cause an immediate problem/crash, but the chances are, it's very likely that won't be ok!
This is why this issue is said to cause "Undefined Behavior" (UB).
When you initialized a pointer you can use *p to access at the value of pointer of the pointed variable and not the address of the pointed variable but it's not possible to affect value like that (with *p=a). Because you try to affect a value without adress of variable.
The second code is right use p = &a
The first one is bad:
int main() {
int a = 12;
int *p;
*p = a;
}
It means: put the value of variable a into location, pointed by pointer p. But what the p points? probably nothing (NULL) or any random address. In best case, it can make execution error like access violation or segmentation fault. In worst case, it can overwrite any existing value of totally unknown variable, resulting in problems, which are very hard to investigate.
The second one is OK.
int main() {
int a = 12;
int *p;
p = &a;
}
It means: get the pointer to (existing) variable a and assign it to pointer p. So, this will work OK.
What is the difference between dereferencing and assigning the address of a variable to pointer variable in C?
The latter is the premise for the first. They are separate steps to achieve the benefit of pointer dereferencing.
For the the explanation for where the difference between those are, we have to look what these guys are separately:
What is dereferencing the pointer?
First we need to look what a reference is. A reference is f.e. an identifier for an object. We could say "Variable a stands for the value of 12." - thus, a is a reference to the value of 12.
The identifier of an object is a reference for the value stored within.
The same goes for pointers. pointers are just like usual objects, they store a value inside, thus they refer to the stored values in them.
"Dereferencing" is when we "disable" this connection to the usual value within and use the identifier of p to access/refer to a different value than the value stored in p.
"Dereferencing a pointer" means simply, you use the pointer to access the value stored in another object, f.e. 12 in a instead through its own identifier of a.
To dereference the pointer the * dereference operator needs to precede the pointer variable, like *p.
What is assigning the address of a variable to a pointer?
We are achieving the things stated in "What is dereferencing a pointer?", by giving the pointer an address of another object as its value, in analogy like we assign a value to a usual variable.
But as opposed to usual object initializations/assignments, for this we need to use the & ampersand operator, preceding the variable, whose value the pointer shall point to and the * dereference operator, preceding the pointer, has to be omitted, like:
p = &a;
Therafter, The pointer "points" to the address the desired value is stored at.
Steps to dereferencing a pointer properly:
First thing to do is to declare a pointer, like:
int *p;
In this case, we declare a pointer variable of p which points to an object of type int.
Second step is to initialize the pointer with an address value of an object of type int:
int a = 12;
p = &a; //Here we assign the address of `a` to p, not the value of 12.
Note: If you want the address value of an object, like a usual variable, you need to use the unary operator of &, preceding the object.
If you have done these steps, you are finally be able to access the value of the object the pointer points to, by using the *operator, preceding the pointer object:
*p = a;
My question is what is the difference between both pieces of codes?
The difference is simply as that, that the first piece of code:
int main() {
int a = 12;
int *p;
*p = a;
}
is invalid for addressing an object by dereferencing a pointer. You cannot assign a value to the pointer´s dereference, if there isn´t made one reference before to which the pointer do refer to.
Thus, your assumption of:
In the first piece of code I dereferenced the pointer as this *p = a...
is incorrect.
You do not be able to dereference the pointer at all in the proper way with *p = a in this case, because the pointer p doesn´t has any reference, to which you are be able to dereference the pointer correctly to.
In fact, you are assigning the value of a with the statement of *p = a somewhere into the Nirwana of your memory.
Normally, the compiler shall never pass this through without an error.
If he does and you later want to use the value, which you think you´d assigned properly by using the pointer, like printf("%d",*p) you should get a Segmentation fault (core dumped).
My understanding is that when you declare a pointer, say int *a = 5, a is the pointer, and *ais the int pointed to - so the * indicates you're accessing the pointer data. (And the & is accessing the address). Hopefully this is correct?
How come when I'm doing printf it doesn't seem to work the way I want?
int main()
{
int *a = 5;
printf("%d\n",a);
return 0;
}
This gives me the correct result, which I didn't expect. When I did *a instead of a in the printf, it failed, which I'm confused with?
Nopes, int *a = 5; does not store an int value of 5 into the memory location pointed by a, the memory location itself is 5 (which is mostly invalid). This is an initialization statement, which initializes the variable a which is of type int * (a pointer) to 5.
For ease of understanding, consider the following valid case
int var = 10;
int *ptrVar = &var;
here, ptrVar is assigned the value of &var, the pointer. So, in other words, ptrVar points to a memory location which holds an int and upon dereferencing ptrVar, we'll get that int value.
That said, in general,
printf("%d\n",a);
is an invite to undefined behavior, as you're passing a pointer type as the argument to %d format specifier.
The declaration int *a does declare a to be a pointer. Thus, the declaration
int *a = 5;
initializes a with the value 5. Just like how
int i = 5;
would initialize i with the value 5.
There are very few situations where you would want to initialize a pointer variable with a literal value (other than 0 or NULL). Those would likely be embedded (or otherwise esoteric) applications where certain addresses have a defined meaning on a particular platform.
Output is: 10 and it gives no error.
int main(){
int j=10;
int *i=&j;
printf("%d",*i);
return 0;
}
but it gives me an error:
int main(){
int *i;
int j=10;
*i=&j;
printf("%d",*i);
return 0;
}
I understand that pointer de-referencing is causing the error. But how is that happening?
Because you are using an uninitialized pointer.
Your *i = &j should be i = &j
This defines i as an int * and sets its value to the address of j:
int *i=&j;
This defines i as an int *, then tries to set what i points to to the address of j:
int *i;
int j=10;
*i=&j;
The final *i = ... is trying to dereference an uninitialized variable.
int *i=&j;
Here you're declaring i to be a int *, and assigning the address of j.
*i=&j;
In this case, though, you've already declared i, and you're assigning &j to the location that i points to rather than to i itself. So that's one error. Another is that i doesn't point to anything yet because you haven't initialized it. If you want i to point to j, you should drop the *:
i = &j;
i itself is declared as a "pointer to int". So you should write i = &j; to assign it with the address of j.
In your case, *i = &j dereferences it before the assignment, that is, the value of a pointer is assigned to an int, which resides in a legal or illegal memory block, because i is uninitialised.
Note that accessing an uninitialised variable causes undefined behaviour, not to mention accessing the object an uninitialised pointer points to.
Here is a simple declaration, with initialization, of an integer variable i:
int i = 10;
Normally it is very easy to split up the declaration and the initialization:
int i;
/* ... */
i = 10;
That's fine. But the syntax of pointer declarations in C is unusual, and it leads to a little bit of asymmetry when working with declarations and initializations. You can write
int *i = &j; /* correct */
But if you split it up, the * does not tag along, because it was part of the declaration.
int *i;
/* ... */
i = &j; /* right */
*i = &j; /* WRONG */
int *i;
You've declared i as a pointer to int, but you haven't set it to point to anything yet; the value of i is indeterminate1. It will contain some random string of bits that (most likely) does not correspond to a valid address2. Attempting to dereference i at this point leads to undefined behavior, which can mean anything from an outright crash to corrupted data to working without any apparent issues.
The line
*i = &j;
has two problems, the first one being that i doesn't point anywhere meaningful (and this is where your runtime error is undoubtedly coming from; you're attempting to access an invalid address). The second is that the types of *i and &j don't match; *i has type int, while &j has type int *.
Variables declared locally to a function without the static keyword have automatic storage duration, and are not implicitly initialized to any particular value. Do not assume that any such variable is initially set to 0 or NULL in the absence of an explicit initializer. Variables declared outside of any function body or with the static keyword have static storage duration, and those variables will be initialized to 0 or NULL in the absence of an explicit initializer.
"Valid" meaning the address of an object defined within your program (i.e., another variable, or a chunk of memory allocated via `malloc`, etc.) or a well-known address defined by the platform (such as a fixed hardware input address). NULL is a well-defined invalid address that's easy to test against.
I was wondering what is the difference between these two lines of code?
int hi;
int *hi;
In the C programming language?
Thanks!
Amit
int hi;
reserves the space for an int in memory, and each time you reference hi, you either read or write directly that int in memory space.
int *hi;
reserves the space for a pointer to an int in memory, each time hi is used, the pointer is either read or written. Meaning that you are not working with an int, only a pointer to an int - there must exist an int somewhere for the pointer to reference something workable. For instance
int hi;
int *phi;
phi = &hi; // phi references the int hi
*phi = 3; // set `hi` to 3
int hi declares the variable hi to be an integer.
int *hi declares the variable hi to be a pointer to an integer.
The first declares an integer variable, while the second declares a pointer to an integer.
Pointers are beyond the scope of a StackOverflow post, but this Wikipedia article is a starting point, and there should be at least a chapter on pointers in whatever book you're using to learn C.
hi stores the integer type value in a particular location, but
*hi stores the address of any int type variable.
Example :
int hi = 10;
int *hello = &hi;
int hi------ indicates that hi is the integer which allocates 2 bytes for it.
int *hi------ * indicates the pointer which holds the address of the variable and that variable is an integer.
both are different.one indicates the integer and the other indicates the address of the integer.
int hi;
reserve a place in the memory for an integer variable while
int *ptr;
reserve a place in the memory for a pointer which contain the memory address of other variable. you can use the pointers in different ways.
int *ptr = hi;
int *ptr;
ptr = &hi;
when you change the value of the ptr you change the address where it is pointing for but if you changed the value after de-referencing the address you are changing the value of the other variable.
*ptr = 3;
leads to change the value of hi;
a. int i;
b. int *address;
c. address = &i;
In line a an integer variable named i is declared. When this is done the compiler reserves a memory space of size sizeof(int) (it's 4 byte on my computer). If you want to refer to this memory space then you have to use pointers.
Line b declares a variable named address which has a special property. This variable doesn't holds an int but it stores the address of a variable that is of type int. Therefore, whatever value address has, it should be interpreted as the address of a variable which is of type int. Currently, the variable address doesn't hold any memory address in it as we haven't yet defined which variable's memory address it has to hold.
Line c can be read as "address is equal to the memory address of variable i". Now, the variable address stores the memory address of the int variable i.
int main(){
int a;
int &b;
b=&a;
a=10;
return 0;
}
When this code is run using a debugger I see:
a = 10 // the variable's value
b = 0x7fffffffe2fc // this is the address at which 'a' is stored.
Pointers are very powerful and you will start to use it more often once you understand it. Apart from the materials that others suggested for you to read I suggest use a debugger(gdb) and run a few programs with pointers in it and check every variable that you declared in the code. I understand things better when I have a visual picture of any problem and I think it might as well speed up your understanding of pointers.
First -int hi;
here you declaring a integer variable named "hi"
Then -int *hi;
here "hi" is a pointer which can point to a integer value
Note:int* hi and int *hi are syntactically same