I am wondering how would I deal with a call to a function when an integer is passed into a function that accepts a pointer? In my case hasPlayedInTeam() accepts a pointer to Team, however, received an int. This causes the Q_ASSERT to hang.
In addition, is my problem also known as a null pointer? My professor has used that term several times in lecture, but I am not sure what he was referring to.
//main.cpp
Person p1("Jack", 22, "UCLA");
Q_ASSERT(p1.hasPlayedInTeam(0) == false);
//person.cpp
bool Person::hasPlayedInTeam(Team *pTeam) {
bool temp = false;
foreach (Team* team, teamList) {
if (team->getName() == pTeam->getName() {
temp = true;
}
}
return temp;
}
In your call:
p1.hasPlayedInTeam(0)
the integer literal 0 is converted to a NULL pointer. So, you are not actually "receiving" an integer; you are passing an integer, the compiler can automatically cast it to the null pointer (given the definition for NULL).
I think you can fix the definition of hasPlayedInTeam by either asserting that its argument is not NULL, or by returning a default value when NULL is passed in:
//person.cpp
bool Person::hasPlayedInTeam(Team *pTeam) {
assert(pTeam!=NULL); //-- in this case, your program will assert and halt
or:
//person.cpp
bool Person::hasPlayedInTeam(Team *pTeam) {
if (pTeam == NULL)
return false; //-- in this case, your program will not assert and continue with a sensible (it actually depends on how you define "sensible") return value
Yes, it sounds like your problem is a null pointer. A null pointer means that you have a pointer which isn't actually pointing to anything:
Team* team = NULL;
It so happens that in C++ NULL is a macro for the integer 0. Stroustrup has some comments on which one he prefers to use in code.
Function hasPlayedInTeam() looks for the argument of type "Team" whereas you are passing the argument of type "integer" which is wrong....
Yes, I think that you are referring to a null pointer in that situation.
To treat the case when an int is passed, you can overload the function and make it behave as you want it to do, when an int is passed.
In C++ there is NULL which is defined as 0 (in some standard header file, cstddef I think) so yes the integer you are passing is the null pointer. 0 is the only (as far as I know) integer that will automatically (implicitly) be converted to a pointer of whatever type is needed.
In practice, I think most people prefer to use NULL instead of 0 for the null pointer.
I'm not sure why it is hanging however, dereferencing the NULL pointer (in your statement pTeam->getName()) should cause the program to crash if you pass it NULL, not just hang.
Unfortunately the null pointer literal is one of the confused parts of the language. Let me try to recap:
For any type there is the concept of "pointer to that type". For example you can have integers and pointer to integers (int x; int *y;), doubles and pointer to doubles (double x; double *y;), Person and pointer to Person (Person x,*y;). If X is a type then "pointer to X" is a type itself and therefore you can even find pointers to pointers to integers (int **x;) or pointers to pointers to pointers to chars (char ***x;).
For any pointer type there is a null pointer value. It's a value that doesn't really point to an object, so it's an error to try to dereference it ("dereferencing" a pointer means reading or writing the object that is being pointed to). Note that the C++ language doesn't guarantee that you will get a message or a crash when you use a null pointer to get try to get to a non-existent pointed object but just that you should not do it in a program because consequences are unpredictable. The language simply assumes you are not going to do this kind of error.
How is the null pointer expressed in a program? Here comes the tricky part. For reasons that are beyond comprehension the C++ language uses a strange rule: if you get any constant integer expression with value zero then that can be (if needed) considered to be a null pointer for any type.
The last rule is extremely strange and illogical and for example means that
char *x = 0; // x is a pointer to char with the null pointer value (ok)
char *y = (1-1); // exactly the same (what??)
char *z = !! !! !! !! !! !!
!!! !! !! !! !! !!
!!!! !! !! !! !! !!
!! !! !! !! !! !! !!
!! !!!! !! !! !! !!
!! !!! !! !! !! !!
!! !! !!!!!! !!!!!!! !!!!!!1; // Same again (!)
and this is true for any pointer type.
Why is the standard mandating that any expression and not just a zero literal can be considered the null pointer value? Really no idea.
Apparently Stroustrup also found the thing amusing instead of disgusting like it should be (the last example with the "NULL" text written with an odd number of negations is present on "The C++ Programming Language" book).
Also note that there is a NULL symbol defined in standard headers that provide a valid definition for a null pointer value for any type. In "C" a valid definition could have been (void *)0 but this is not valid in C++ because void pointers cannot be converted implicitly to other pointer types like they do in "C".
Note also that you may find in literature the term NUL (only one L) but this is the ASCII character with code 0 (represented in C/C++ with '\0') and is a logically distinct thing from a pointer or an integer number.
Unfortunately in C++ characters are integers too and therefore for example '\0' is a valid null pointer value and the same goes for ('A'-'A') (they are integer constant expressions evaluating to zero).
C++11 increases complexity of these already questionable rules with std::nullptr_t and nullptr. I cannot explain those rules because I didn't understand them myself (and I'm not yet 100% sure I want to understand them).
Related
Does both NULL and nullptr point to same address or NULL points to nowhere?
(I have seen in many places that nullptr points to zero address where memory is inaccessible)
It might be useful to clear up some terminology. A pointer points to an object. The value of a pointer is an address value. There is a special address value for pointers that do not point to an object. We call such pointers "null pointers". When you assign the NULL or nullptr values to a pointer, it becomes a null pointer.
Since all null pointers compare equal, static_cast<void*>(NULL) == static_cast<void>(nullptr).
First of all, nullptr is C++09 addition (well, it was included in C++0x which was going to be released somewhere that time and ended up as C++11). So prior to this there was no nullptr and NULL was all you had.
The whole point was to make null values unambiguous. There is no guarantee that NULL is 0. It may be 0L for example. It can also be 42. Passing it to overloaded functions could cause unexpected behavior. To avoid such ambiguity the new strongly typed nullptr was introduced and now you can create overloads or even templates precisely to handle this case. Now you can overload your constructor.
http://coliru.stacked-crooked.com/a/7faac5903a02e365
#include <iostream>
void func(int* ptr)
{
std::cout << "ptr" << std::endl;
}
void func(size_t size)
{
std::cout << "size" << std::endl;
}
void func(std::nullptr_t)
{
std::cout << "nullptr" << std::endl;
}
int main()
{
int myValue(10);
func(myValue);
func(&myValue);
func(nullptr);
// Good luck with this
// func(NULL);
}
To be precise here, NULL is constant literal that is implicitly convertible to any pointer and has null pointer value. The same applies to nullptr, so in both cases you are guaranteed that they will produce pointer with null pointer value. It does not mean that it is 0 and technically it does not even guarantee that it will be the same value, at least I did not find a proof that there has to be just one null pointer value. Obviously it would be ridiculous to implement more than one of them but if it's not specified, it's not guaranteed. In any modern implementation the pointer created from NULL and nullptr will point to the same null pointer value address which is treated by compiler differently from any other, presumably valid address.
Most of all, nullptr does not have a value. It can't be converted to any number, it can only be converted to any pointer type. You can't say that nullptr is zero because it is not. It converts to any pointer type which then converted to numeric value will be null pointer value whatever it is on given platform/compiler.
NULL is just a pre-processor constant for 0. And because address is a number, the address 0 is reserved for a 'bad' address. But nothing stops you from assigning NULL to any number variable since it will be replaced with 0. A nullptr is a special constant, that will only work with pointers. But it's essentially pointer-only constant for 0.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have just started using c++ and saw that their is a null value for pointers. I am curious as to what this is used for. It seems like it would be pointless to add a pointer to point to nothing.
Well, the null pointer value has the remarkable property that, despite it being a well-defined and unique constant value, the exact value depending on machine-architecture and ABI (on most modern ones all-bits-zero, not that it matters), it never points to (or just behind) an object.
This allows it to be used as a reliable error-indicator when a valid pointer is expected (functions might throw an exception or terminate execution instead), as well as a sentinel value, or to mark the absence of something optional.
On many implementations accessing memory through a nullpointer will reliably cause a hardware exception (some even trap on arithmetic), though on many others, especially those without paging and / or segmentation it will not.
Generally it's a placeholder. If you just declare a pointer, int *a;, there's no guarantee what is in the pointer when you want to access it. So if your code may or may not set the pointer later, there's no way to tell if the pointer is valid or just pointing to garbage memory. But if you declare it as NULL, such as int *a = NULL; you can then check later to see if the pointer was set, like if(a == NULL).
Most of the time during initialization we assign null value to a pointer so that we can check whether it is still null or a address has been assign to it or not.
It seems like it would be pointless to add a pointer to point to
nothing.
No, it is not. Suppose you have a function returning optional dynamically allocated value. When you want to return "nothing" you return null. The caller can check for null and distinguish between 2 different cases: when the return value is "nothing" and when the return value is some valid usable object.
null value in C and C++ is equal to 0. But nullptr in C++ is different from it, nullptr is always a pointer type in C++. We assign a null value to a pointer variable for various reason.
To check whether a memory has been allocated to the pointer or not
To neutralize a dangling pointer so that it should not create any side effect
To check whether a return address is a valid address or not etc.
Most of the time during initialization we assign null value to a pointer so that we can check whether it is still null or a address has been assign to it or not.
Basically, pointers are just integers. The null pointer is a pointer with a value of 0. It doesn't strictly point to nothing, it points to absolute address 0, which generally isn't accessible to your program; dereferencing it causes a fault.
It's generally used as a flag value, so that you can, for example, use it to end a loop.
Update:
There seem to be a lot of people confused by this answer, which is, strictly, completely correct. See C11(ISO/IEC 9899:201x) §6.3.2.3 Pointers Section 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.
So, what's an address? It's a number n where 0 ≤ n ≤ max_address. And how do we represent such a number? Why, it's an integer, just like the standard says.
The C11 standard makes it clear that there's never anything to reference at address 0, because in some old pathologically non-portable code in BSD 4.2, you often saw code like this:
/* DON'T TRY THIS AT HOME */
int
main(){
char target[100] ;
char * tp = &target ;
char * src = "This won't do what you think." ;
void exit(int);
while((*tp++ = *src++))
;
exit(0);
}
This is still valid C:
$ gcc -o dumb dumb.c
dumb.c:6:12: warning: incompatible pointer types initializing 'char *' with an
expression of type 'char (*)[100]' [-Wincompatible-pointer-types]
char * tp = &target ;
^ ~~~~~~~
1 warning generated.
$
In 4.2BSD on a VAX, you could get away with that nonsense, because address 0 reliably contained the value 0, so the assignment evaluated to 0, which is of course FALSE.
Now, to demonstrate:
/* Very simple program dereferencing a NULL pointer. */
int
main() {
int * a_pointer ;
int a_value ;
void exit(int); /* To avoid any #includes */
a_pointer = ((void*)0);
a_value = *a_pointer ;
exit(0);
}
Here's the results:
$ gcc -o null null.c
$ ./null
Segmentation fault: 11
$
I searched in the web but couldn't find a reliable answer.
And what would
someclass* ptr = 1;
char* charptr = 2;
or assigning them to any other integer mean?
What happens if I don't initialize pointers (for native data pointers as well as class pointers) before using them?
Setting a pointer to 0 is equivalent to setting it to NULL. However, this is only true for a constant expression 0, i.e. for compile-time zero value. Trying to set a pointer to a run-time zero value is not guaranteed to produce a null pointer
int *pi = 0; // Initializes a null pointer
char *pc = 2 - 2; // Initializes a null pointer
short *ps = sizeof *pc - 1; // Initializes a null pointer
int x = 0;
double *pd = (double *) x;
// Implementation-defined, not guaranteed to produce a null pointer
You can explore the matter in greater detail C FAQ
To answer the second part of your question:
It is illegal to assign any other integer (besides literal/constant 0) to a pointer. Neither of your initializations (or assignments) will compile. It is illegal in both C and C++, although C compilers are historically more permitting in this regard, responding with a warning instead of refusing to compile the code.
Also, in C++ language there's no difference of how pointers to class types are treated. Pointer to class types are still considered scalar types and behave in this regard the same way as any pointer to a fundamental type does.
Yes, in C++ NULL is defined to be 0. Setting a pointer to some other small integer value would mean it pointed to a -- likely illegal -- portion of the computer's memory (but it wouldn't be considered a NULL pointer).
If you don't initialize a global pointer it will be set to zero (NULL) for you just before the program starts. If you don't initialize pointer variables declared on the stack (i.e. as within functions or methods) they will have garbage in them. Likewise, the contents of any dynamically allocated pointer or any contained in an object as a data member also will have no predefined value. Some compilers have extensions that allow requests for dynamically allocated memory to be initially zeroed, like C's calloc() function does for raw memory.
I encountered a problem in c++. I read some codes,but there was a very wired usage of pointer. The code is following:
double* marginalProbability =
new double [10 * sizeof(marginalProbability[0])];
memset( marginalProbability, 0, 10 * sizeof(double) );
//................
//.................
if(marginalProbability>0)
printf("larger");
else
printf("smaller");
The question I'm asking is what does it mean that if(marginalProbability>0). It is a pointer greater than zero. I think that in a normal compiler, there are no addresses which will be equal to zero. Or are there any other meanings of that? Otherwise, this line seems meaningless. Thanks.
I think that's a bug and the original author meant something like:
if(marginalProbability[0]>0)
printf("larger");
else
printf("smaller");
I don't see why they would test if marginalProbability was valid if they have already called memset() on it unconditionally. Also the use of the words larger and smaller indicate a comparison of a value, not a pointer.
The NULL pointer is treated as if it were zero. That being said, this code is probably just wrong, as the comparison is guaranteed to be true (since memset would have crashed if the pointer was NULL).
In this case, 0 is being interpreted as a null pointer constant.
You can compare two pointers, but the result is unspecified unless they point to two elements of the same array; so that code is well-formed but meaningless.
I suspect the code is supposed to compare a probability value, *marginalProbability or marginalProbability[i], with zero. If it's intended to check whether the allocation succeeded, then it's wrong for three reasons:
it would have to use !=, since the result of > is unspecified;
it would have to be done before memset();
it would only be necessary if the allocation used new (std::nothrow); plain new throws std::bad_alloc on failure.
a pointer with the value of zero is a null pointer. A pointer to nothing. Checking that it is not zero (p!=0 is more common that p>0 although p!=nullptr is most correct) means that it is not null.
The code you have listed is also wrong. if the new operation fails it will not return a null pointer but throw an exceptions which will no be caught.
this is what it should be.
try{
std::vector<double> marginalProbability (10, 0.0);
}catch(const std::bad_alloc& e){
std::cerr << "no memory" << std::endl;
}
There are pointers which are 0. They are explicitly the "null" pointer which points to no current valid object. However, using </>in this case is pretty meaningless- there's no such thing as the 1 pointer, for example.
Also, that's C code pretending to be C++.
What is the meaning of
*(int *)0 = 0;
It does compile successfully
It has no meaning. That's an error. It's parsed as this
(((int)0) = 0)
Thus, trying to assign to an rvalue. In this case, the right side is a cast of 0 to int (it's an int already, anyway). The result of a cast to something not a reference is always an rvalue. And you try to assign 0 to that. What Rvalues miss is an object identity. The following would work:
int a;
(int&)a = 0;
Of course, you could equally well write it as the following
int a = 0;
Update: Question was badly formatted. The actual code was this
*(int*)0 = 0
Well, now it is an lvalue. But a fundamental invariant is broken. The Standard says
An lvalue refers to an object or function
The lvalue you assign to is neither an object nor a function. The Standard even explicitly says that dereferencing a null-pointer ((int*)0 creates such a null pointer) is undefined behavior. A program usually will crash on an attempt to write to such a dereferenced "object". "Usually", because the act of dereferencing is already declared undefined by C++.
Also, note that the above is not the same as the below:
int n = 0;
*(int*)n = 0;
While the above writes to something where certainly no object is located, this one will write to something that results from reinterpreting n to a pointer. The mapping to the pointer value is implementation defined, but most compilers will just create a pointer referring to address zero here. Some systems may keep data on that location, so this one may have more chances to stay alive - depending on your system. This one is not undefined behavior necessarily, but depends on the compiler and runtime-environment it is invoked in.
If you understand the difference between the above dereference of a null pointer (only constant expressions valued 0 converted to pointers yield null pointers!) and the below dereference of a reinterpreted zero value integer, i think you have learned something important.
It will usually cause an access violation at runtime. The following is done: first 0 is cast to an int * and that yields a null pointer. Then a value 0 is written to that address (null address) - that causes undefined behaviour, usually an access violation.
Effectively it is this code:
int* address = reinterpret_cast<int*>( 0 );
*address = 0;
Its a compilation error. You cant modify a non-lvalue.
It puts a zero on address zero. On some systems you can do this. Most MMU-based systems will not allow this in run-time. I once saw an embedded OS writing to address 0 when performing time(NULL).
there is no valid lvalue in that operation so it shouldn't compile.
the left hand side of an assignment must be... err... assignable