指针(C语言)

文章目录

  • 1 指针是什么
  • 2 指针和指针类型
    • 2.1 指针+-整数
    • 2.2 指针的解引用
  • 3 野指针
    • 3.1 指针未初始化
    • 3.2 指针越界访问
    • 3.3 指针指向的空间释放
    • 3.4 避免野指针
  • 4 指针运算
    • 4.1 指针±整型
  • 4.2 指针减指针
  • 5 指针和数组
  • 6 二级指针
  • 7 指针数组


1 指针是什么

  • 指针是内存中一个最小单元(1字节byte)编号,也就是地址
  • 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
  • 我们可以通过&(取地址操作符)取出变量的内存 (起始地址),把地址可以存放到一个变量中,这个变量就是指针变量
int a = 10;
int * pa = &a;
*pa = 20;
printf("%d\n", a);

20

指针(C语言)_第1张图片

  • 存放在指针中的值都被当成地址处理
  • 对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0),有2的32次方个地址. 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节.那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。
    指针(C语言)_第2张图片

2 指针和指针类型

指针的定义方式是: type + *

	int* pa;
	char* pc;
	float* pf;

	printf("%d\n", sizeof(pa));
	printf("%d\n", sizeof(pc));
	printf("%d\n", sizeof(pf));

4
4
4

在x86下,指针变量的大小都是4.

2.1 指针±整数

int main()
{
	int a = 0x11223344;
	//int*pa = &a;
	//*pa = 0;
	char* pc = &a;
	*pc = 0;

	return 0;
}

指针(C语言)_第3张图片
指针(C语言)_第4张图片
指针(C语言)_第5张图片
因为用char*,解引用的时候只能访问1个字节,只能修改44.

2.2 指针的解引用

int main()
{
	int a = 0x11223344;
	int*  pa = &a;
	char* pc = &a;

	printf("pa=%p\n", pa);
	printf("pc=%p\n", pc);

	printf("pa+1=%p\n", pa -1);
	printf("pc+1=%p\n", pc -1);

	return 0;
}

pa=00AFF7EC
pc=00AFF7EC
pa+1=00AFF7E8 //减4
pc+1=00AFF7EB //减1

指针(C语言)_第6张图片

  • 数组名作指针
	int arr[10] = { 0 };
	int* p = arr;//数组名就是数组首元素的地址arr->&arr[0];

	for (int i = 0; i < 10; i++)
	{
		*(p + i) = i + 1;
	}

指针(C语言)_第7张图片

	int arr[10] = { 0 };
	char* p = arr;
	
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*p = i + 1;
		p++;
	}

指针(C语言)_第8张图片
可以看见用char类型解引用整型数组是不对的.01 02 03 04对应arr[0] = 67305985.

3 野指针

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

3.1 指针未初始化

	int* p;
	*p = 20;

指针(C语言)_第9张图片

3.2 指针越界访问

int main()
{
	int arr[10] = {0};
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = arr;
	for (i = 0; i <= sz; i++)
	{
		*p = i;
		p++;
	}

	return 0;
}

Run-Time Check Failure #2 - Stack around the variable 'arr' was corrupted.

3.3 指针指向的空间释放

int* test()
{
	int num = 100;
	printf("%p\n", &num);
	return &num;
}

int main()
{
	int* p = test();
	*p = 200;
	printf("%d\n", *p);
	printf("%p\n", p);

	return 0;
}


010FF754
200
010FF754

3.4 避免野指针

int main()
{
	int a = 10;
	int* pa = &a;
	int* p = NULL;

	return 0;
}
  • 判断为NULL
	int a = 10;
	//int* p = NULL;
	//*p = 20;

	int* p = &a;

	if (p != NULL)
	{
		printf("%d\n", *p);
	}
	
10

4 指针运算

4.1 指针±整型

	double arr[5] = {0};
	double* p = arr;
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%lf ", *(p + i));
	}
0.000000 0.000000 0.000000 0.000000 0.000000
  • 注意浮点%f
#define N_VALUES 5
float values[N_VALUES];
float* vp;

int main()
{
	for (vp = &values[N_VALUES - 1]; vp >= &values[0]; vp--)
	{
		*vp = 1;
	}
	for (int i = 0; i < N_VALUES; i++)
	{
		printf("%f\n", values[i]);
	}
	return 0;
}

1.000000
1.000000
1.000000
1.000000
1.000000

实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行。

4.2 指针减指针

两个指针相减的前提是:指针指向的同一块连续的空间

	int arr[10] = {0};
	printf("%d\n", &arr[9] - &arr[0]);
	printf("%d\n", &arr[0] - &arr[9]);

	int a = 10;
	char c = 'w';
	printf("%d\n", &a - &c);//err
9
-9
2

5 指针和数组

  • 指针为NULL判断结束
int my_strlen1(char* str)
{
	int count = 0;
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}


int my_strlen2(char* str)
{
	char* start = str;
	while (*str)
		str++;
	return str - start;
}
//
int main()
{
	char arr[] = "abc";
	int len1 = my_strlen1(arr);
	int len2 = my_strlen2(arr);
	printf("%d\n", len1);
	printf("%d\n", len2);

	return 0;
}

3
3
  • 指针访问数组元素
    指针(C语言)_第10张图片
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);

	for (i = 0; i < sz; i++)
	{
		printf("%d\n", *(p + i));
	}

1
2
3
4
5
6
7
8
9
10

6 二级指针

  • p就是指针变量,一级指针变量
  • pp二级指针
int main()
{
	int a = 10;//
	int* p = &a;//
	int** pp = &p;//

	//*(*pp) = 200;
	**pp = 200;
	//*p = 20;
	printf("%d\n", a);

	return 0;
}

200

指针(C语言)_第11张图片

7 指针数组

指针数组是指针还是数组?答案:是数组。是存放指针的数组。

	int arr[10];
	char arr2[5];
	int* arr3[5];//存放整型指针的数组
	char* arr4[6];//存放字符指针的数组
  • 1
	int a = 10;
	int b = 20;
	int c = 30;
	int d = 40;
	int e = 50;

	int* arr3[5] = {&a, &b, &c, &d, &e};//存放整型指针的数组
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", *(arr3[i]));
	}
10 20 30 40 50
  • 用一维数组模拟一个二维数组
    指针(C语言)_第12张图片
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };
	int arr4[] = { 4,5,6,7,8 };

	int* arr[4] = {arr1, arr2, arr3, arr4};
	int i = 0;
	for (i = 0; i < 4; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", *(*(arr+i)+j));
		}
		printf("\n");
	}

1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8

上面的打印可以写为

	int i = 0;
	for (i = 0; i < 4; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}```

你可能感兴趣的:(C初阶,c语言)