The Road to C Language Learning (Basics) - Memory Management

Note: This blog is written word by word by the blogger, which is not easy. Please respect the originality, thank you all!

Scope

CThe scope of language variables is divided into:

  • code block scope (a code block is a section of code between {})
  • function scope
  • file scope

1) Local variables

Life cycle: when to open up space (birth) and release space (death), this process is called life cycle.
Local variables are also called auto automatic variables (auto can be written or not), generally code blocks < a i=4>The internally defined variables are all automatic variables, which have the following characteristics:{}

  • Scope: defined within a function, it is only valid within the function scope; defined in a compound statement, it is only valid within the compound statement
  • Life cycle:The program runs to the variable definition to open up space. With the end of the function call or the end of the compound statement, the life cycle of the local variable also ends, and the space is released< /span>
  • If no initial value is assigned, the content is random.

Example 1:

#include <stdio.h>

void test()
{
    
    
	//auto写不写是一样的
	//auto只能出现在{}内部
	auto int b = 20; 
	return;
}

int main(){
    
    
	
	//b = 100; //err, 在main作用域中没有b
	//int c;
	//printf("c=%d\n", c); // 未初始化的值   随机
	int* p = NULL;
	if (1)
	{
    
    
		//在复合语句中定义,只在复合语句中有效
		int a = 10;
		int d = 30;
		p = &d;
		printf("a = %d\n", a);
	}

	//a = 10; //err 离开if()的复合语句,a已经不存在
	*p = 300;
	printf("%d", *p);
	return 0;
}
输出结果
a = 10
300

2) Static local variables

  • Scope:staticThe scope of local variables is also valid within the defined function
  • Life cycle:staticThe life cycle of local variables is the same as the program running cycle. The space has been opened before the execution of the main function. When the program ends to release space; at the same timestaticthe value of local variable is only initialized once, but can be assigned multiple times
  • staticIf a local variable is not assigned an initial value, it will be automatically assigned by the system: Numeric variables are automatically assigned an initial value0, and character variables are assigned a null character

Example 1:

#include <stdio.h>

void fun1()
{
    
    
	int num1 = 1;
	num1++;
	printf("num1 = %d\n", num1);
}

void fun2()
{
    
    
	//静态局部变量,没有赋值,系统赋值为0,而且只会初始化一次
	static int num2 = 1;
	num2++;
	printf("num2 = %d\n", num2);
}

int main(void)
{
    
    
	static int n;
	printf("n = %d\n", n); // n = 0
	fun1(); // num1 = 2
	fun1(); // num1 = 2
	fun2(); // num2 = 2
	fun2(); // num2 = 3
	
	return 0;
}
输出结果
n = 0
num1 = 2
num1 = 2
num2 = 2
num2 = 3

3) Global variables

  • Scope: defined outside the function, can be shared by functions in this file and other files (all files in the entire project). If functions in other files call this variable, they must use externStatement
  • Life cycle: The life cycle of global variables is the same as the program running cycle. The space is opened before the main function is executed, and the space is released after the program ends.
  • If a global variable is not assigned an initial value, it will be automatically assigned by the system: Numeric variables are automatically assigned an initial value0, and character variables are assigned a null character
  • Global variables in different files cannot have the same name.

Example 1:

#include <stdio.h>

int num;

void test01() {
    
    


	num = 10;
	printf("num = %d\n", num);

}

int main() {
    
    
	printf("num = %d\n", num); // 0
	test01(); // 10
	

	return 0;
}

Example 2:

#include <stdio.h>

extern int num; // 声明num在其他文件定义过
int main() {
    
    

	num = 100;
	printf("num = %d\n", num);

	return 0;
}

Insert image description here

4) Static global variables

  • Scope: defined outside the function, the scope is limited to the defined file (current file);Static global variables in different files can have the same name, but the scope does not Conflict
  • Life cycle:staticThe life cycle of global variables is the same as the program running cycle. The space is opened before the main function is executed, and the space is released after the program ends; at the same time< a i=2>The value of the global variable is only initialized oncestaitc
  • staticIf a global variable is not assigned an initial value, it will be automatically assigned by the system: Numeric variables are automatically assigned an initial value0, and character variables are assigned a null character

Example 1:

#include <stdio.h>

static int num2;

void test02() {
    
    


	num2 = 20;
	printf("num2 = %d\n", num2);

}

int main() {
    
    
	printf("num2 = %d\n", num2); // 0
	test02(); // 20
	
	return 0;
}

