C语言----指针

一、概念

简单的来说,指针就是地址。我们口头上说的指针其实指的是指针变量。指针变量就是一个存放地址的变量。

从语法的角度看,只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。
 

(1)int*p;     //指针的类型是int*
(2)char*p;    //指针的类型是char*
(3)int**p;    //指针的类型是int**

当指针保存了保存了变量地址,我们称指针指向该变量。

   *     是指针运算符,单目运算符,优先级为二级,结合方向是自右向左。

当我们在定义一个指针时:int *p;这里的 * 只是说明p是指针类型,并无指针运算。

指针的主要功能是通过被调函数修改主调函数。

void fn(int *p)
{
	*p += 1;
}

指针在程序中只干三件事:

1.根据指针变量中的值到内存中定位。

2.从定位处开始向后偏移sizeof(基类型)

3.整体的将偏移好的那部分内存当作是一个基类型的变量。

*p总是要与基类型的类型匹配。

野指针与疯指针:是指对未经初始化的变量进行指针运算,其指向的位置不可知。当使用指针对数组越界访问时也会出现野指针,导致程序崩溃。

在做关系运算时:&*与*&总是可以相互抵消,但是要注意的点是:*运算要求其对象必须是指针。

	int i = 10;
	int *p = &i;

	printf("%p\n", &*p);
	printf("%d\n", *&i);
	printf("%p\n", *&p);
//X	printf("%d\n", &*i); 

当我们在定义了一个指针后,写出下代码:

int *p;
p + n;

其并不是在原有的地址上加n,而是在原有的地址上加 n * sizeof(基类型)。

空指针:在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 。 赋为 NULL 值的指针被称为空指针。 *p = NULL 是将指针置空,是一种状态。

指针与指针之间是无法进行加法运算的,但是可以进行减法运算,但是求差的时候指针的基类型必须相同。求差的结果是指两个指针之间差了多少个基类型,结果可正可负,负数的含义就是地址在前。

	int a[] = {1,2,3,4,5,6,7,8,9,0};
	int *p = a;
	int *q = a + 2;

	printf("%ld\n" ,p - q);

 const的作用:

1.当const加在变量之前时,表示该变量为只读变量,只可读取,不可更改。

2.当const加在指针前时:如const int *p表示不能通过该指针修改其所指向的的变量。当是

int const *p时,表示指针不可更改。

void* 为万能指针,不能作为指针进行指针运算。

二、指针的使用

1.通过指针的方式实现求三个数的最大值

void maxOfTwoNumbers(int a, int b, int *pMax)
{
	*pMax = a > b ? a : b;
}

void maxMinOfThreeNumbers(int a, int b, int c, int *pMax, int *pMin)
{
	*pMax = a > b ? a : b;
	*pMax = *pMax > c ? *pMax : c;
	*pMin = a < b ? a : b;
	*pMin = *pMin < c ? *pMin : c;
}

2.通过指针的方式交换两个数

void swap(int *a, int *b)
{
    int k;
	k = *a;
	*a = *b;
	*b = k;
}

3.实现对大端存储与小端存储的判断

	int i = 0x12345678;
	char *p;
	p = (char *)&i;

	if(1 == *p)
	{
		puts("little");
	}
	else
	{
		puts("big");
	}

4.通过指针实现对一维数组的遍历

void printArray(int *a, int len)
{
	int i;
	for(i = 0;i < len;++i)
	{
		printf("%d\n", *(a + i));
	}
}

5.通过指针实现对一维数组求和

int sumOfArray(int *a, int len)
{
	int sum = 0, i;
	for(i = 0;i < len;++i)
	{
		sum += *(a + i);
	}
	return sum;
}

6.通过指针实现对一维数组的逆序

void reverse(int *a, int len)
{
	int i;
	for(i = 0;i < len / 2;++i)
	{
		swap(a + i, a + len - i - 1);
	}
}

7.通过指针对一维数组排序(选择排序)

void sort(int *a, int len)
{
	int i, j;
	for(i = 0;i < len - 1;++i)
	{
		for(j = i + 1;j < len;++j)
		{
			if(*(a + i) > *(a + j))
			{
				swap(a + i, a + j);
			}
		}
	}
}

8.通过指针的方式实现对一维数组的二分查找

int *binaryFind(int *a, int len, int n)
{
	int begin = 0;
	int end = len - 1;
	while(begin <= end)
	{
		int mid = (begin + end) / 2;
		if(*(a + mid) < n)
		{
			begin = mid + 1;
		}
		else if(*(a + mid) > n)
		{
			end = mid - 1;
		}
		else
		{
			return a + mid;
		}
	}
	return NULL;
}

9.通过递归与指针实现数组遍历

void printArray(int *begin, int *end)
{
	if(begin > end)
	{
		return ;
	}
	else
	{
		printf("%d\n", *begin);
		printArray(begin + 1, end);
	}

10.使用递归与指针实现数组逆序

void reverse(int *begin, int *end)
{
	if(begin >= end)
	{
		return ;
	}
	else
	{
		swap(begin, end);
		reverse(begin + 1, end - 1);
	}

11.通过指针实现对数组的选择排序

void choiceSort(int *begin, int *end)
{
	int *p;
	for(;begin < end;++begin)
	{
		for(p = begin + 1;p <= end;++p)
		{
			if(*begin > *p)
			{
				swap(begin, p);
			}
		}
	}
}

12.通过指针与递归实现快速排序

void qSort(int *begin, int *end)
{
	if(begin > end)
	{
		return ;
	}
	int t = *begin;
	int *p = begin;
	int *q = end;

	while(p < q)
	{
		while(p < q && *q >= t)
		{
			--q;
		}
		while(p < q && *p <= t)
		{
			++p;
		}
		swap(p, q);
	}
	swap(begin, p);
	qSort(begin, p - 1);
	qSort(p + 1, end);

}

13.puts

void Puts(const char *s)
{
	while(*s)
	{
		putchar(*s++);
	}
	putchar('\n');
}

14.strle

int Strlen(const char *s)
{
	if(*s == '\0')
	{
		return 0;
	}
	else
	{
		return Strlen(s + 1) + 1;
	}

15.strcpy与Memcpy

char *Strcpy(char *dest,const char *src)
{
	char *ret = dest;
	while(*src)
	{
		*dest++ = *src++;
	}
	*dest = 0;
	return ret;
}

void *Memcpy(void *dest, const void *src, unsigned long n)
{
	char *p = (char *)dest;
	char *q = (char *)src;
	while(n)
	{
		*p++ = *q++;
		--n;
	}
	return dest;
}

16.strcat与strncat

char *Strcat(char *dest, const char *src)
{
	char *ret = dest;
	while(*dest)
	{
		++dest;
	}
	while(*src)
	{
		*dest++ = *src++;
	}
	*dest = 0;
	return ret;
}

char *Strncat(char *dest, const char *src, unsigned long n)
{
	char *ret = dest;
	while(*dest++)
	{
		
	}
	while(*src && n)
	{
		*dest++ = *src++;
		--n;
	}
	*dest = 0;
	return ret;

}

17.strcmp与strncmp

int Strcmp(const char *s1, const char *s2)
{
	while(*s1 == *s2 && *s1 && *s2)
	{
		++s1;
		++s2;
	}
	return *s1 - *s2;
}

int Strncmp(const char *s1, const char *s2, unsigned long n)
{
	while(--n && *s1 == *s2 && *s1 && *s2)
	{
		++s1;
		++s2;
	}
	return *s1 - *s2;
}

  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值