当前位置:网站首页>C pointer and array depth summary
C pointer and array depth summary
2022-04-22 02:37:00 【Descosmos】
guide
-
- problem 1( Flexible array )
- problem 2( Array scopes of different storage types )
- problem 3( Initialize dynamic array and static array )
- problem 4(typedef Use of pointers )
- problem 5( Where the pointer is used )
- problem 6( Array address problem )
- problem 7( Pointer symbol priority )
- problem 8( Address cast )
- problem 9( Two dimensional pointer , Two dimensional array 1)
- problem 10( Two dimensional pointer , Two dimensional array 2)
- problem 11( Failed to open dynamic array )
- problem 12( A function pointer )
- problem 13( Function pointer array )
- problem 14(malloc)
After reading the basic about C After language books , Consider oneself C The author, who has learned almost the same language, has done several interview questions , Um. , Doubt life . And as most people think ,C The essence of language is pointers . Then carefully list the pits that the author has fallen .
problem 1( Flexible array )
struct A{
int i;
char str[];
};
In the upper structure ,str The array length of is 0. This is in vs2012 An error will be reported in the compiler . And a lot about C Language books have repeatedly stressed , The array in the structure must declare the length , But in C99 This can be allowed .
A typical case of this problem is in Linux C In the network file library ,sys/un.h Header file , About socket structure sockaddr_un The definition of .
/* Some header file versions */
struct sockaddr_un{
sa_family_t sun_family;
char sun_path[];
};
/* Chuanyi Linux edition CentOs-7 */
struct sockaddr_un{
__SOCKADDR_COMMON (sun_);
char sun_path[108];
};
But in this kind of structure , A flexible array must be preceded by a structure member . Understand the specific usage :C99 file .
problem 2( Array scopes of different storage types )
int *func(){
int arr[3] = {1,1,1};
return arr;
}
int main(){
int i = 0;
int *p = func();
while( i++ < 3 ){
printf("%d\n",*p++);
}
return 0;
}
What is the result of this code ?