Example 2:

#include <stdio.h>

extern int num2; // error 静态全局变量不能进行声明,更不能在其他文件使用
int main() {
    
    

	num2 = 100;
	printf("num2 = %d\n", num2);

	return 0;
}

Insert image description here

Scope: Local variables (ordinary local and static local) are within the scope of{}; ordinary global variables have scope in the entire project; static Globally affects the current file.

Life cycle: Only ordinary local variables are opened when running to the variable definition, and are released after the function ends. Other variables are executed before the main function The space has been opened up and will not be released until the program ends.

Initialized value: Only ordinary local uninitialized values ​​are random, others are0.

5) The problem of dividing global variables into files

Defects of global variable redefinition in C language:

#include <stdio.h>

// 全局变量之所以能编译过去,是因为其中有三个默认为声明extern,因为extern可写可不写,所以最好声明加上 extern
int a;
int a;
int a;
int a;

int main() {
    
    

	int b;
	//int b; // error 重定义
	return 0;
}

Insert image description here

First, let’s look at the correct handling of global variables in files.

main.cdocument

#include <stdio.h>
#include "demo.h"

// 声明全局变量cnum
//extern int cnum;
//extern void cfunc();
int main() {
    
    

	cfunc();
	printf("cnum = %d", cnum);

	return 0;
}

demo.cdocument

#include <stdio.h>
// 定义全局变量
int cnum=10;
void cfunc() {
    
    

	cnum = 100;
}

demo.hdocument

#pragma once

// 声明全局变量cnum
extern int cnum;
extern void cfunc();

Insert image description here

Now comment out the declaration of global variables in the demo.h header file and change it to int cnum;. In this case, the compiler can compile it , when it is not known whether it is a definition or a declaration, and the existence of in the demo.c file will be regarded as a definition, then in After in the function, it is equivalent to the presence of in the function. It will be treated as a statement, that is, no error will be reported during compilation. int cnum=10;maininclude "demo.h"mainint cnum;

Insert image description here

Then if you modify demo.h in the header file int cnum; to define int cnum=20;, then an error will be reported for redefinition, so In the .h file, global variables are only declared but not defined. The definition is only placed in the .c file

Insert image description here

6) The problem of variable name duplication

Taking into account the proximity principle under the premise of scope:

Example 1:

a.cdocument

#include <stdio.h>

static char* language = "java";

void func3()
{
    
    
	printf("language = %s\n", language);
}

b.cdocument

#include <stdio.h>

// 不同作用域可以重名
char* language = "c";

func2()
{
    
    
	printf("language = %s\n", language);

}

int main() 
{
    
    
	func2();
	func3();
	char* language = "c++";
	printf("language = %s\n", language);
	if (1)
	{
    
    
		char* language = "python";
		printf("language = %s\n", language);
	}
	printf("language = %s\n", language);
	return 0;
}

Insert image description here

Example 2:

func1.cdocument

int va = 7;
int getG(void)
{
    
    
	int va = 20;
	return va;
}

func2.cdocument

static int va = 18;
static int getG(void)
{
    
    
	return va;
}
int getO(void)
{
    
    
	return getG();
}

main.cdocument

#include <stdio.h>

extern int va;
extern int getG(void);
extern int getO(void);

int main() 
{
    
    
	printf("va=%d\n", va);
	printf("getO=%d\n", getO());
	printf("getG=%d\n", getG());
	printf("%d", va*getO()*getG());

}

Insert image description here

7) Global functions and static functions

In theC language, functions are global by default. Use the keywordstatic to declare the function as static, and the function is defined as static means that this function can only be used in the file in which this function is defined, and cannot be called in other files. Even if this function is declared in other files, it will be useless.

  • Ordinary functions without any modification are global functions that can be called by the entire project.
  • A static function is a function that is modified withstatic when the function is defined. A static function can only be called by the current file function

Global functions:

#include <stdio.h>

static char* language = "java";
// 全局函数
void func3()
{
    
    
	printf("language = %s\n", language);
}

Static function:

// 静态函数
static void func4()
{
    
    
	printf("language = %s\n", language);
}

If you have to call a static function, you can define a global function in the .c file where the static function is located, and call the static function in the same file in this global function. Then we can call the static function by calling this global function.

// 静态函数
static void func4()
{
    
    
	printf("language = %s\n", language);
}
// 全局函数
void func5()
{
    
    	// 调用静态函数
	func4();
}

