It is undefined behaviour to de-reference a null pointer. The fix is simply to ensure that the pointer refers to an appropriate function.
In your case you want something like this:
void MyFunction(void)
{
printf( "0\n" );
}
and then later you can assign to func0:
func0 = &MyFunction;
Note that I am using a different name for the function pointer variable and the actual function.
And now you can call the function, via the function pointer:
func0();
Answer from David Heffernan on Stack OverflowIt is undefined behaviour to de-reference a null pointer. The fix is simply to ensure that the pointer refers to an appropriate function.
In your case you want something like this:
void MyFunction(void)
{
printf( "0\n" );
}
and then later you can assign to func0:
func0 = &MyFunction;
Note that I am using a different name for the function pointer variable and the actual function.
And now you can call the function, via the function pointer:
func0();
I think you are mixing up naming and defining function pointers. I'll just point out that if you write
void func0(void) { printf( "0\n" ); }
void (*func0)(void);
you actually have two completely unrelated objects with the same name func0. The first func0 is a function, the second func0 is a variable with type pointer-to-function.
Assuming you declared your variable func0 globally (outside of any function), it will be automatically zero initialized, so the compiler will read your line
void (*func0)(void);
as
void (*func0)(void) = NULL;
So the variable func0 will be initialized with the value NULL, and on most systems NULL will actually be 0.
Your debugger is now telling you that your variable func0 has the value 0x0000, which is 0. So this is really no big surprise.
To your question regarding a "fix" - well, I assume you want a function pointer, pointing to your function func0, so you can do the following:
void func0(void) { printf( "0\n" ); }
void (*pFunc)(void) = func0;
or even better (although on most compilers not necessary) you can write
void (*pFunc)(void) = &func0;
so you initialize your variable pFunc (I highly recommend renaming it!) to point to func0. A bit more precise: You take the adress &... of the function func0 and assign this value to your variable pFunc.
Now you can "call" the function pointer (which means to call the function which the function pointer points to) by:
pFunc(); //will call function func0
In C and C++, this is called undefined behaviour, meaning that this can lead to a Segmentation fault, nothing or whatever such a case will cause based on your compiler, the operating system you're running this code on, the environment (etc...) means.
Initializing a pointer to a function, or a pointer in general to NULL helps some developers to make sure their pointer is uninitialized and not equal to a random value, thereby preventing them of dereferencing it by accident.
What happnes when u try to access NULL? Following is true about data as well as code, and this is what happens when you try to read NULL(or any address from 0 to 4096,i.e atleast first page of segment). Root cause of this lies in OS and microprocessor segmentation/paging architecture
When you try to access NULL( or 0) address, in any of data or code section, it causes segmentation fault(which is actually a killer page fault). First page of section is treated as out of( or invalid part of) virtual address space. That is purposefully that first page is kept invalid( or not present) so atleast one address that pointer contains could be represented as invalid in program at execution time.
Page descriptor of the 1st page(which contains virtual address 0, NULL), has first bit "present" as 0 (means its invalid page). Now if you try to access NULL pointer(0 address) it will cause to raise a page fault as page is not present, and OS will try to handle this page fault. When page fault handler see that its trying to access 1st page, which is treated as a invalid part of virtual address space it kills the process. This is all about user space process. If you try to access NULL pointer in system process(kernel level code), it will fail your OS an crash the system.
Links: http://en.wikipedia.org/wiki/Page_fault#Invalid http://en.wikipedia.org/wiki/Memory_protection#Paged_virtual_memory http://pdos.csail.mit.edu/6.828/2005/readings/i386/s05_02.htm
Above is sufficient bt as i think u should read this as well http://www.iecc.com/linker/linker04.txt
Why function pointer is initialized to NULL? Although if you try to call the with NULL its going to give page/segment fault. NULL signifies its invalid function. If it contains any garbage address but in valid virtual address space of code section, i think any code at that address will be called, which could be even more disaster(spl in case of real time systems). Initialize funcp = funct_foo_name + 1; now call function using function pointer. Function pointer points to valid virtual address space of code section. bt function will start from incorrect place to execute. which could result into wrong code execution or wrong order.
is there a way to pass NULL to an function in c that requires arguments in c?
What does it mean to do a "null check" in C or C++? - Software Engineering Stack Exchange
Can I reliably set a function pointer to NULL in C and C++? - Stack Overflow
pointers - How do some C functions accept null parameters? - Stack Overflow
Say i have a function "void blabla( int argument )"
if i call it as this: blabla(NULL);
can i then do the following inside the function:
if(argument == NULL){}
?
if so, is there a more straightforward way of doing this?
In C and C++, pointers are inherently unsafe, that is, when you dereference a pointer, it is your own responsibility to make sure it points somewhere valid; this is part of what "manual memory management" is about (as opposed to the automatic memory management schemes implemented in languages like Java, PHP, or the .NET runtime, which won't allow you to create invalid references without considerable effort).
A common solution that catches many errors is to set all pointers that don't point to anything as NULL (or, in correct C++, 0), and checking for that before accessing the pointer. Specifically, it is common practice to initialize all pointers to NULL (unless you already have something to point them at when you declare them), and set them to NULL when you delete or free() them (unless they go out of scope immediately after that). Example (in C, but also valid C++):
void fill_foo(int* foo) {
*foo = 23; // this will crash and burn if foo is NULL
}
A better version:
void fill_foo(int* foo) {
if (!foo) { // this is the NULL check
printf("This is wrong\n");
return;
}
*foo = 23;
}
Without the null check, passing a NULL pointer into this function will cause a segfault, and there is nothing you can do - the OS will simply kill your process and maybe core-dump or pop up a crash report dialog. With the null check in place, you can perform proper error handling and recover gracefully - correct the problem yourself, abort the current operation, write a log entry, notify the user, whatever is appropriate.
The other answers pretty much covered your exact question. A null check is made to be sure that the pointer you received actually points to a valid instance of a type (objects, primitives, etc).
I'm going to add my own piece of advice here, though. Avoid null checks. :) Null checks (and other forms of Defensive Programming) clutter code up, and actually make it more error prone than other error-handling techniques.
My favorite technique when it comes to object pointers is to use the Null Object pattern. That means returning a (pointer - or even better, reference to an) empty array or list instead of null, or returning an empty string ("") instead of null, or even the string "0" (or something equivalent to "nothing" in the context) where you expect it to be parsed to an integer.
As a bonus, here's a little something you might not have known about the null pointer, which was (first formally) implemented by C.A.R. Hoare for the Algol W language in 1965.
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.
int (*pfun) (void) = NULL;
It is actually valid.
The C rules of assignment says that:
(Note that's an initialization here but the same type of constraints and conversions as for simple assignment apply.)
(C99, 6.5.16.1 Simple assignment p1 Constraints) "One of the following shall hold: [...] — the left operand is a pointer and the right is a null pointer constant;"
and
(C99, 7.17p3) "The macros are NULL which expands to an implementation-defined null pointer constant;"
So assigning a null pointer constant to any pointer (object pointer, function pointer or void *) is allowed by C. Note that Plauger's book refers to C89 when he mentions Standard C but the wording of the assignment constraints are the same in C89.
void (*test)() = (void*)0=> produced an invalid conversion error in both gcc and g++
GCC detects the language based on the file extension. Compiling a .cc file with GCC will invoke the C++ compiler, not the C compiler.
Try it with a C source file and you'll see this is accepted. As it should be, as it's allowed by the standard.
If so, why does assigning to NULL work all the time, but assigning to (void*)0 not?
NULL isn' t allowed to be defined as ((void*)0) in C++ mode. In C++ mode, it must be defined as either an integral constant with value 0, or as nullptr. Either can be converted to any function pointer type.
Can I always reliably set a function pointer to NULL in C and C++?
Yes, in any conforming C or C++ implementation this will work.
In some programming languages [...] it is possible to pass a NULL parameter as an argument, but in C I always thought this would result in Undefined Behavior.
Passing a NULL parameter for a pointer by itself does not result in UB; it's attempting to access the memory pointed to by a pointer set to NULL that does.
Passing NULL is a very common practice for situations when something is not specified. The caller is expected to check parameters for NULL before performing the access. For example, the standard lets you pass NULL to free, which makes the function a lot more convenient.
don't
NULLpointers simply point to nothing?
Yes, they do. But that "nothing" is globally well-known, so using a NULL lets you communicate the fact that a pointer points to nothing to functions that you call. In other words, the check
if (myPointer == NULL)
is well-defined*, so you can use it to your advantage.
* Unless you use a dangling pointer, i.e. a pointer that you have freed, or a pointer that points to object that went out of scope. You can prevent the first situation from happening by assigning NULL to every pointer that you free(), and the second situation by declaring pointers in the scope that has the same or higher level of nesting as the scope of an automatic object to which the pointer is pointing.
void func_with_optional_arg(char *optional)
{
if (optional == NULL) {
// do something differently
}
/* ... */
}
Why would that invoke UB? Dereferencing a NULL pointer certainly would, but passing one around does not. NULL is a sentinel value used to determine whether or not a pointer is valid (not that invalid pointers cannot have other values, but we use this one explicitly.) If passing it to a function invoked UB then what would be the point of its existence in the first place?
whereas passing a NULL non-pointer value is not?
There is no such thing as a "NULL non-pointer" in C, so I'm not sure what you mean here.
Actually, you can use a literal 0 anyplace you would use NULL.
Section 6.3.2.3p3 of the C standard states:
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.
And section 7.19p3 states:
The macros are:
NULLwhich expands to an implementation-defined null pointer constant
So 0 qualifies as a null pointer constant, as does (void *)0 and NULL. The use of NULL is preferred however as it makes it more evident to the reader that a null pointer is being used and not the integer value 0.
NULL is used to make it clear it is a pointer type.
Ideally, the C implementation would define NULL as ((void *) 0) or something equivalent, and programmers would always use NULL when they want a null pointer constant.
If this is done, then, when a programmer has, for example, an int *x and accidentally writes *x = NULL;, then the compiler can recognize that a mistake has been made, because the left side of = has type int, and the right side has type void *, and this is not a proper combination for assignment.
In contrast, if the programmer accidentally writes *x = 0; instead of x = 0;, then the compiler cannot recognize this mistake, because the left side has type int, and the right side has type int, and that is a valid combination.
Thus, when NULL is defined well and is used, mistakes are detected earlier.
In particular answer to your question “Is there a context in which just plain literal 0 would not work exactly the same?”:
- In correct code,
NULLand0may be used interchangeably as null pointer constants. 0will function as an integer (non-pointer) constant, butNULLmight not, depending on how the C implementation defines it.- For the purpose of detecting errors,
NULLand0do not work exactly the same; usingNULLwith a good definition serves to help detect some mistakes that using0does not.
The C standard allows 0 to be used for null pointer constants for historic reasons. However, this is not beneficial except for allowing previously written code to compile in compilers using current C standards. New code should avoid using 0 as a null pointer constant.
In C, NULL is a macro that expands either to 0 or (void*)0 (or something that has a similar effect).
In the first case, you can not differentiate between NULL and 0, because they are literally the same.
In the second case, your code will cause a compile error, because you can't compare an integer variable with a pointer.
First some background ...
The macros are
NULLwhich expands to an implementation-defined null pointer constant; C11 §7.19 3
NULL typically is an integer constant 0 or (void*)0 or the like. It may have a different implementation or type - It could be ((int*) 0xDEADBEEF) as strange as that may be.
NULL might be type int. It might be type void * or something else. The type of NULL is not defined.
When the null pointer constant NULL is cast to any pointer, is is a null pointer. An integer 0 cast to a pointer is also a null pointer. A system could have many different (bit-wise) null pointers. They all compare equally to each other. They all compare unequally to any valid object/function. Recall this compare is done as pointers, not integers.
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. C11 §6.3.2.3 3
int x;
if (&x == NULL) ... // this is false
So after all that chapter and verse how to distinguish NULL from 0?
If the macro NULL is defined as an int 0 - it is game over - there is no difference between 0 and NULL.
If NULL is not an int, then code can use _Generic() to differentiate NULL and 0. This does not help OP's "Any change made can only be made within the function itself." requirement as that function accepts an int augment.
If NULL is an int that has a different bit-pattern than 0, then a simple memcmp() can differentiate.
I suspect the whole reason for this exercise is to realize there is no portable method to distinguish NULL from 0.
Maybe there are some basic things you should rethink:
First, only pointers can be NULL, but not objects. Hence, if you return an object of type struct Stack (which is not a pointer), you cannot return NULL but just an instance of struct Stack.
Second, passing in and returning an object of struct Stack by value will result in copying the respective object; I think that passing references or pointers would be a better choice; and - if you pass in and return a pointer, you could also return NULL to indicate a full stack or some other issue.
The problem is that your function must return a value that has the type Stack.
The code you provided doesn't define the type of NULL, but, since you're not seeing another error and you're assigning it to node, I would guess that the type of NULL is StackNode *... or, at least, something compatible with that.
So, there's your problem. You're trying to return something with the type StackNode * when your function claims to return a Stack.
Your best bet is to redesign this function that returns the result of the push operation and not the Stack itself.