stay linux Environmental use gcc compile , The answer is not three 1, But cannot execute . Why? ? because arr Array is defined in func Internal function , In the main function execution, enter func Function time , The system opens up a piece of memory for func Function USES , This memory “ Valid time ” Is the time from the execution of the function to the end of the function . stay func The function is in memory ,arr Array opens up a block of memory to store array variables . here arr The scope of the array is limited to func Internal function . So in func After the function is executed ,arr The memory of the array is also naturally lost . Therefore, the compiler will report an error .
So if you put func The function is slightly modified ?
int *func(){
static int arr[3] = {1,1,1};
return arr;
}
Or become like this :
int *func(){
int *arr = (int*)malloc(3 * sizeof( int ));
arr[0] = 1, arr[1] = 1, arr[2] = 1;
return arr;
}
Will the program fail to execute ?
Can't .
because static Variables and global variables are at static addresses , The address will not be released until the program execution is completed . Dynamic memory allocation is not on the stack , It's a pile . So as long as you don't use free To release arr Array or program end , This address will always exist . This thing initializes the sequence table later , Queue and other data types will play a great role .
problem 3( Initialize dynamic array and static array )
In some numerical calculations , You will need to initialize the array , Let the inner element of the array be a definite value .
/* The dynamic array */
void func(){
int i = 0;
int *arr = (int*)malloc(3 * sizeof(int));
while( i < 3 ){
*arr = i++;
arr++;
}
}
/* Static array */
void func(){
int i = 0;
int arr[3];
while( i < 3 ){
*arr = i++;
arr++;
}
}
Do these two functions have the same execution results ?
Different .
Using dynamically opened arrays and directly using array names for address self addition operation is allowed , The statically opened array does not allow direct operation on the array name . But you can do this for static addresses :
void func(){
int i = 0;
int arr[3];
int *p = arr;
while( i < 3 ){
*p = i++;
p++;
}
}
Using this method, static arrays can also be initialized by pointer method .
Although dynamic arrays are relatively convenient , But if you don't pay attention, there will be big pits .
int func(){
int arr[3];
int *p = a;
while( p < &a[2] ){
*p++ = 0;
}
}
int func(){
int *p = (int*)malloc(3 * sizeof(int));
while( p <= &p[2] ){
*p++ = 0;
}
}
Why use this method , Because it's efficient . The internal variables of the computer are through “ Addressing ” The way to operate , under these circumstances , There is no doubt that it is more efficient to judge the array boundary directly with the address . In this function ,p It's one, three int An array of lengths , Its starting address is &p[0] That is to say p , Termination address is &p[3] .
According to this rule , that arr and p Arrays will be initialized 0. Is that so? ?
The method of static array can get the desired result , And dynamic ? This is an infinite cycle . because p Your address keeps going to “ front ” Into the ,p[2] The meaning is p The second address after . It means p Your address is constantly “ Forward ”,p[2] Your address is also constantly “ Forward ”. If you want leather, I think you can only keep the termination address of the dynamic array unchanged , Re pass “ Lock termination address ” To achieve the purpose of initialization .
But generally initialize the array ( No matter what type of array ), The author generally uses memset This function is used to .
Both static arrays and dynamic arrays can be assigned or self operated by using the method of array subscript , However, pointer methods can only be used with dynamic arrays .
problem 4(typedef Use of pointers )
Did you learn C Language people are really fidgety about the definition of structure , Because when you create a data structure using a structure type , Very inconvenient , Why don't you look at the things below .
struct InfomationStudent{
int number;
char *name;
};
Such as the list , To create a new node , Dynamic memory development requires a lot of writing ,
struct InfomationStudent*stu = (struct InfomationStudent *)malloc(sizeof(struct InfomationStudent));
Just write such a statement , Half my life is gone . So... Is usually used typedef To simplify types , About typedef Kawashi didn't elaborate on the specific usage of . Let's look at a question ,
typedef Struct InfomationStudent* InfoStu;
const InfoSu stu1; /* A */
InfoSu const stu2; /* B */
The second one above , What's the difference between the third sentence ?
Did you learn const and typedef usage , Maybe A What is decorated in is stu1, and B The pointer is decorated in . No , These two statements are one thing . It's like const int a ; and int const a; There is no difference . Why? ? because ,typedef The mechanism is to replace the type directly , Rather than define Same simple text replacement .
problem 5( Where the pointer is used )
In the previous example , Let's make a little change :
int i = 0;
int arr[3];
int *p = arr;
while( p < &a[2] ){
*p++;
}
Maybe you can easily answer ,*p++ The meaning of , But this one ?
int neg, a = 1 , b = 1;
int *p = &b;
neg = a/*p;
neg What is the result ? yes 1 Do you ? unfortunately , No . This statement cannot be executed ,
Look for the ,/* , What is this thing ? notes ,a The following contents are all commented out as comments . Of course, you will clearly observe this problem in the compiler , But if you're wrong , Explain your C Language Pointers and comments There is still a big problem with the foundation .
problem 6( Array address problem )
After many people have a preliminary understanding of arrays and pointers , I think I have fully mastered their usage , Let's take a look at the following classic example .
int a[5] = {1,2,3,4,5};
int *ptr = (int*)(&a+1);
*(a+1), *(ptr-1) What will the results be ?
Before we understand this question , Familiarize yourself with , What is a pointer ? What is an array ? The pointer is not an array , Arrays are not pointers either . Even if the array member address is assigned to the pointer , The pointer is still just a pointer .
Of course , You should also find out **&a**,&a[0],a The difference between .
&a, Is the starting position of the array , and &a[0] Is the starting position of the first element of the array , as for a, In a one-dimensional array , It and &a[0] It's the same thing . Although the addresses of the above three things are the same , But you still need to know their usage and differences .
As for this question , The answer is 2,5.
What about the next one ?
int a[5] = {1,2,3,4,5};
int (*ptr)[5] = &a;
int (*pt)[5] = a;
ptr and pt Usage of , Which is correct ?
There is no doubt that ptr , The specific differences have been mentioned earlier , As for right pt Usage of , The compiler will give an alarm , Because the type doesn't match .
ptr+3,pt+4 What's the value of ? If you understand this , Look at the following :
int a[5] = {1,2,3,4,5};
int (*ptr)[3] = &a;
int (*pt)[3] = a;
At this time ptr+3,pt+4 What is the value ?( Most compilers will report an error for this problem , But as a programmer, it's best to know this problem )
problem 7( Pointer symbol priority )
I just went to freshman school in Sichuan C Language , By pointer array , Array pointer , Pointer function , Confused by function pointers . Of course, their meanings can be distinguished from words , But the definition .
int *a[3];
int (*a)[3];
int *fun();
int (*fun)();
Many beginners will be confused , But as long as you know Operator precedence The problem will easily come to , The first is the pointer array , The second is the array pointer , The third is the pointer function , The fourth is the function pointer . because [],() The operation priority of symbols is higher than * high , Therefore, the variable name is first combined with the operator with high priority , Then combine with the operators with low operation order .
int *(*a)[6];
int *(*fun())();
int (*(*fun)())[6];
So what are these ?
problem 8( Address cast )
If you are confident that you have mastered C Cast usage of , that :
int a[4] = {1,2,3,4};
int *ptr = (int*)(&a+1);
int *pt = (int*)( (int)a + 1);
printf("%x,%x\n",ptr[-1],*pt);
What is the result of the output ?
After the above example , It may be easy for you to know ptr[-1] The address of is a[3] The address of . that *pt Well ?
In Chuanyi gcc In the environment , This is the result of the operation :

pt The address of , Obviously , yes a[0] The address of the second byte of , And one int Four more bytes . Do you understand ?
problem 9( Two dimensional pointer , Two dimensional array 1)
The basic usage of two-dimensional pointer will not be repeated here , Let's start with a two-dimensional array .
When passing between multidimensional array functions , If you directly use the following usage , Seems amateur and cumbersome , Operating efficiency is also greatly reduced . Because it is very important to master the use of multi-layer pointers to multi-dimensional arrays . Arrays over two dimensions are rarely used , So just talk about two-dimensional pointers and arrays .
Suppose we need to do matrix operation now , And the calculation of your matrix , The operation and display are in different functions , What would you do ?
/* Method 1 */
void init( int a[3][3] ){
for(int i = 0 ; i < 3 ; i++){
for(int j = 0 ; j < 3 ; j++){
a[i][j] = 0;
}
}
}
/* Method 2 */
void init(int **a,int len){
for(int len = 0 ; i < len ; i++){
*p++ = 0;
}
}
Maybe you will find it more convenient to pass in an array directly from the above code , But then you'll know which method is more appropriate .
stay C In language , A function is a contiguous area of memory , When the compiler operates on a function , It will not only open up space for variables defined in the function , It will also open up space for the incoming parameters . In this case, if the first method is used , The memory overhead of program execution will be very large , Moreover, the execution efficiency of pointer bit operation will be much higher than that of array .
Let's simply look at the number of different assembly instructions in this code :