Insert image description here

Notice:

  • The same variable name is allowed to be used in different functions. They represent different objects and are allocated to different units without interfering with each other.
  • In the same source file, global variables and local variables are allowed to have the same name. Within the scope of local variables, global variables have no effect.
  • All functions are global by default, which means that all functions cannot have the same name, but if it is a staitc function, the scope is file level, so different files staticThe function names can be the same.

8) Summary

type Scope life cycle
autovariable Itshu{ } inside current function
staticlocal variables Itshu{}Inside The entire program running period
externvariable the whole program The entire program running period
staticglobal variables current file The entire program running period
externfunction the whole program The entire program running period
staticfunction current file The entire program running period
registervariable Itshu{}Inside current function
global variables the whole program The entire program running period

memory layout

1) Memory partition

CThe code generates an executable program after four steps of preprocessing, compilation, assembly, and linking.
Under Windows, the program is an ordinary executable file. The basic situation of a binary executable file is listed below:

Insert image description here
Insert image description here

As can be seen from the above figure, before the program is run, that is to saybefore the program is loaded into the memory, inside the executable program Three pieces of information have been divided into code area (text), data area (data) and uninitialized data area (bss) ( Some people directly call data and bss together as the static area or global area).

  • Code area
    stores the machine instructions executed by CPU. Usually the code area is shareable (that is, other executing programs can call it). The purpose of making it shareable is that for frequently executed programs, only one copy of the code is needed in the memory. A code area is usually read-only. The reason for making it read-only is to prevent the program from accidentally modifying its instructions. In addition, the code area also plans relevant information about local variables.

  • Global initialization data area/static data area (data section)
    This area contains global variables that are explicitly initialized in the program and initialized static variables (including global static variables and local static variables) and constant data (such as string constants).

  • Uninitialized data area (also called bss area)
    stores global uninitialized variables and uninitialized static variables. The data in the uninitialized data area is initialized by the kernel to 0 or empty (NULL) before the program starts executing.

    Before the program is loaded into memory, the sizes of the code area and global area (data and bss) are fixed . It cannot be changed while the program is running. Then, run the executable program, and the system loads the program into the memory. In addition to dividing the code area (text), data area (data) and uninitialized data area (bss) according to the information of the executable program ), a stack area and a heap area are also added.

    Insert image description here

  • Code area (text segment)
    loads the executable file code segment. All executable codes are loaded into the code area. This memory cannot be modified during operation. of.

  • Uninitialized data area (BSS)
    loads the executable fileBSS section. The location can be separated or close to the data section. It is stored in The life cycle of the data in the data segment (global uninitialized, static uninitialized data) is the entire program running process.

  • Global initialization data area/static data area (data segment)
    The executable file data segment is loaded and stored in the data segment (global initialization, static initialization data, literal constants ( The data lifetime of read-only)) is the entire program running process.

  • Stack area (stack)
    The stack is a first-in, last-out memory structure that is automatically allocated and released by the compiler to store function parameter values, return values, local variables, etc. It is loaded and released in real time during the running of the program. Therefore, the life cycle of local variables is to apply for and release the stack space.

  • Heap area (heap)
    The heap is a large container. Its capacity is much larger than that of the stack, but it does not have the first-in, last-out order like the stack. Used for dynamic memory allocation. The heap is located between the BSS area and the stack area in memory. Generally, it is allocated and released by the programmer. If the programmer does not release it, it will be recycled by the operating system when the program ends.

2) Summary of storage types

type Scope life cycle storage location
autovariable Itshu{}Inside current function stack area
staticlocal variables Itshu{}Inside The entire program running period is initialized in the data section, uninitialized in the BSS section
externvariable the whole program The entire program running period is initialized in the data section, uninitialized in the BSS section
staticglobal variables current file The entire program running period is initialized in the data section, uninitialized in the BSS section
externfunction the whole program The entire program running period code area
staticfunction current file The entire program running period code area
registervariable Itshu{}Inside current function stored inCPUregister during runtime
String constant current file The entire program running period datapart

Example:

#include <stdio.h>
#include <stdlib.h>

