The definition of pointers in C language and their use as formal parameters in different environments, as well as the strong conversion of pointer types

1. Basic knowledge of pointers

Definition of pointer: The full name of pointer is pointer variable.

A pointer is essentially a type, which is the same as int, float, double, and char. This type is called a pointer type, and the defined variable is called a pointer variable.

int *p; This expression means to define a variable p, the * symbol means that the variable p I defined is a pointer type, and the previous int means that the pointer variable p I defined points to an integer, and the pointer variable The value of p is the address of the integer variable pointed to by p, so when assigning a value to the pointer, it is an address value.


&: Take the address symbol, add & in front of the variable, then the whole represents the address of the variable

*: When using * in variable definition, it means that I define a pointer type variable. When used in other places, it means that I operate on the data stored in the variable address pointed to by the pointer variable. For example int a = 5; int *p; *p =& a


int a = 5; An integer variable a is defined, and a is initially assigned a value of 5

p = &a; a is an integer variable, add & in front of a to get the address symbol, then &a as a whole represents the address of the variable a, and assign this address   Give the pointer variable p, that is to say, the value of the pointer variable p is the int variable a pointed to by the pointer variable p

2. Operation of pointer variables

A pointer is essentially a variable, but this variable is of pointer type, and there is no essential difference from variable types such as int type. Since it is a variable, you can + - * / % these arithmetic operations. It's just that the value of the pointer type variable is an address * / %, etc. These operations are possible, but they have no practical significance. The most common usage is the + - operation on pointers. It is most obvious when combined with the method of array value operation:

int a[4] = {100,200,300,400}; Define an integer array, this array has five integer type data

int *p; Define a pointer variable p pointing to an integer variable, and the value of p is the address of the integer variable pointed to.

p = a; When the array name is an rvalue, the meaning is that the array name is the address of the first element of the array, that is, the address of a[0]. Both a and &a[0] are equivalent to indicate the first address of the array element

p points to the first address of a[0] *p value is a[0]

p+1 points to the address of a[1]     The value of *(p+1) is a[1]      

p+2 points to the address of a[2]     The value of *(p+2) is a[2]

For *(p+1), () has the highest priority, so the expression of () is calculated first, p+1 means to perform +1 operation on the address of the variable pointed to by p, here +1 is not the address The value is +1, but the address is increased by 4. The meaning of this 1 is to increase the size of the variable type pointed to by p. The variable pointed to by p is of integer type, and the size of the integer type occupies 4 words. section data size, so 4 is added. Take the following table as an example:

*p=a[0]            *(p+1)=a[1]   *(p+2)=a[2]    *(p+3)=a[3]     

a[0] =100 a[1]=200 a[2]=300 a[3]=400
0x1000        0x1004         0x1008          0x100c

p                  p+1              p+2                p+3


It can be seen from the above table that p=&a[0]; the address value of &a[0] is 0x1000, then the value of p is 0x1000. The value of p+1 is 0x1004, not 0x1001, so the value of this +1 is actually the length occupied by int in memory, which is 4 bytes.

p = &a[0]; 

printf("*p=%d\n",*p); The value of *p is the value stored in the address of the variable pointed to by p. The variable pointed to by p is a[0], the address of the variable pointed to by p is 0x1000, and the value stored in the address 0x1000 is 100, so *p = 100;

*p = 200; It is equivalent to modifying the value stored in the address of the variable pointed to by p, that is, the value of 100 stored in 0x1000 is changed to 200, that is, the value of a[0] is 200.

*(p+1) and *p have the same meaning. First of all, it is determined that the highest priority is in (), p is a pointer variable, the value of p is the address of the variable pointed to by p, the variable pointed to by p is a[0], and the address of a[0] is 0x1000 , so the value of p is 0x1000, p+1 is the value of p with sizeof(int) bytes added on the original basis, which is 4 bytes, so p+1=0x1004, that is to say, the value of p+1 It is &a[1], so p+1 points to the integer variable a[1], and the value of p+1 is the address of a[1]. *The meaning in the operation expression is to operate on the value of the address of the variable pointed to by the pointer, and now p+1 points to the integer variable a[1], so