The first one is the assembly instruction according to the first method , On the contrary, the second .
Although this picture is not very different , But it can also explain the problem of efficiency . But remember one thing :
When an array is used as a function parameter , The compiler always parses it into a pointer to the address of its first element . And , You cannot change the value of the passed in array using this method , The parameter passed in is just a copy . This is the difference between calling by value and calling by address .
problem 10( Two dimensional pointer , Two dimensional array 2)
How to create a dynamic two-dimensional array ?
There are two ways , One is to create... Through a row pointer array , The other is realized by two-dimensional pointer . Each method has its own advantages and disadvantages , Row pointer array is used in the implementation of creating generalized list and cross linked list , Two dimensional arrays are a little more interesting .
Line pointer create
int *arr[3];
for( int i = 0 ; i < 3 ; i++){
arr[i] = (int*)malloc( 3*sizeof(int) );
}
This method is easier to understand , After all, it's the same as creating a one-dimensional array .
Two dimensional array creation
int **arr;
arr = (int**)malloc( 3 *sizeof(int) );
for( int i = 0 ; i < 3 ; i++ ){
*arr++ = (int*)malloc( 3*sizeof(int));
}
/* Destroy */
for( int i = 0 ; i < 3 ; i++ ){
free(*arr);
*arr++;
}
free(arr);
Because it's dynamic , Therefore, you need to free memory after using it , Free memory from low to high dimensions .
problem 11( Failed to open dynamic array )
void fun(char *str , int len){
str = (char*)malloc( len * sizeof(int) );
}
int main(){
char *str = NULL;
fun(str,10);
strcpy(str,"hello");
return 0;
}

str The result will be hello Well ? Unfortunately , No . This is the transmission mentioned earlier a and &a The difference between . Think back to string output , Is it right? printf("%s\n",str); If it is , Then it means that the compiler will str Also as a parameter , that fun Dynamic development in is to str A copy of the ,fun Medium str Opened up memory .
So what to do ? Two ways .
Return value method
This method is to create a header node in the data structure , Head pointer is often used .
char *fun(char str , int len){
str = (char*)malloc( len * sizeof(int) );
return str;
}
int main(){
char *str = NULL;
str = fun(str,10);
strcpy(str,"hello");
return 0;
}
Two dimensional pointer method
void fun( char **str , int len ){
*str = (char*)malloc(len*sizeof(char));
}
int main(){
char *str = NULL;
fun(&str,10);
strcpy(str,"hello");
return 0;
}
Be careful , The parameter here is &str instead of str, In this way, the address is passed in instead of the value , Pass through... Inside the function “*” To unlock . This is used in Linux Process or thread management is often used .
problem 12( A function pointer )
Speaking of function pointers, many people understand :void (*fun)(); This format , What about the following things ?
char *(*fun1)(char *p , char *s);
char **fun2(char *p , char *s);
char *fun3(char *p , char *s);
What is the difference between the three ?
According to the previous example , Judge by operator priority . Obviously , The first is a function pointer , The return value type of the function is char * type .
fun2 Is a pointer function , The return value is a secondary pointer .
fun3 Is a pointer function , The return value is one char The pointer .
So the next :
void fun(){
printf(""fun\n);
}
int main(){
void (*p)();
*(int*)&p = (int)fun;
(*p)();
return;
}
*(int*)&p = (int)fun What does it mean ?
adopt C Language generated assembly instructions can know , The address of the function name is the first address of the memory stored for the function . For this statement , I understand that :
First ,p Is a function pointer ,p Point to a function , The type and return value of this function are void.
&p Is the storage address of the pointer itself .
(int*)&p Is to force the address to int Pointer to type .
(int)fun Is to cast the entry address of the function into int type .
Then the function of the whole sentence is , Assign the entry address of the function to p The pointer .
(*p)(), Is the call to the pointer .
Of course , Callback functions are commonly used like this :
void fun(){
printf(""fun\n);
}
int main(){
void (*p)() = &fun;
(*p)();
return;
}