int e;
static int f;
int g = 10;
static int h = 10;
int main()
{
    
    
	int a;
	int b = 10;
	static int c;
	static int d = 10;
	char *i = "test";
	char *k = NULL;

	printf("&a\t %p\t //局部未初始化变量\n", &a);
	printf("&b\t %p\t //局部初始化变量\n", &b);

	printf("&c\t %p\t //静态局部未初始化变量\n", &c);
	printf("&d\t %p\t //静态局部初始化变量\n", &d);

	printf("&e\t %p\t //全局未初始化变量\n", &e);
	printf("&f\t %p\t //全局静态未初始化变量\n", &f);

	printf("&g\t %p\t //全局初始化变量\n", &g);
	printf("&h\t %p\t //全局静态初始化变量\n", &h);

	printf("i\t %p\t //只读数据(文字常量区)\n", i);

	k = (char *)malloc(10);
	printf("k\t %p\t //动态分配的内存\n", k);

	return 0;
}

Insert image description here

输出结果
&a       003DFE9C        //局部未初始化变量
&b       003DFE90        //局部初始化变量
&c       00088180        //静态局部未初始化变量
&d       00088014        //静态局部初始化变量
&e       000884A4        //全局未初始化变量
&f       0008817C        //全局静态未初始化变量
&g       0008800C        //全局初始化变量
&h       00088010        //全局静态初始化变量
i        00085060        //只读数据(文字常量区)
k        007104D0        //动态分配的内存

3) Memory operation function

3.1 memset()

Fill a memory space with a certain value:

  • Header file:#include <string.h>
  • Define function:void *memset(void *s, int c, size_t n);
  • Function: Fill in the first bytes of the memory area ofs with parametersnc
  • Parameter:
    s:The first address of the memory to be operated onThe characters filled in, Although the parameter is , it must be , and the range is Specify the size that needs to be sets
    c:cintunsigned char0~255
    n:
  • Return value:The first address of s

Example:

#include <stdio.h>
#include <string.h>

// memset函数
int main()
{
    
    
	int a = 10;
	//a = 0;  -> memset()
	memset(&a, 0, sizeof(a));
	printf("a=%d\n", a);

	char str[20] = "hellocdtaogang";
	printf("str=[%s]\n", str);
	memset(str, 0, sizeof(str));
	printf("str=[%s]\n", str);
	// 将前10个字符置为a字符
	memset(str, 'a', sizeof(str) - 10);  // memset(str, 97, sizeof(str) - 10);
	printf("str=[%s]\n", str);
	return 0;
}
输出结果
a=0
str=[hellocdtaogang]
str=[]
str=[aaaaaaaaaa]

3.2 memcpy()

Copy memory contents

  • Header file:#include <string.h>
  • Define function:void *memcpy(void *dest, const void *src, size_t n);
  • Function: Copy the first bytes of the memory pointed to bysrc to the memory pointed by on the address. ndest
  • Parameters:
    dest:First address of destination memory
    src:First address of source memory,Note:< The memory spaces pointed to by a i=4> and cannot overlap, which may cause the program to report an error. Number of bytes to be copieddestsrc
    n:
  • Return value:The first address of dest

Example:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

// memcpy函数
int main()
{
    
    
	int a[10] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	int b[10] = {
    
     0 };
	// a = b;// error 常量不能修改
	// 将a数组中的前五个元素拷贝到b数组中
	memcpy(b, a, sizeof(int)*5);
	for (int i = 0; i < sizeof(b)/sizeof(b[0]); i++)
	{
    
    
		printf("%d ", b[i]);
	}
	printf("\n");
	char str1[128] = "";
	char str2[128] = "abc\0def\0hellocdtaogang";
	char str3[128] = "";
	// 使用strncpy
	strncpy(str1, str2, sizeof(char) * 22);
	for (int i = 0; i < 22; i++)
	{
    
    
		printf("%d ", str1[i]);
	}
	printf("\n");
	// 使用memcpy
	memcpy(str3, str2, sizeof(char) * 22);
	for (int i = 0; i < 22; i++)
	{
    
    
		printf("%d ", str3[i]);
	}
	return 0;
}
输出结果
1 2 3 4 5 0 0 0 0 0
97 98 99 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
97 98 99 0 100 101 102 0 104 101 108 108 111 99 100 116 97 111 103 97 110 103

3.3 memmove()

memmove()The function usage is the same as memcpy(), the difference is: when the memory spaces pointed to by dest and src overlap, < /span>. memmove() can still be processed, but the execution efficiency is lower than memcpy()

3.4 memcmp()

Compare memory contents

  • Header file:#include <string.h>
  • Define function:int memcmp(const void *s1, const void *s2, size_t n);
  • Function: Compare the first bytes of the memory area pointed to bys1 and s2n
  • Parameters:
    s1:Memory first address 1
    s2:Memory first address 2
    n:The first n bytes to be compared
  • Reply:
    Equal:=0
    Dayu:>0
    Xiaoyu:<0