*(p+1) = a[1], that is to say *(p+1) = 200; the following operations can be deduced by analogy.


3. Casting of pointer types

int a = 0x11223344;

char *p;

p = &a; 

Analyze the code above. The pointer variable p points to a variable of char type, and the type of the variable a pointed to by p is int type when assigning a value to the pointer variable. This assignment method is unreasonable, and the compiler will report a warning or error. In practice If you use this method to assign values ​​in the project, there will be unpredictable risks. Only redefine the pointer variable p so that the pointer points to an integer variable. as follows

int *p;

p = &a;

Then the value of *p is 0x11223344;


Add us to define according to the method at the beginning, but we need to take out the four values ​​of 0x11, 0x22, 0x33, 0x44 separately. How should we operate? This involves the forced conversion of the pointer type. Do as follows:

int a = 0x11223344;

char *p;

p=(char *)&a;

Analysis: () has the highest priority, so the first operation starts from inside (), char * means to force the variable type pointed to by the pointer to char type, the variable pointed to by the pointer p is a, The type of a is int type, and the int type is cast to char type. The value of the pointer variable p itself remains unchanged, or the address value of a&a; the only thing that changes is that the type of the variable a pointed to by the pointer variable p is cast. What is the value of *p?

After the forced conversion, p points to a variable of type char, so the value of *p is a value of type char. Analyze through the following table:


0x11 0x22 0x33 0x44

0x1000        0x1001        0x1002        0x1003

p                  p+1             p+2              p+3


p = (char*)&a;     p的值还是a的地址,就是p的值是0x1000;但是p所指向的变量也就是a的类型强制转换为char型,a在内存中还是按照整型数据存储的,但我们取值的时候是按照char型取出的。

说以*p取值时取的是一个char型变量,也就是0x11,

*(p+1) 这里+1的意思是地址+sizeof(char)个字节,不是+sizeof(int)个字节,因为我们在指针赋值时强制将指针所指向的变量类型转换为char型,所以p+1的值是0x1000+1就是0x1001,而0x1001的地址存放的值是0x22,所以

*(p+1) = 0x22;

*(p+2) = 0x33;

*(p+3) = 0x44;

这种操作一般用在函数传参时的类型强制转换,一般用在内存读写上。


注:一定要明白指针类型的强制转换的含义,强制转换的是指针所指向的变量类型,而不是指针类型,因为指针本来就是一个类型了。对指针进行+ -操作时,每次+1的值含义是地址偏移sizeof(char)字节,而不是sizeof(int)字节。


如何将一个有意义的整型变量转换为一个地址?


char *p;

int a = 0x1200;

p = (char* )a;

分析:将a强制转换为指针类型,则a的值由一个int型的值转换为一个地址值了,这个p指针变量指向char型变量。

举例:

void ReadFlash(uint32_t addr, uint8_t *ptr, int len)

{

int i;

for(i = 0; i < len; i++)
{

*ptr++ = (char *)addr++; //将整型addr的值赋值给ptr指针,则ptr的地址值就是addr的值,ptr所指向的变量

//char型的,也就是ptr取值时是按照char数据类型大小来取值的。

}

}

#define BUFF_LEN      (100)

int main(void)

{

uint8_t buff[BUFF_LEN] = {0};

ReadFlash(0x10000,buff, BUFF_LEN);

}


整型变量强转为地址值时用的很少,但在内存中取值时这种用法有时候是必须的。


4.函数传参的俩种方式,传值和传地址

调用函数时经常要给函数的形参列表来传递参数,将实参传递给形参有俩种方法

第一种:传值

调用函数时将实参的值传递给形参,实际上是将实参的值拷贝一份传递给形参,而实参并没有参与调用函数的运算,所以传值传参是不会改变实参的值的,因为是将实参值拷贝了一份传给形参。

第二种:传地址

实参向形参传地址,则形参是指针类型的,将地址赋值给形参,则形参和实参共用同一片内存地址,也就是说通过传进来的地址对形参进行操作,会改变实参的值,因为形参和实参的地址是同一个,通过指针操作修改形参值,也就修改了实参的值。











Guess you like

Origin blog.csdn.net/qq_27568125/article/details/78283530