Maybe you think it's faster and easier to call functions directly , But in fact, this method is not conducive to the overall development . Using pointers to call functions is more conducive to modular implementation .
wait , Here's another question to think about :
(*(void (*))0)() , What is it? ?
problem 13( Function pointer array )
Since the above example mentioned C Modular design , In progress , When designing large-scale software , You can't always rely on ctags To judge the architecture , To make better use of functions , Make the use of functions more Organized , There is a system , A module can be , Or function pointers of similar functions are placed in an array .
void fun1(){
printf(""fun1\n);
}
void fun2(){
printf(""fun2\n);
}
void fun3(){
printf(""fun3\n);
}
int main(){
void (*pArr[3])();
pArr[0] = &fun1;
pArr[1] = &fun2;
pArr[2] = &fun3;
pArr[0]();
pArr[1]();
pArr[2]();
}
The general usage is like this .
What about function pointers and array pointers ?
char *fun1(char *s){
puts(s);
return s;
}
char *fun2(char *s){
puts(s);
return s;
}
char *fun3(char *s){
puts(s);
return s;
}
int main(){
char *(*a[3])(char *s);
char *(*(*ptr)[3])(char *s);
ptr = &a;
a[0] = &fun1;
a[1] = &fun2;
a[2] = &fun3;
ptr[0][0]("fun1");
ptr[0][1]("fun2");
ptr[0][2]("fun3");
return 0;
}
Always be right about * Have a clear understanding of the level of symbols and the priority of symbols , In this way, pointers and arrays are not difficult to understand . Because there will be no such troublesome usage in practice , But when there is a problem, you should know what this thing is .
problem 14(malloc)
When opening up dynamic arrays or other data types , Will be used a lot malloc function . Linux Next , The declaration of this function is in /usr/include/stdio.h Is the default , But in /usr/include/malloc.h , Is another usage . Specifically, it does not explain .
int *ptr = NULL;
ptr = (int*)malloc(0);
if( ptr == NULL ){
printf("NULL\n");
}
ptr yes 0 Well ? printf Not execute , and ptr Will be allocated a piece of memory .

This address really exists , You can also assign values .
Actually in .C Reference malloc In the introduction of function , That explains the situation .
But no one will use it like that , So as to understand the content .
版权声明
本文为[Descosmos]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204220230319310.html
边栏推荐
- 我要开始学canvas了
- Shuttle jump interface
- JS regular expression -- commonly used by individuals
- The night can also be colorful, and the full-color night vision system can be realized by deep learning
- How to solve the deadlock problem in MySQL?
- Plug in import and usage of uni list
- Soxinda won 100 million yuan investment from Financial Street capital
- How does ECS connect to ad domain or LDAP user source
- Mysql的索引为什么使用B+树而不使用跳表?
- STM32 CAN通信实验
猜你喜欢

WSOLA原理及matlab仿真

softmax运算

Complete solution of closure operation in Discrete Mathematics

【时序】DCRNN:结合扩散卷积和GNN的用于交通流量预测的时空预测网络

Knowledge points of machine learning and deep learning

Training set: alexnet classification

YOLOv3论文翻译

Development management · Huawei IPD

Eight common probability distribution formulas and visualization

Wu Enda's machine learning assignment -- Logical Regression
随机推荐
[TIANTI competition] l2-040 Zhezhi game (25 points (s)) (simulation)
Uniapp handles forced refresh
K3s source code analysis 2 - Master Logic source code analysis
致文明的生活方式和环境污染
2022年物联网安全的发展趋势
golang 1.8泛型测试
Binary cross entropy loss function
刷题计划——动态规划dynamic programming(二)
JS Baidu map positioning
Unity game optimization - third edition reading notes Chapter 1 analyze performance problems
Can initialization process
遇到个奇怪的问题,同时开启本地和远程两个事务,远程事务是sql2000没问题,是sql2008的不报错,但是写不上数据
Possible reasons for slow response of Web site access
Five cool login pages that can be used
CentOS 7 installs mysql5 7 detailed tutorial
DOS 命令行基本命令及实践
Complete solution of closure operation in Discrete Mathematics
Oracle table Association divergence
STM32 CAN通信实验
Oracle表关联发散