Does NULL pointer take any memory?
If it takes memory,then how much memory is consumed by it and what is the significant use of NULL pointer if it takes memory?
A pointer value (NULL or not) requires some amount of space to store and represent (4 to 8 bytes on most modern desktop systems, but could be some oddball size depending on the architecture).
The pointer value NULL represents a well-defined "nowhere"; it's an invalid pointer value guaranteed to compare unequal to the address of any object or function in memory. The macro NULL is set to the null pointer constant, which is a zero-valued integer expression (either a naked 0, or (void *) 0, or some other expression that evaluates to 0).
After the code has been compiled, the null pointer constant will be replaced with the appropriate null pointer value for that particular platform (which may be 0x00000000, or 0xFFFFFFFF, or 0xDEADBEEF, or some other value).
Any pointer value, including NULL, takes a small, system-dependent amount of space to express or store.
That's an altogether separate consideration from any space that the pointed-to object, if any, may require. A NULL pointer is guaranteed to not point to any object, but a non-NULL pointer is not guaranteed to point to an object. On the other hand, there may be more than one pointer to the same object.
Where a NULL pointer is intentionally used, it is typically used to explicitly express an invalid pointer, since you cannot tell from any other pointer value whether that pointer is valid. This can be useful, for example, as a sentinel value marking the end of an unknown-length array of pointers, or as a function return value indicating failure. The canonical example of the latter might be malloc(), which returns NULL if it fails to allocate the requested space.
A NULL pointer doesn't allocate anything. If you have a definition like this:
int *x = NULL;
That means the variable x, which points to an int, doesn't point to anything. You can then check if (x == NULL) to see if it points to valid memory.
Related
I hope not to sound very foolish here, but does the NULL module actually require memory allocation or not when doing this:
TheNull = malloc(sizeof(NULL));
If true, how can something that has no memory allocated actually exist in the ram?
If you use NULL as parameter of malloc(sizeof()), does it return NULL?
No, unless out-of-memory, like any other allocation.
NULL, the null pointer constant, does not have a particular type. It may be void *, int, long, or some integer type.
Avoid sizeof(NULL) as its size/type may differ from system to system.
The expression is not in any other way related to any NULL module or NULL object. There are no such things anyway.
NULL is just a useful definition for a null pointer constant.
The C Standard specifies the NULL macro defined in <stddef.h> and some other standard headers this way:
7.19 Common definitions <stddef.h>[...]
The macros are [...]
NULL
which expands to an implementation-defined null pointer constant [...]
null pointer constant is defined in 6.3.2.3:
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.67) 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.
67) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.19.
Many targets define NULL is defined as #define NULL ((void *)0), while other targets just use #define NULL 0, or possibly some other zero integer constant expression (eg: 0L, 0UL...).
Hence malloc(sizeof(NULL)) attempts to allocate the number of bytes corresponding to the type of the expression in the definition of NULL, probably the size of void pointer, but never 0 bytes.
Whether it succeeds or not depends on available memory:
if successful, the return value will be a valid pointer, different from NULL.
if malloc(sizeof(NULL)); does return NULL, it means no memory is available to allocate a very small size, a critical situation that should be reported to the user and handled with care.
TheNull = malloc(sizeof(NULL));
That doesn't allocate 0 bytes (because sizeof(NULL) isn't zero), but malloc(0) might. The standard says:
If size is zero, the behavior of malloc is implementation-defined. For
example, a null pointer may be returned. Alternatively, a non-null
pointer may be returned; but such a pointer should not be
dereferenced, and should be passed to free to avoid memory leaks.
So, maybe a null pointer, maybe not.
If true, how can something that has no memory allocated actually exist in the ram?
The pointer returned from malloc might point to a piece of memory slightly larger than what you asked for. For example, if you ask for 1 or 2 bytes, you might get 8 (or even 16) bytes instead. A memory manager often only provides certain size memory blocks (for efficiency), and might require a minimum size so its own bookkeping can fit in a free'd block.
And if it returns an oversized block for 1 or 2 bytes, it could do that for 0 bytes as well.
I was playing around with pointers, and I tried to initialize a pointer variable with a value and not a memory location.
If I am initializing a pointer with a non-zero value, and it is clearly giving me a compile time error.
int *p = 1;
main.c:14:14: error: initialization makes pointer from integer without a cast [-Werror=int-conversion]
int *p = 1;
^
However, if I initialize it as value 0, it doesn't give me a compile time error.
int *p = 0; //no compile time error but segmentation fault
Why is this so? Is there a valid memory address like 0? Normally, an address location is shown as 0xffffff or similar way. How is 0 interpreted into a memory location?
Thanks
From the C11 Standard (draft):
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. 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.
Usualy 0 represent a "no address" asNULL. When you use it that way you can check:
if (p) {
doSomthingWith(*p)
}
You are allowed to assign 0 to a pointer because NULL is typically defined as 0 cast to a void *. Any other integer value is a type mismatch.
While you can cast some other integer value to a pointer to assign it a value, it rarely makes sense to do so unless you're dealing with an embedded environment where specific memory locations have known uses.
You're getting a segfault not because you're printing the pointer but because you dereference the pointer and attempt to print what it points to. Because the pointer has a NULL value, dereferencing it causes undefined behavior. In this case, it results in a segfault.
To print the pointer, do the following:
printf("%p\n", (void *)p);
Why is this so? Is there a valid memory address like 0? Normally, an
address location is shown as 0xffffff or similar way. How is 0
interpreted into a memory location?
Generally, the address 0 is not accessible for most of the operating systems, because they reserve it for other tasks.
In C, the address 0 is interpreted as a NULL pointer and a NULL pointer is a pointer that is interpreted as a pointer that is not referencing a valid memory location accessible by the program.
So, if you are defining int* p = 0 or int* p = NULL the program written in C is assuming that the pointer is pointing to nothing (not a 0xffffff address).
A literal 0 in a pointer context represents a null pointer constant. A 1 is always just a 1 and therefore an int.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Can we assign or compare a valid pointer with 0? where could we assign NULL as legal?
See what I know NULL is a invalid pointer , that pointing to heap memory , which pointer has not freed yet.But is the address of the pointer is valid?
NULL as a pointer valid address?
Maybe: NULL is a macro which expands to a null pointer constant. It may have a value like int 0. In that case, it is not a pointer but a int. It may have a value like ((void*)0) which is a pointer. When a null pointer constant is converted to void *, it is a null pointer. No object will have an address that is equal to a null pointer. The null pointer can be assigned to any pointer variable.
Can we assign or compare a valid pointer with 0?
Yes. any_type *ptr = 0; is valid. The comparison if (ptr == 0) is valid. The int 0 is converted to a null pointer as part of the assignment / compare.
where could we assign NULL as legal?
any_type *ptr = NULL; is a legal assignment.
See what I know NULL is a invalid pointer , that pointing to heap memory , which pointer has not freed yet. But is the address of the pointer is valid?
The address is or is not valid is irrelevant. Pointing to heap memory or not is irrelevant. In C, assigning a null pointer to a pointer variable is valid. Comparing a null pointer to a valid object is a valid comparison and the result never matches.
Dereferencing a pointer that has the value of a null pointer is undefined behavior (UB). It may "work", it may crash the code. It is UB.
NULL is the null pointer constant, it's value is implementation defined, that is to say, it is not necessarily being 0.
According to the C11 standard,
Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.
In addition, assign integers to pointers is implementation defined, you should not rely on it if you want to make portable code.
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.
No, NULL does not denote a valid address in any way. NULL is a MACRO which is basically an implementation defined null pointer constant.
Related, C11, chapter 7.19,
NULL
which expands to an implementation-defined null pointer constant
It will compare unequal to any valid pointer and any attempt to derefernce a pointer initialized with NULL will result in UB.
Quoting C11, chapter §6.3.2.3
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.
NULL is by definition an invalid pointer. But. On most systems pointers are just numbers that we give a special treatment. Until a while ago (maybe a decade or so) it was possible on some operating systems to forcibly map memory at the address where a NULL pointer pointed.
This led to a dangerous situation where the operating system kernel could have a relatively harmless bug that led to a NULL dereference and normally just crash. But instead, if a malicious program forcibly mapped memory at the NULL address and then triggered the kernels NULL dereference, it would point to valid memory and if done correctly it could escalate a simple system crash to a kernel level privilege escalation.
There was a bug in Linux where a driver could be fooled into executing a NULL function pointer and that allowed a malicious program to put code at that address that the kernel would execute with raised privileges.
Since then most operating systems have tightened their security and disallow mapping any valid memory at the addresses at and close to NULL ("close to" to protect against array access with a large offset through a NULL pointer).
In a C book I found in an example for implementing a dynamically resizing array this code (simplified):
void *contents = realloc(array->contents, array->max * sizeof(void *));
array->contents = contents;
memset(array->contents + old_max, 0, array->expand_rate + 1);
Source: Learn C The Hard Way – Chapter 34
I was a bit surprised what memset is supposed to achieve here, but then I understood it's used in order to "zero out" the reallocated memory.
I googled in order to find out, if this is what I'm supposed to do after a realloc and found a stackoverflow answer regarding this:
There is probably no need to do the memset […]
But, even if you wanted to "zero it out so everything is nice", or really need the new pointers to be NULL: the C standard doesn't guarantee that all-bits-zero is the null pointer constant (i.e., NULL), so memset() isn't the right solution anyway.
Source: How to zero out new memory after realloc
The suggested solution instead of memset is then to use a for loop in order to set the memory to NULL.
So my question is, as memset does not necessarily mean setting values to NULL and the for loop solution seems a bit tedious – is it really needed to set the newly allocated memory?
So my question is, as memset does not necessarily mean setting values
to NULL and the for loop solution seems a bit tedious – is it really
needed to set the newly allocated memory?
realloc doesn't initialize values of the newly allocated memory segment.
So it is needed to initialize the memory if you are planning to read values of that (uninitialized) memory. Because reading values from that uninitialized memory will trigger undefined behaviour.
By the way, safe way to use realloc (since it can fail) is:
// Since using realloc with size of 0 is tricky and useless probably
// we use below check (from discussion with #chux)
if (new_size == 0)
dosmth();
else
{
new_p = realloc(p, new_size);
if (new_p == NULL)
{
// ...handle error
}else
{
p = new_p;
}
}
Setting a void * to 0 is a value that will compare equal to NULL. Likely memset(ptr, 0, size) is OK - but need to see more code for certainty.
OTOH: is the code correct? Maybe should be
// memset(array->contents + old_max, 0, array->expand_rate + 1);
memset(array->contents + old_max, 0, sizeof(void *) * (array->expand_rate + 1) );
This is wrong:
But, even if you wanted to "zero it out so everything is nice", or
really need the new pointers to be NULL: the C standard doesn't
guarantee that all-bits-zero is the null pointer constant (i.e.,
NULL), so memset() isn't the right solution anyway.
The C standard does in fact guarantee exactly that.
Per section 6.3.2.3 of the C standard:
An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant. 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.
Conversion of a null pointer to another pointer type yields a null
pointer of that type. Any two null pointers shall compare equal.
Note that a pointer with a value of zero is a null pointer. That doesn't mean NULL itself has to be zero. But also note that "any two null pointers shall compare equal". So any null pointer is equal to the NULL value.
Since memset() takes as its second argument an integer value, passing a zero integer value to memset() will produce null pointers. Because the value passed to memset() is "[a]n integer constant expression with the value 0", per 6.3.2.3.
I am a complete novice to C, and during my university work I've come across comments in code that often refer to de-referencing a NULL pointer. I do have a background in C#, I've been getting by that this might be similar to a "NullReferenceException" that you get in .Net, but now I am having serious doubts.
Can someone please explain to me in layman's terms exactly what this is and why it is bad?
A NULL pointer points to memory that doesn't exist. This may be address 0x00000000 or any other implementation-defined value (as long as it can never be a real address). Dereferencing it means trying to access whatever is pointed to by the pointer. The * operator is the dereferencing operator:
int a, b, c; // some integers
int *pi; // a pointer to an integer
a = 5;
pi = &a; // pi points to a
b = *pi; // b is now 5
pi = NULL;
c = *pi; // this is a NULL pointer dereference
This is exactly the same thing as a NullReferenceException in C#, except that pointers in C can point to any data object, even elements inside an array.
Dereferencing just means accessing the memory value at a given address. So when you have a pointer to something, to dereference the pointer means to read or write the data that the pointer points to.
In C, the unary * operator is the dereferencing operator. If x is a pointer, then *x is what x points to. The unary & operator is the address-of operator. If x is anything, then &x is the address at which x is stored in memory. The * and & operators are inverses of each other: if x is any data, and y is any pointer, then these equations are always true:
*(&x) == x
&(*y) == y
A null pointer is a pointer that does not point to any valid data (but it is not the only such pointer). The C standard says that it is undefined behavior to dereference a null pointer. This means that absolutely anything could happen: the program could crash, it could continue working silently, or it could erase your hard drive (although that's rather unlikely).
In most implementations, you will get a "segmentation fault" or "access violation" if you try to do so, which will almost always result in your program being terminated by the operating system. Here's one way a null pointer could be dereferenced:
int *x = NULL; // x is a null pointer
int y = *x; // CRASH: dereference x, trying to read it
*x = 0; // CRASH: dereference x, trying to write it
And yes, dereferencing a null pointer is pretty much exactly like a NullReferenceException in C# (or a NullPointerException in Java), except that the langauge standard is a little more helpful here. In C#, dereferencing a null reference has well-defined behavior: it always throws a NullReferenceException. There's no way that your program could continue working silently or erase your hard drive like in C (unless there's a bug in the language runtime, but again that's incredibly unlikely as well).
It means
myclass *p = NULL;
*p = ...; // illegal: dereferencing NULL pointer
... = *p; // illegal: dereferencing NULL pointer
p->meth(); // illegal: equivalent to (*p).meth(), which is dereferencing NULL pointer
myclass *p = /* some legal, non-NULL pointer */;
*p = ...; // Ok
... = *p; // Ok
p->meth(); // Ok, if myclass::meth() exists
basically, almost anything involving (*p) or implicitly involving (*p), e.g. p->... which is a shorthand for (*p). ...; except for pointer declaration.
From wiki
A null pointer has a reserved value, often but not necessarily the value zero, indicating that it refers to no object
..
Since a null-valued pointer does not refer to a meaningful object, an attempt to dereference a null pointer usually causes a run-time error.
int val =1;
int *p = NULL;
*p = val; // Whooosh!!!!
Quoting from wikipedia:
A pointer references a location in
memory, and obtaining the value at the
location a pointer refers to is known
as dereferencing the pointer.
Dereferencing is done by applying the unary * operator on the pointer.
int x = 5;
int * p; // pointer declaration
p = &x; // pointer assignment
*p = 7; // pointer dereferencing, example 1
int y = *p; // pointer dereferencing, example 2
"Dereferencing a NULL pointer" means performing *p when the p is NULL
A NULL pointer points to memory that doesn't exist, and will raise Segmentation fault. There's an easier way to de-reference a NULL pointer, take a look.
int main(int argc, char const *argv[])
{
*(int *)0 = 0; // Segmentation fault (core dumped)
return 0;
}
Since 0 is never a valid pointer value, a fault occurs.
SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=NULL}
Lots of confusion and confused answers here. First of all, there is strictly speaking nothing called a "NULL pointer". There are null pointers, null pointer constants and the NULL macro.
Start by studying my answer from Codidact: What's the difference between null pointers and NULL? Quoting some parts of it here:
There are three different, related concepts that are easy to mix up:
null pointers
null pointer constants
the NULL macro
Formal definitions
The first two of these terms are formally defined in C17 6.3.2.3/3:
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer
constant.67) 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.
In other words, a null pointer is a pointer of any type pointing at a
well-defined "nowhere". Any pointer can turn into a null pointer when
it is assigned a null pointer constant.
The standard mentions 0 and (void*)0 as two valid null pointer
constants, but note that it says "an integer constant expression with
the value 0". This means that things like 0u, 0x00 and other
variations are also null pointer constants. These are particular
special cases that can be assigned to any pointer type, regardless of
the various type compatibility rules that would normally apply.
Notably, both object pointers and function pointers can be null
pointers. Meaning that we must be able to assign null pointer
constants to them, no matter the actual pointer type.
NULL
The note 67) from above adds (not normative):
67) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.19.
where 7.19 simply defines NULL as (normative):
NULL which expands to an implementation-defined null pointer constant;
In theory this could perhaps be something other than 0 and
(void*)0, but the implementation-defined part is more likely saying
that NULL can either be
#define NULL 0 or #define NULL (void*)0 or some other integer
constant expression with the value zero, depending on the C library
used. But all we need to know and care about is that NULL is a null
pointer constant.
NULL is also the preferred null pointer constant to use in C code,
because it is self-documenting and unambiguous (unlike 0). It should
only be used together with pointers and not for any other purpose.
Additionally, do not mix this up with "null termination of strings", which is an entirely separate topic. Null termination of strings is just a value zero, often referred to either as nul (one L) or '\0' (an octal escape sequence), just to separate it from null pointers and NULL.
Dereferencing
Having cleared that out, we cannot access what a null pointer points at, because it is as mentioned a well-defined "nowhere". The process of accessing what a pointer points at is known as dereferencing, and is done in C (and C++) through the unary * indirection operator. The C standard specifying how this operator works simply states (C17 6.5.3.3):
If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined
Where an informative note adds:
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.
And this would be where "segmentation faults" or "null pointer/reference exceptions" might be thrown. The reason for such is almost always an application bug such as these examples:
int* a = NULL; // create a null pointer by initializing with a null pointer constant
*a = 1; // null pointer is dereferenced, undefined behavior
int* b = 0; // create a null pointer by initializing with a null pointer constant
// not to be confused with similar looking dereferencing and assignment:
*b = 0; // null pointer is dereferenced, undefined behavior
Let's look at an example of dereferencing a NULL pointer, and talk about it.
Here is an example of dereferencing a NULL pointer, from this duplicate question here: uint32_t *ptr = NULL;:
int main (void)
{
uint32_t *ptr = NULL;
// `*ptr` dereferences the NULL ptr
*ptr = 0;
return 0;
}
Memory hasn't been allocated for the uint32_t, so calling *ptr, which "dereferences" the pointer, ptr, or otherwise said: accesses memory at an unallocated (NULL--usually 0, but implementation-defined) address, is illegal. It is "undefined behavior"--ie: a bug.
So, you should statically (preferred, where possible), or dynamically allocate space for a uint32_t and then only dereference a pointer which points to valid memory, as follows.
Here is how to statically allocate memory and use it with a pointer. Note even that the memory for the pointer itself is statically allocated in my example!:
// allocate enough memory for a 4-byte (32-bit) variable
uint32_t variable;
// allocate enough memory for a pointer, which is **usually** 2 bytes on an
// 8-bit microcontroller such as Arduino, or usually 4 bytes on a 32-bit
// architecture, or usually 8 bytes on a 64-bit Linux computer, for example
uint32_t* ptr;
// assign the address of `variable` to the pointer; you can now say that
// `ptr` "points to" the variable named `variable`; in literal terms, `ptr` now
// contains the numerical value of the address of the first byte of the
// variable `variable`
ptr = &variable;
// Store a number into the 4-byte variable named `variable`, via a pointer to it
*ptr = 1234;
// OR, same exact thing as just above: store a number into that 4-byte
// variable, but this time via the variable name, `variable`, directly
variable = 1234;
Note, dynamic allocation is fine too, but static memory allocation is safer, deterministic, faster, better for memory-constrained embedded systems, blah blah blah. The point is simply that you cannot legally dereference any pointer (meaning: put an asterisk "dereference operator" in front of it, like *ptr) which does not point to a chunk of allocated memory. I generally allocate memory statically by declaring a variable.