Example:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

// memcmp函数
int main()
{
    
    
	int a[10] = {
    
     1, 0, 2, 3, 5, 6, 2, 8, 9, 10 };
	int b[10] = {
    
     1, 0, 4, 4, 5, 6, 7, 8, 9, 10 };

	int res1 = memcmp(a, b, sizeof(int));
	printf("res1 = %d\n", res1);
	
	int res2 = memcmp(a, b, sizeof(int)*10);
	printf("res2 = %d\n", res2);

	int res3 = strncmp(a, b, sizeof(int) * 10);  // strncmp遇到0就结束了
	printf("res3 = %d\n", res3);

	char str1[] = "abcd\0abc";
	char str2[] = "abcd\0bbc";
	printf("%d\n", strncmp(str1, str2, sizeof(str1))); // strncmp遇到\0就结束了
	printf("%d\n", memcmp(str1, str2, sizeof(str1))); 

	return 0;
}
输出结果
res1 = 0
res2 = -1
res3 = 0
0
-1

4) Heap area memory allocation and release

4.1 malloc()

Configure memory space

  • Header file:#include <stdlib.h>
  • Define function:void *malloc(size_t size);
  • Function: Allocate a continuous area of ​​size bytes in the dynamic storage area (heap area) of the memory to store the type specified by the type specifier. The content of the allocated memory space is uncertain and is generally initialized using memset.
  • Parameters:
    size: Memory size to be allocated (unit: bytes)
  • Return value:
    Success: starting address of allocated space
    Failure:NULL

Example:

#include <stdio.h>
#include <stdlib.h>

// malloc函数
int main()
{
    
    	
	//int a[10]; 直接是从栈区申请空间
	//申请一个数组,数组有10个元素,每个元素int类型,到堆区申请内存空间
	int* p = (int *)malloc(sizeof(int) * 10);  // malloc函数的返回值未void *类型最好是强转下
	*p = 100;
	*(p + 5) = 200;
	for (int i = 0; i < 10; i++)
	{
    
    
		printf("%d ", *(p + i));
	}
}

Insert image description here

输出结果
100 -842150451 -842150451 -842150451 -842150451 200 -842150451 -842150451 -842150451 -842150451

4.2 free()

Release the originally configured memory

  • Header file:#include <stdlib.h>
  • Define function:void free(void *ptr);
  • Function: Release a memory space pointed to byptr. ptr is a pointer variable of any type, pointing to the first address of the released area. Freeing the same memory space multiple times will cause an error.
  • Parameters:
    ptr:The first address of the space to be released. The released area should be the area allocated by the malloc function.
    Return value: None

Example:

#include <stdlib.h> 
#include <stdio.h>
#include <string.h>

// free函数
int main()
{
    
    
	//申请一个字符数组,有1024元素
	char* p = (char *)malloc(1024);
	//将申请到空间清0
	memset(p, 0, 1024);
	strcpy(p, "hellocdtaogang");
	// 释放内存
	free(p);
	//free(p+1) // free 参数  地址必须是上一次malloc申请过的,不能去改变这个地址
	//printf("%s\n", p); // 释放完了再打印那么就不会是你想要的数据
	//free(p); // malloc申请的空间不可以释放两次,申请一次,释放一次
	return 0;
}

Note:freeThe space applied for last time can only be released once;freeThe parameter address must be the last onemallocIf you have applied, you cannot change this address;mallocThe applied space cannot be released twice. Apply once and release once.

4.3 Memory leak

Memory leak: only apply for but not release
Memory pollution: write data to unapplied memory space

Insert image description here

Memory partition code analysis

1) Return stack area address

Example:Ordinary local variables exist in the stack area and will be released when the function call is completed, so the address of ordinary local variables cannot be returned for operation.

#include <stdio.h>

int* newfunc() 
{
    
    

	int a = 10; 
	a *= 10;

	return &a; // 函数调用完毕,a释放

}

int main()
{
    
    

	int* p = newfunc();
	//操作野指针指向的内存
	*p = 200; // error p所指向的空间已经被释放,
	printf("%d\n", *p);

	return 0;
}

Insert image description here

2) Return the data area address

Example 1:Static local variables exist in the static global area, and initialized ones exist in the data area. As long as the program does not exit, they will not be released, so the addresses of these variables can be returned. operate.

