C Language Notes: Pointers

content

1. What is a pointer?

2. Pointers and pointer types

3. Wild pointer

 3.1 Causes of wild pointers

 3.2 How to avoid wild pointers

4. Pointer arithmetic

4.1 Pointer + - Integer

4.2 Pointer-Pointer

4.3 Relational operations on pointers

5. Pointers and arrays 

6. Secondary pointer

7. Array of pointers


1. What is a pointer?

2 points for pointer understanding:

1. A pointer is the number of a smallest unit in memory, that is, an address

2. The pointers that are usually spoken in spoken language usually refer to pointer variables, which are variables used to store memory addresses.

The memory will be divided into one memory unit , each memory unit occupies one byte

Memory cell number:

For a 32-bit computer, there are 32 address lines/data lines - wires - that generate positive ( 1 )/negative ( 0 ) power when powered on

There are 2^32 kinds of binary sequences (numbers) generated after power-on, each of which corresponds to a memory unit in the memory, and the number is called the address of the memory unit

Summary: A pointer is an address, and a pointer in colloquial language usually refers to a pointer variable.

pointer variable:

We can use the & (address operator) to take out the actual address of the variable's memory, and store the address in a variable, which is a pointer variable

void test1()
{
	int a = 10; //向内存申请四个字节的空间,存放10
	printf("%p\n", &a); //取地址 00AFFC8C
	int* pa = &a; //地址也是一个值,可以存储到pa变量中 - pa就是指针变量 
	              //此时的*是告诉读者pa是一个指针变量
				  //此时的int表示a的类型是int类型
	*pa= 20; //解引用操作符
	printf("a = %d\n", a);
	
	char ch = 'w'; //向内存申请一个字节的空间,存放'w'
	char* pc = &ch;
	*pc = 'a';
	printf("ch = %c\n", ch); //ch = a
}

Summarize:

Pointers are used to store addresses, and addresses uniquely mark a piece of address space.

The size of a pointer is 4 bytes on 32-bit (32bit) platforms and 8 bytes on 64-bit platforms.

2. Pointers and pointer types

Since the size of the pointer is 4 bytes (32 bits), why should the pointer variable be divided into int, char, ...?

Meaning of pointer types:

1. The type of the pointer determines how much authority it has when dereferencing the pointer (can operate several bytes)

2. When the pointer is + - integer, the type of the pointer determines how much (distance) the pointer goes forward or backward.

void test2()
{
	//指针类型的意义:
	//1.指针类型解引用操作时,能一次性访问几个字节
	//2.指针进行+ -整数的时候,指针的类型决定了指针向前或者向后走一步有多大(距离)。

	int a = 0x11223344;
	int* pa = &a;
	char* pc = &a;
	*pa = 0;//访问4个字节
	*pc = 0;//访问1个字节

	//当使用int*pa定义时,*pa = 0让a的4个字节全部改成了0
	// 而用char*pa定义时,*pa = 0只让a的1个字节变成了0

	printf("%p\n", pa);    //010FFB60
	printf("%p\n", pa + 1);//010FFB64 向后走了4个字节

	printf("%p\n", pc);    //010FFB60
	printf("%p\n", pc + 1);//010FFB61 向后走了1个字节
}
void test3()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* pa = arr;
	char* pb = arr;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d\n", *(pa + i));//1 2 3 4 5 6 7 8 9 10
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d\n", *(pb + i));//1 0 0 0 2 0 0 0 3 0
	}
	//因为1 2 3在内存中为 01 00 00 00 02 00 00 00 03 00 00 00
	//用char定义指针变量,pb每次+1,只向前走了一个字节

	char arr1[] = "abcdef";
	char* pc = arr1;
	int* pd = arr1;
	for (i = 0; i < 6; i++)
	{
		printf("%c\n", *(pc + i));// a b c d e f
	}
}

3. Wild pointer

Concept: A wild pointer is where the pointer points to is unknowable (random, incorrect, unspecified)

 3.1 Causes of wild pointers

1. The pointer is not initialized

void test4()
{
	int* p; 
	//p就是野指针
	//p是指针变量,也是局部变量。局部变量不主动初始化,默认是随机值
	*p = 20;//内存中随机找了一个位置 放入20
}

2. Pointer out-of-bounds access

When the range pointed to by the pointer exceeds the range of the array , p is a wild pointer

void test5()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	int i = 0;
	for (i = 0; i <= 10; i++) //循环11次时,越界访问了
	{
		*p = 0;
		p++;
	}
}

3. The space pointed to by the pointer is released 

