Null pointer, segfault, I fell here for this interview!

Interviewer: Sweaty, the interview must be a long way, right?

 

Fortunately, for less than two hours riding

 

Interviewer: Let’s drink a glass of water first.

 

Wow, thank you, Gulong Gulong drink half a cup

 

Interviewer: Let's start, and see that you have done a lot of projects. It's not bad. Let's talk casually.

 

Wow, "This interviewer is not bad, it feels like a show"

 

Interviewer: What is the nature of NULL pointer, is it the same as 0?

 

Hmm, this, isn't NULL equal to 0?

 

 

Interviewer: Are you sure? With a smile, calm eyes...

 

Hmm, it should be,,, isn't it, sweat is starting to rise again...

 

Interviewer: Yes, I understand, don't rush to drink water slowly, I will go to the toilet first.

 

The moisture and saliva are intertwined with each other. I rode for two hours and interviewed for 3 minutes. This time I am here.

 

The standard definition of NULL in C/C++

Standard definition of NULL

#if !defined(NULL) && defined(__NEEDS_NULL)
#ifdef _cplusplus      
#define NULL 0         // 这里对应C++的情况
#else
#define NULL (void *)0 // 这里对应C语言的情况
#endif

The compiler defines a macro in advance _cplusplusto determine whether the current compilation environment is C++ or C language, which is defined as 0 in C++ and as defined in C language (void *)0.

Difference in C/C++

In the C language, the "standard" writing in C, NULL is replaced with a void*type of pointer rvalue, the value is equal to 0; because it is of void* type, it can be implicitly converted to other types of pointers.

In C++, void* cannot be implicitly converted to other types of pointers freely, and the literal 0 can be implicitly converted to pointer types.

What is the nature of NULL

We start with pointers, null pointers, null pointer constants and the memory pointed to

From a pointer point of view

We look at the following definition, p is a local variable in a function, then the value of p is random, that is, p is a wild pointer.

int func()
{
  int *p; 
  ...
}

Look at the following function again, p is a local variable, the address allocated on the stack, the value of p is (void *)0, in fact 0x00000000, it means that the pointer p points to the 0x00000000address of the memory . At this time, p is not a wild pointer.

int func()
{
  int *p = NULL; 
  ...
}

What is a null pointer?

If you convert a null pointer constant to a pointer type, it is guaranteed that the generated pointer (called a null pointer) will compare unequal values ​​with pointers to any object or function.

After definition char *p=0, after any assignment operation of p, p becomes a null pointer, that is, p does not point to any actual object or function. Conversely, the address of any object or function cannot be a null pointer.

What is a null pointer constant?

An integer constant expression with a value of 0, or void *an expression that is cast to a type, is called a null pointer constant

Where does the null pointer point to the memory

The standard is not defined here, it depends on the implementation of the system. Our common null pointers generally point to 0x00000000addresses, that is, the internals of the null pointers 0x00000000are represented by all , and some systems use some special address values ​​or special ways to represent the null pointer.

When we actually write code, the key point is to determine which is a null pointer.

What does NULL do

In most CPUs, the memory 0x00000000address is not accessible at will, so the wild pointer points to this area to ensure that the wild pointer has a home, otherwise a segmentation fault will occur.

It will block you when you try to access, but some addresses are not read-only. If a pointer points to this address and you inadvertently modify it, it may cause some important files to be modified, so the pointer is initialized to NULL It is necessary.

Be careful not to mix'\0' and '0' and 0 and NULL

  • '\0' is an escape character, and its corresponding ASCII code value is 0, which is essentially 0; it is often used to indicate the end of a string to determine whether the string ends.

  • '0' is a character, and its corresponding ASCII code value is 48, which is essentially 48.

  • 0 is an int type number, which is essentially 0.

  • NULL is an expression, which is a type of forced conversion to void *type 0, which is generally used to compare whether the pointer is a wild pointer.

Is NULL 0?

NULL is 0?

Let's first look at the following code:

//https://tool.lu/coderunner/
#include<stdio.h>
int main()
{    
  int *p=NULL;    
  printf("%s",p); 
}

The results are as follows:

Output (null), in execution int *p=NULL, print out blank, in fact the value of p 0x00000000, in C language, the essence of NULL is 0, but this 0 is not parsed as an integer data, but as a memory address to parse , Which represents the 0 address of the memory.

(void *)0This overall expression represents a pointer. Where the address is depends on the pointer variable itself. This pointer variable points to address 0 (actually a section of memory starting at address 0).

NULL is not 0?

If a pointer is assigned NULL, it is equivalent to that the pointer executes the 0x00000000logical address, but the logical address 0x0000 in C language cannot be used by users, so when you try to get the contents of a pointer that points to NULL, you will be prompted Segmentation fault, test the code as follows:

//https://tool.lu/coderunner/
//来源:技术让梦想更伟大
//作者:李肖遥
#include<stdio.h>
int main()
{    
 
 int *node = NULL;
 int p = 0;
 p = *node;
 printf("%d\n",p);
 
 return 0;
}

The compilation result is as follows:

Since the pointer node executes NULL, which is a logical address 0x00000000, and this address cannot be accessed, the compiler prompts a segmentation error.

Do you think NULL is still 0 when you see this? According to the macro definition, we know that: it (void *)0means that the value 0 is forced into a void *type, so the final operation result is 0.

When a variable is defined, the system will allocate memory space for it. The same is true for pointer variables. If the pointer does not point to it, the address is a random value. If it is used carelessly, it will cause data errors and cause the program to exit.

NULL makes the pointer p point to the address 0x00000000, which will be 0x00000000used as an unused address in most systems , so using p will not destroy the data.

But there are also systems that use addresses 0x00000000and define NULL as other values, so do not equate NULL with 0.

Let’s look at the way we pass by value. There is an interview question on the Internet. Here I refer to the code to help you understand it better. The code is as follows:

//https://tool.lu/coderunner/
//来源:技术让梦想更伟大
//作者:李肖遥
#include <stdio.h>

void vPassByFun(int *node)
{
    static int N = 1024;
    node = &N;
}

int main()
{
 
    int *node = NULL;
    int p = 0;
    vPassByFun(node);
    p = *node;
 
    printf("%d\n",p);
    
    return 0;
}

The output is as follows:

vPassByFun函数It is value transfer, and the value of the node pointer variable is not affected, so the effect of this program and the result of the previous program are both segfaults.

If you want the result to be 1024, how should you write the code? Let's write the code like this:

//https://tool.lu/coderunner/
//来源:技术让梦想更伟大
//作者:李肖遥
#include <stdio.h>

void vPassByFun(int ** node)
{
    static int N = 1024;
    *node=&N;
}

int main()
{
 
    int *node = NULL;
    int p = 0;

    vPassByFun(&node);
    p = *node;

    printf("%d\n",p);
 
    return 0;

}

The results are as follows:

Passing a secondary pointer means passing the pointer of the node pointer variable to vPassByFun函数, in this case the result is correct.

At last

During the coding process, we need to be responsible for our own pointers, and it is this kind of detail that often leads to bugs or not finding the location of the problem. Finally, originality is not easy, I hope to correct the mistakes in the article, and leave more comments, thank you.

Guess you like

Origin blog.csdn.net/u012846795/article/details/107853299