NULL Pointer (NULL, 0), wild pointer, void *

Source: Internet
Author: User
Tags define null

I. Wild pointer

The "wild pointer" is not a NULL pointer, but a pointer to the "junk" memory.

There are two main causes of "wild pointer:

(1) pointer variables are not initialized. When a pointer variable is created, it does not automatically become a NULL pointer. Its default value is random, which means it is random. Therefore, the pointer variable should be initialized at the same time when it is created, either set the pointer to NULL or set it to direct to the legal memory. For example
    Char * p = NULL;
    Char * str = (char *) malloc (100 );

(2) After the pointer p is free or deleted, It is not set to NULL, which makes people mistakenly think p is a valid pointer.

Free and delete only release the memory indicated by the pointer, but they do not kill the pointer itself. After free, the address remains unchanged (not NULL), but the memory corresponding to the address is junk, and p becomes a "wild pointer ". If p is not set to NULL at this time, it is mistaken that p is a valid pointer.
If the program is long, we sometimes cannot remember whether the memory referred to by p has been released. Before using p, the statement if (p! = NULL. Unfortunately, the if statement does not prevent errors at this time, because even if p is not a NULL pointer, it does not point to a valid memory block.

    Char * p = (char *) malloc (100 );
    Strcpy (p, "hello ");
    Free (p );       // The Memory indicated by p is released, but the address indicated by p remains unchanged.
    ...
     If (p! = NULL)    // Error prevention
    {
       Strcpy (p, "world ");    // Error
}

(3) pointer operations go beyond the scope of variables. This situation is hard to prevent. The example program is as follows:
    Class
{     
Public:
    Void Func (void) {cout <"Func of class A" <endl ;}
};
    Void Test (void)
{
    A * p;
          {
                A;
                P = &;    // Note the life cycle of
}
          P-> Func ();          // P is a "wild pointer"
}

When the function Test executes the statement p-> Func (), object a has disappeared, and p points to a, so p becomes a "wild pointer ".

2: NULL pointer/0/NULL

A null pointer is a pointer with a value of 0. Its value is 0 before it is initialized.

NULL is a standard macro definition used to represent NULL pointer constants.

# Define NULL 0 Or

# Define NULL (void *) 0)

Judge whether a pointer is a null pointer:

F (! P) andIf (p = NULL), if (NULL = p)

It is best to use the last two types. Some platforms do not use 0 for NULL, and the program will be faulty at this time.

Among them, if (NULL = p) and if (p = NULL) are no different. The previous one is to avoid incorrect writing (the latter is easy to write P = NULL, which cannot be found by the compiler. The previous NULL = p will not be compiled ).

Generally, before using a pointer (especially adding or subtracting it), you need to judge if (p = NULL ),Such as the address returned by the function for non-null judgment.

For example:

Item * pItem = itemList. getItem (index );

Item * ItemList: getItem (int index)
{
  If (index <0) return NULL;
  If (index> = size () return NULL;
  Return _ list [index];
}
If a null pointer is returned and related operations are performed on the pItem, a null pointer exception occurs and the program may crash.

 

After the free (p) function is called, p should be NULL, that is, p = NULL.

 

3: VOID type

Void literally means "no type", void * is "no type Pointer", and void * can point to any type of data.

Void has almost only "Comments" and restrictions on the role of the program, because no one will ever define a void variable, let's try to define:

Void;

An error occurs when compiling this line of statements, and the message "illegal use of type 'void'" is displayed '". However, even if the compilation of void a does not go wrong, it has no practical significance.
Void actually plays the following role:
(1) Restrictions on function return;
(2) Restrictions on function parameters.

As we all know, if the pointer p1 and p2 are of the same type, we can directly assign values to each other between p1 and p2. If p1 and p2 point to different data types, you must use the forced type conversion operator to convert the pointer type on the right of the value assignment operator to the pointer type on the left.
For example:

Float * p1;
Int * p2;
P1 = p2;

The p1 = p2 statement will cause compilation errors and the prompt "'=': cannot convert from 'int * 'to 'float *'" must be changed:

P1 = (float *) p2;

Void * is different. pointers of any type can be directly assigned to it without forced type conversion:

Void * p1;
Int * p2;
P1 = p2;

However, this does not mean that void * can also be assigned to other types of pointers without force type conversion. Because "No type" can tolerate "type", while "type" cannot tolerate "No type ". The principle is simple. We can say that "both men and women are people", but not "people are men" or "people are women ". The following statement compilation error:

Void * p1;
Int * p2;
P2 = p1;

The message "'=': cannot convert from 'void * 'to 'int *' is displayed *'".

The following describes the rules for using the void Keyword:
Rule 1 if the function does not return a value, the void type should be declared.
In C language, any function without a limited return value type will be processed by the compiler as the return integer value. However, many programmers mistakenly think it is of the void type. For example:

Add (int a, int B)
{
Return a + B;
}
Int main (int argc, char * argv [])
{
Printf ("2 + 3 = % d", add (2, 3 ));
}

The program running result is output:
2 + 3 = 5
This indicates that the function without return values is indeed an int function.

  "High Quality C/C ++ programming" mentioned: "The C ++ language has strict type security checks and does not allow the above situation (that is, the function does not add a type declaration ". However, the compiler does not necessarily think so. For example, in Visual C ++ 6.0, the compilation of the add function is error-free and has no warning and runs correctly, therefore, we cannot expect the compiler to perform strict type checks.

Therefore, in order to avoid confusion, when writing C/C ++ programs, you must specify the type of any function. If the function does not return a value, it must be declared as void. This is both a need for good program readability and a requirement for standardized programming. In addition, after adding the void type declaration, you can also use the "self-annotation" function of the Code. The "self-annotation" of the code means that the code can annotate itself.

Rule 2 If the function has no parameters, the parameter should be declared as void
Declare a function in C ++:

Int function (void)
{
Return 1;
}

The following call is invalid:

Function (2 );

In C ++, the function parameter void means that this function does not accept any parameters.

We compile in Turbo C 2.0:

# Include "stdio. h"
Fun ()
{
Return 1;
}
Main ()
{
Printf ("% d", fun (2 ));
Getchar ();
}

Compiling is correct and 1 is output. In C, parameters of any type can be transferred to a function without parameters. However, compiling the same code in C ++ compiler will cause an error. In C ++, no parameters can be transferred to a function without parameters. If an error occurs, the system prompts "'fun ': function does not take 1 parameters ".
Therefore, whether in C or C ++, if the function does not accept any parameters, you must specify the parameter as void.

Rule 3 be careful when using the void pointer type

According to the ANSI (American National Standards Institute) standard, you cannot perform algorithm operations on the void pointer, that is, the following operations are invalid:

Void * pvoid;
Pvoid ++; // ANSI: Error
Pvoid + = 1; // ANSI: Error
// The ANSI standard determines this because it insists that the pointer to the algorithm operation must be determined to know the data type it points.
// Example:
Int * pint;
Pint ++; // ANSI: Correct

The result of pint ++ is to increase sizeof (int ).

However, the well-known GNU (GNU's Not Unix abbreviation) does Not recognize this as it specifies that the void * algorithm operation is consistent with char.

Therefore, the following statements are correct in the GNU Compiler:

Pvoid ++; // GNU: Correct
Pvoid + = 1; // GNU: Correct

The execution result of pvoid ++ is increased by 1.
In actual programming, to cater to ANSI standards and improve program portability, we can write code that implements the same function as below:

Void * pvoid;
(Char *) pvoid ++; // ANSI: Correct; GNU: Correct
(Char *) pvoid + = 1; // ANSI: error; GNU: Correct

Rule 4 if the function parameter can be a pointer of any type, the parameter should be declared as void *

Typical function prototypes for memory operation functions such as memcpy and memset are:

Void * memcpy (void * dest, const void * src, size_t len );
Void * memset (void * buffer, int c, size_t num );


In this way, any type of pointer can be passed into memcpy and memset, which truly reflects the significance of the memory operation function, because the object it operates on is only a piece of memory, no matter what kind of memory this piece is. If the parameter types of memcpy and memset are not void * But char *, it is really strange! Such memcpy and memset are obviously not "pure, out of low-level interests" functions!

The following code is correctly executed:

// Example: memset accepts any type of pointer
Int intarray [100];
Memset (intarray, 0,100 * sizeof (int); // clear intarray 0
// Example: memcpy accepts any type of pointer
Int intarray1 [100], intarray2 [100];
Memcpy (intarray1, intarray2, 100 * sizeof (int); // copy intarray2 to intarray1

Interestingly, the memcpy and memset functions also return the void * type. how knowledgeable are the compilers of the standard library functions!

Rule 5 void cannot represent a real Variable

The following code tries to make void represent a real variable, so it is all wrong code:

Void a; // Error
Function (void a); // Error

Void represents an abstraction in which all variables in the world are "typed". For example, a person is either a man or a woman (or a demon ?).
The emergence of void is only for an abstract need. If you have understood the concept of "abstract base class" in object-oriented, it is easy to understand the void data type. Just as we cannot define an instance for an abstract base class, we cannot define a void (let's say that void is an abstract data type) variable.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.