why I can't print a pointer with value NULL?
This is my code:
#include <stdio.h>
int main(void)
{
int * p = 0;
printf("%p %p ", p, *p);
getchar();
return 0;
}
The error is : "Exception thrown: read access violation.
p was nullptr."
I want to understand the error...
p is NULL, which is an invalid pointer value - there’s no object at that address. The expression *p in the printf call tries to dereference that invalid pointer, and the behavior on doing so is undefined. In this particular case, it causes your code to crash.
Remember that the declaration
int * p = 0;
creates an object of type “pointer to int” (the * is only there to indicate type), and initializes the value of that pointer object to 0 (NULL). By definition, p is not pointing to any object or function, so the expression *p is not meaningful.
Not to mention, the type of the expression *p is int, so you’d use %d to print it, not %p.
Note - there is a null pointer constant and a null pointer value. A zero-valued constant expression in a pointer context (such as 0 or (void*) 0) is a null pointer constant (the NULL macro). During translation, that null pointer constant is converted to a null pointer value, which may or may not be 0. The null pointer value is simply some well-defined address value that’s guaranteed to compare unequal to the address of any object or function.
Pointers point to a variable. Try with this:
#include <stdio.h>
int main(void)
{
int a = 0;
int * p = &a;
printf("%p %p ", p, *p);
getchar();
return 0;
}
Related
I have a basic doubt, when we de-reference a pointer to an array why we get name of the array instead the value of first member of an array, I see this has been asked here but I didn't get it
exactly how?
dereferencing pointer to integer array
main()
{
int var[10] = {1,2,3,4,5,6,7,8,9,10};
int (*ptr) [10] = &var;
printf("value = %u %u\n",*ptr,ptr); //both print 2359104. Shouldn't *ptr print 1?
}
So, is it like when we dereference a pointer, it cancel out the reference operator and what we get is variable name, and in case of pointer to an array, it is the array name ?
main()
{
int a = 10;
int *p = &a;
printf("%d\n", *p) /* p = &a; *p = *(&a); and having a dereference cancel out the &, gives us *p = a ? */
}
Because ptr has type int (*)[10] which is a pointer to an array, *ptr has type int[10] which is an array type.
This array decays to a pointer to its first element when it is passed to printf which then prints the pointer value. The result would be the same if you passed var to printf instead of *ptr.
You do not get a variable name when you dereference a pointer. If the pointer points to an object the you get that object. If it does not point to an object then you get undefined behavior. In particular, if the pointer points to a whole array, then you get that array. That's a fundamental aspect of how pointers work.
However, a fundamental aspect of how arrays work is that in most contexts, an expression of array type is automatically converted to a pointer to the first array element. This address corresponds to the address of the array itself, but has different type (int * in your case, as opposed to int (*)[10]). Typically, converting these to an integer type produces the same value. Thus, in your example code, *ptr is equivalent to var, and each is automatically converted to a pointer of type int *, equivalent to &var[0].
But note also that it is not safe to convert pointers to integers by associating them with printf directives, such as %u, that expect a corresponding integer argument. The behavior is undefined, and in practice, surprising or confusing results can sometimes be observed. One prints a pointer value with printf by using a %p directive, and converting the pointer value to type void *. Example:
printf("pointer = %p %p\n", (void *)*ptr, (void *)ptr);
Combined with the type and value of ptr from your example, this can be expected to reliably print two copies of the same hexadecimal number.
This question was inspired by this snipped from a C book I've been working through
Where is says:
int num;
int *pi=0; // Zero referes to the null pointer, NULL
pi = #
*pi = 0; // Zero refers to the integer zero
We are accustomed to overloaded operators, such as the asterisk used
to declare a pointer, to dereference a pointer, or to multiply. The
zero is also overloaded. We may find this discomforting because we are
not used to overloading operands.
So I did a bunch of investigating with the debugger and my answer is what the debugger showed me. It's undefined behavior, I get that, but I'm not writing a program I'm trying to figure something out. Whatever the case, the pointer is initialized to 1 every time I run it, I'm not depending on that in some calculation, it's what the debugger repeatedly shows.
This is all just one question really, but I had to write more or it wouldn't accept it.
Why does *p=0 have different effects at different times? How is 0 overloaded?
How can I tell if *p=0 is making p a null pointer or if it is assigning 0 to a variable that p is pointing to? And how does the compiler know to assign a null at the address of p rather than the address that p points too?
$ cat prac.c
#include <stdio.h>
int main()
{
int num;
int *p;
printf("0) %p is %d\n",p,*p);
*p=0; //Why is this......
printf("1) %p is %d\n",p,*p);
num=5;
p=#
printf("2) Now %p is %d\n",p,*p);
*p=0; //....different than this
printf("3) p is not null, %p : %d\n",p,*p);
return 0;
}
$ ./prac
0) 0x7ffeb36b5c30 is 1 //pointer is initialized to 1, not-null, definitely out-of-bounds though
1) 0x7ffeb36b5c30 is 0
2) Now 0x7ffeb36b5b3c is 5
3) p is not null, 0x7ffeb36b5b3c : 0
The concept you're asking about is null pointer constants.
The C standard defines a null pointer constant as
An integer constant expression with the value 0, or such an expression cast
to type void *
So the expression 0, which is of type int, is also a null pointer constant. (Note that a null pointer constant needn't be of pointer type.)
The standard further says that:
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.
Given:
int n;
int *p;
this:
p = 0;
implicitly converts the int expression 0 to a null pointer of type int*, while this:
n = 0;
or
*p = 0;
does not perform an implicit conversion, because the object being initialized is already of type int.
The rules for when implicit conversions are invoked are stated in the description of the assignment operator. The same rules apply to initialization, argument passing, and return statements. These rules explicitly state that a null pointer constant is converted to the target type.
See the N1570 draft of the C11 standard (large PDF).
Null pointer constants and null pointers: 6.3.2.3
Simple assignment: 6.15.6.1
I'm not familiar with the book or article you cite, but it failed spectacularly in helping you Understand and Use Pointers in C.
What is a Pointer?
A pointer is simply a normal variable that holds the address of something else as its value. In other words, a pointer points to the address where something else can be found. Where you normally think of a variable holding an immediate values, such as int a = 5;, a pointer would simply hold the address where 5 is stored in memory, e.g. int *b = &a;. It works the same way regardless what type of object the pointer points to. (a pointer, is just a pointer....)
How to Declare, Assign an Address to & Reference the Value Pointed to
Let's take your example and look at what each line does (ignoring your p & pi typos and using p only):
int num; /* declares an integer 'num' whose value is uninitialized */
int *p = 0; /* declares a pointer 'p' and ininializes the address
* to a the constant expression 0. (a Null Pointer Constant)
*/
See C11 Standard - Null Pointer Constant (p3) which is a constant expression with the value 0, or such an expression cast to type void * (e.g. (void *)0). Virtually all C compilers, and if fact the C-Standard provide NULL for this purpose. (see: C11 Standard - 7.19 Common definitions ) So you would generally see:
int *p = NULL; /* declare and initialize 'p' to the Null Pointer Constant */
Next the unary operator '&' is used to obtain the address of an object. Here:
p = # /* assigns the address of 'num' as the value of 'p', so
* 'p' holds the address of 'num' (e.g. 'p' points to the
* memory location where 'num' is stored).
*/
The unary '*' opertor is the dereference operator and provides a way to directly access the value located at the memory address held (pointed to) by a pointer, so:
*p = 0; /* sets the value at the address held by 'p' to zero */
Now lets look at your code and output:
int num;
int *p;
printf("0) %p is %d\n",p,*p);
What is the address held by p and what is the value of num?
You have attempted to access the value of an uninitialized pointer and an uninitialized integer. You have just invoked Undefined Behavior. The defined operation of your code is over and anything can happen, from appearing to behave normally or SegFault'ing. You cannot access uninitialized values.
*p=0;
printf("1) %p is %d\n",p,*p);
p is now initialized to the Null Pointer Constant, you cannot dereference a NULL pointer -- Undefined behavior again.
num=5;
p=#
printf("2) Now %p is %d\n",p,*p);
Hallelujah! num is now initialized to 5 and p now holds (points to) a valid memory address! (but unfortunately once you invoke Undefined Behavior, the game is over, and you may or may not get the correct output, but luckily you appear to.
*p=0;
printf("3) p is not null, %p : %d\n",p,*p);
What does p point to? (hint: num). What does the dereference operator do? (hint: allows you to access the value at the memory location held by a pointer). So what did *p = 0; do? (hint: you just set the value of num to 0, which is the value at the address held by p)
Let me know if you have further questions.
This question already has answers here:
What exactly is meant by "de-referencing a NULL pointer"?
(8 answers)
Closed 5 years ago.
I am studying C at school , and I am facing a problem with pointers , Why does this unhandled error rise (im using visual studio 2013 express for desktop on 64 bit windows 10) , when I try to run the code below.
My question is , Why is this happening?
Code Block :
// ~~ Libraries Or Header Files. ~~ //
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ~~ Main Function ~~ //
int main(void)
{
// ~ Variables ~ //
int * p = NULL;//#define NULL ((void *)0)
printf(*p);
//printf(p)l also raises an error.
// ~ END ~ //
system("PAUSE");
return 0;
}
Error:
" Unhandled exception at 0x009A3C2A in hwQ3.exe: 0xC0000005: Access violation
reading location 0x00000000 ".
There are two problems with this code.
First, printf expects its first argument to be a format string, and the type of the argument is assumed to be const char * (it's a pointer to the first character in a zero-terminated string). Since the object p has type int *, the expression *p has type int, so it's the wrong type, and the value of *p isn't a valid address of a string, because...
You've initialized p to NULL. NULL is an invalid pointer value that's guaranteed to compare unequal to any valid pointer value (it's a well-defined "nowhere" value). When you write *p, you're saying, "I want the value of the integer object p points to." Since p points "nowhere", the behavior of the operation is undefined, and one possible result of undefined behavior is a segfault.
So...
If you want to print the value of the integer object that p points to, you would write something like
printf( "%d\n", *p );
but only after you do a sanity check on p to make sure it isn't NULL:
if ( p ) // or p != NULL
printf( "%d\n", *p );
Valid pointer values are obtained by one of the following methods:
Using the unary & operator on an lvalue (an expression that refers to an object in memory such that the object may be read or updated):
p = &x; // x is an integer object
p = &a[i]; // a is an array of integer, so a[i] is an integer object
p = &foo.bar; // foo is a struct with an int member named bar, so foo.bar is an integer object
etc.
Calling one of malloc, calloc, or realloc:
p = malloc( sizeof *p );
Using an array expression in most circumstances. Unless it is the operand of the sizeof or unary & operators, or is a string literal being used to intialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. In the case of printf, when we write
printf( "this is a test\n" );
the type of the string literal "this is a test\n" is converted from type "16-element array of char" to "pointer to char", and its value is the address of the first character in the string - that address value is what actually gets passed to printf.
The first argument to printf(...) is a const char *format so in both cases you're trying to dereference a NULL pointer. That causes you to access memory outside your allowable range (at zero).
Basic information about pointers:
Pointers are to declare a pointer variable, set it to point somewhere, and finally manipulate the value that it points to. A simple pointer declaration looks like this:
int *ip;
Pointers are generated with the address-of'' operator &, which we can also think of as thepointer-to'' operator. Demonstrating this by declaring (and initializing) an int variable i, and then setting ip to point to it:
int i = 5;
ip = &i;
Example pointer usage:
#include <stdio.h>
int main(){
int var =10;
int *ptr = &var;
printf("%d\n", *ptr);
return 0;
}
What happens when you deference the pointer to NULL?
int *a = NULL; // a is a null pointer
int b = *a; // CRASH: dereferencing a, trying to read it
*a = 0; // CRASH: dereferencing b, trying to write it
I was learning pointers in C when I wrote the following code:
#include <stdio.h>
main()
{
char *p = 0;
*p = 'a';
printf("value in pointer p is %c\n", *p);
}
When I compiled the code, It was compiled successfully. Although, when I executed its out file, a runt-time error occurred: Segmentation Fault (core dumped)
I couldn't understand why that run-time error occurred. After all, the pointer p was pointing to character a, and thus the output should've been a.
Although, when I wrote the following code, it compiled and ran successfully:
#include <stdio.h>
main ()
{
char *p = 0;
char output = 'a';
p = &output;
printf("value which pointer p points is %c\n", *p);
}
Can someone explain me why the first program fails, while the second program runs successfully?
Your code invokes undefined behavior because you are dereferencing a NULL1 pointer. A pointer needs to point to valid memory, a simple way to achieve what you want is this
#include <stdio.h>
int // `main()' MUST return `int'
main(void)
{
char *pointer;
char value;
pointer = &value; // Now the pointer points to valid memory
*pointer = 'a';
printf("value in pointer p is %c\n", *pointer);
return 0;
}
1
6.3.2.3 Pointers
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. 66) 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.
66)The macro NULL is defined in (and other headers) as a null pointer constant; see 7.19.
6.5.3.2 Address and indirection operators
Semantics
The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.102)
102)Thus, &*E is equivalent to E (even if E is a null pointer), and &(E1[E2]) to ((E1)+(E2)). It is always true that if E is a function designator or an lvalue that is a valid operand of the unary & operator, *&E is a function designator or an lvalue equal to E. If *P is an lvalue and T is the name of an object pointer type, *(T)P is an lvalue that has a type compatible with that to which T points.
Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.
In the first example, you set p to 0, which on most implementations is the same as NULL. You then attempt to dereference that pointer (read/write the memory location that p points to), which leads to the core dump. p is not pointing to the character a. This *p = 'a' says "take the memory location that p points to and put a there".
In the second example, you're setting p to the address of output, so it points to a known memory location. Then when you dereference is, you're reading the value at the location where p points, i.e. output. This is valid usage.
A pointer is a "special" variables that store the address of another variables. Take a look at this program, I hope that it will help you clarifying what a pointer is and how to use it :
#include <stdio.h>
int main(void){
int x = 10, *pointer = 0;
pointer = &x;
printf("\nThe address of x : %p.\n", &x);
printf("\nThe address of the pointer : %p.\n", pointer);
printf("\nThe value of x : %d.\n", x);
*pointer += 10;
printf("\nThe value of x after we modifed it with the pointer : %d.\n\n", x);
return 0;
}
If you compile and give this program a run, this will be its output:
The address of x : 0xbf912108.
The address of the pointer : 0xbf912108.
The value of x : 10.
The value of x after we modifed it with the pointer : 20.
As you can clearly see the address of the pointer is the same of the variable itself. That's why when you modify a pointer (for example in my program I do *pointer += 10) it's actually modifying the variable.
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 8 years ago.
There're 2 things I don't understand, usually when using malloc() / calloc() we type cast the it because they return a void pointer so we type cast it to our pointer type so we could do pointer arithmetic with it.
So I've made a code example where I use malloc() and I don't type cast it and the pointer arithmetic still works :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p = malloc(8);
*p++ = 30;
*p = 40;
printf("p points to address [%p] which holds a value of %d, p points to address [%p] which holds a value of %d\n", p, *p++, p, *p--);
return 0;
}
why is that ?
Another question of mine regarding to pointers arithmetic is that the code I showed you above, I originally wrote it as follow :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p = malloc(8);
*p++ = 30;
*p-- = 40;
printf("p points to address [%p] which holds a value of %d, p points to address [%p] which holds a value of %d\n", p, *p++, p, *p--);
return 0;
}
Notice the difference is *p-- = 40.
I've use p-- because I wanted to print the correct address the pointer was pointing at, I was assuming that after I use p++ I need to use p-- so the pointer will point at the address of the value of 30, but if I added the p-- and printed it I've noticed that it prints another value.
So something here doesn't click for me what's going on with it ? Also if I removed the -- and then printed, it printed 30 and then 40 as I expected BUT the address remained the same, I've expected it to be the previous address+4 which it wasn't yet the value changed, what's going on ?
http://imgur.com/GRRInBL
Pointer arithmetic depends on the type with which your pointer is declared. Since your pointer is int *, then ++ and -- will increment and decrement the (raw) value of the pointer by sizeof(int) so that you can access adjacent int values.
In C, it is possible to assign a void * to another type of pointer (such as int *) without triggering a warning (this is not true in C++). In this case the cast is implicitly performed by the compiler.