#include <stdio.h>

int* newfunc() 
{
    
    

	//int a = 10; 
	static int a = 10;
	a *= 10;

	return &a; 

}

int main()
{
    
    

	int* p = newfunc();
	*p = 200; // p所指向的空间没有释放(静态局部变量),则可以操作这块内存
	printf("%d\n", *p);

	return 0;
}

Insert image description here
Example 2:Static global and global variables exist in the static global area, and initialized ones exist in the data area. As long as the program does not exit, they will not be released, so the addresses of these variables are Operation can be returned.

#include <stdio.h>

//int a = 10; // 全局变量变量
static int a = 10; // 静态全局变量
int* newfunc() 
{
    
    
	//int a = 10; 
	//static int a = 10;
	a *= 10;

	return &a;

}

int main()
{
    
    
	int* p = newfunc();
	*p = 200; // p所指向的空间没有释放(静态全局变量、全局变量),则可以操作这块内存
	printf("%d\n", *p);

	return 0;
}

In short:Only the address of ordinary local variables cannot be returned, because ordinary local variables are released after the function ends; while static local variables, global variables, and static global variables These variables will not be released as long as the program does not exit, so the addresses of these variables can be returned to the operation.

3) Value transfer

Example 1:The essence of the formal parameter is a local variable. When the function call is completed, it will be released, so the address of the formal parameter cannot be returned.

#include <stdio.h>

int* newfunc2(int num)

{
    
    	//形参的本质就是局部变量
	num += 100;

	return &num; // 函数调用完毕,num释放,不可以返回形参的地址

}
int main()
{
    
    
	int num = 10;
	int *p = newfunc2(num); 
	*p = 200;


	return 0;
}

Example 2:Define the function to return the address of k actual parameters, so the actual parameter address will not be released when the function ends.

#include <stdio.h>

int* newfunc3(int *k)

{
    
    
	int i = 100;
	*k = *k + i;

	return k; // 返回k指向的num的地址,所以函数结束num变量的地址没有被释放
}
int main()
{
    
    
	int num = 10;
	int* p = newfunc3(&num);

	return 0;
}

Insert image description here

Example 3:

4) Return the heap area address

Example:The address of the heap area can be returned, and the heap area will not be released after the function ends; however, string constants cannot be assigned directly, which will cause space loss and memory loss. leak

#include <stdio.h>
#include <stdlib.h>

char* newfunc4()
{
    
    
	char* q = malloc(100);

	return q; // 堆区的地址是可以返回的,函数结束不会被释放
}
int main()
{
    
    
	char* p = newfunc4();
	p = "hello";
	free(p); // error p并没有指向堆区,而是指向文字常量区"hello"

	return 0;
}

Insert image description here
Insert image description here

Assignp to an integer, and there will be no error

Insert image description here

Usingstrcpy(p, "hello"); will not cause memory leaks

Insert image description here

Insert image description here

5) The actual parameter is the address of the first-level pointer

Example 1: Passing by value of the function cannot change the value of the actual parameter

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void mem_p(char *q) 
{
    
    
	q = malloc(1024);
	return;
}
int main()
{
    
    
	char* p = NULL;
	mem_p(p);
	strcpy(p, "hello");
	printf("p=%s\n", p);

	return 0;
}

Insert image description here

If you compile and run directly, no error will be reported, but no data will be printed. It can only be said that the compiler does not prompt an error, but the error can be viewed through break points.

Insert image description here

causes the above error because p points to NULL and does not point to the heap address, causing memory pollution. The solution is p just points to the address opened in the heap area.

char* mem_p(char *q) 
{
    
    
	q = malloc(1024);
	return q;
}
int main()
{
    
    
	char* p = NULL;
	p = mem_p(p);
	strcpy(p, "hello");
	printf("p=%s\n", p);

	return 0;
}

Insert image description here

Example 2: Pass the address of the actual parameter, and you can change the value of the actual parameter when calling the function (the actual parameter is the first-level pointer address, and the formal parameter is the second-level pointer)

void mem_p2(char** k)
{
    
    
	*k = malloc(1024);
	return;
}
int main()
{
    
    
	char* p = NULL;
	mem_p2(&p);
	strcpy(p, "hello");
	printf("p=%s\n", p);

	return 0;
}

Insert image description here

Insert image description here

Guess you like

Origin blog.csdn.net/qq_41782425/article/details/127956346