int* test6()
{
	int a = 10;
	return &a;
}

int main()
{
	int *p = test6();//p就是一个野指针
	return 0;
}

When the call to test6() ends, the space created by the local variable a will be destroyed, and the address recorded by *p is meaningless at this time.

3.2 How to avoid wild pointers

1. Pointer initialization

2. Beware of pointer out of bounds

3. The pointer points to the space to be released and set to NULL in time

4. Avoid returning the address of a local variable

5. Check the validity of the pointer before use

4. Pointer arithmetic

4.1 Pointer + - Integer

void test8()
{
	char arr[] = { 'a', 'b', 'c', 'd' };
	char* p = arr;
	int i = 0;
	for (i = 0; i < 4; i++)
	{
		printf("%c\n", *p++);//++优先级高于*
	}
	/*int i = 0;
	for (i = 0; i < 4; i++)
	{
		printf("%c\n", *(p+i)); // a b c d
	}*/
}
#define N_VALUES 5
float values[N_VALUES];
float *vp;
//指针+-整数;指针的关系运算
for (vp = &values[0]; vp < &values[N_VALUES];)
{
     *vp++ = 0;
}

Note: the pointer can also be larger than the size

4.2 Pointer-Pointer

Pointer - the pointer gets the number of elements between the pointer and the pointer
Precondition: two pointers point to the same space

void test9()
{
	char ch[5] = { 0 };
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", &arr[9] - &arr[0]); //9
	printf("%d\n", &arr[9] - &ch[0] ); //err
	//指针 - 指针 得到的是指针和指针之间的元素个数
	//前提条件:两个指针指同一块空间
}

 For example: find the length of a string

int my_strlen(char* str)
{
	char* start = str;
	while (*str != '\0')
	{
		str++;
	}
	return str - start;
	
	/*int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;*/
}

void test10()
{
	char arr[] = "abcdef";
	//int len = strlen(arr);
	int len = my_strlen(arr);
	
	printf("%d\n", len);

}

int main()
{
	test10();
	return 0;
}

 4.3 Relational operations on pointers

Known: The array is stored continuously, and as the index of the array grows, the address changes from low to high

void test12()
{
	#define N_VALUES 5
	float values[N_VALUES];
	float* vp;

	for (vp = &values[N_VALUES]; vp > &values[0];)
	{
		*--vp = 0;
	}
 
}

It can be simplified like this:

for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--)
{
	*vp = 0;
}

In fact, the task can be successfully completed on most compilers, but we should avoid writing this because the standard does not guarantee that it will work.

standard regulation:

Comparison of a pointer to an array element with a pointer to a memory location after the last element of the array is allowed , but comparison with a pointer to a memory location before the first element is not allowed .

5. Pointers and arrays 

What is the array name? Let's look at an example

void test13()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	printf("%p\n", arr);
	printf("%p\n", &arr[0]);
}

operation result:

It can be seen that the array name and the address of the first element of the array are the same .

Conclusion: The array name represents the address of the first element of the array. (two exceptions, 1.&arrayname, 2.sizeof(arrayname))

Then it is possible to write code like this:

void test14()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int* p = arr;//p存放的是数组首元素的地址
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d\n", *(p + i));
	}
}

Are arrays pointers? NO

Are pointers an array? NO

However, arrays can be accessed through pointers

6. Secondary pointer

void test15()
{
	int a = 10;

	int* pa = &a;

	int* * ppa = &pa;//此时的ppa为二级指针

    int** * pppa = &ppa;//pppa为三级指针
}

 For the above code: The address of a is stored in pa, and the address of pa is stored in ppa. pa is a first-level pointer, ppa is a second-level pointer

The operations for secondary pointers are:

*ppa finds pa by dereferencing the address in ppa, and *ppa actually accesses pa 

int b = 20;
*ppa = &b;//等价于 pa = &b;

**ppa first finds pa through *ppa, and then dereferences pa: *pa, that finds a 

**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;

7. Array of pointers

Is an array of pointers a pointer or an array? Answer: It is an array . is an array of pointers .

arrays we already know

The integer array int arr1[10] stores 10 integers

The character array char arr2[6] stores 6 characters

What about an array of pointers?  What is int* arr3[5] ?

arr3 is an array with five elements, each element is an integer pointer .

void test16()
{
	int a = 10;
	int b = 20;
	int c = 30;
	int* arr3[5] = { &a, &b, &c };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%d\n", *arr3[i]);//arr3存放a,b,c的地址,解引用即可访问
	}
}

Guess you like

Origin blog.csdn.net/m0_62934529/article/details/123517249