C语言指针的基本用法

1.指针定义:是编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方  的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为指针。

#include<stdio.h>
int main()
{
	int a = 10;  //在内存中开辟一个空间
	int* p = &a; //这里我们对变量a,取出它的地址,可以使用&操作符
	             //将a的地址存放到p变量中,p就是一个指针变量
	return 0;
}

指针就是变量,用来存放地址的变量(存放在指针中的值都被当成地址处理)
指针是用来存放地址的,地址是唯一标识一块地址空间的
指针的大小在32位平台是4个字节,在64位平台是8个字节

#include<stdio.h>
int main()
{
	int a = 0x11223344;
	char *pc = &a;
	*pc = 0;
	return 0;
}

指针类型决定了指针进行解引用操作的时候,能够访问空间的大小
int* p;    *p能访问4个字节
char* p;   *p能访问1个字节
double* p; *p能访问8个字节
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。比如:char *的指针解引用就只能访问一个字节,而int *的指针能访问4个字节

#include<stdio.h>
int main()
{
	int a = 0x11223344;
	int* pa = &a;
	char* pc = &a;
	printf("%p\n", pa);   
	printf("%p\n", pa+1); +4
	printf("%p\n", pc);
	printf("%p\n", pc+1); +1
	return 0;
}  
//指针类型决定了:指针走一步走多远(指针的步长)

2. 野指针:指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)

在指针的使用中,往往造成错误最多的就是出现了野指针,因此在使用指针时一定要注意野指针,三种野指针示例如下:

#include<stdio.h>
int main()
{
	int a;//局部变量不初始化,默认是随机值
	int* p;//局部的指针变量,就被初始化随机值
	*p = 20;
	return 0;
}
#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	int* p = arr;
	int i = 0;
	for (i = 0; i < 12; i++)
	{
		p++;//当指针指向的范围超出数组arr的范围时,p就是野指针
	}
	return 0;
}
#include<stdio.h>
int* test()
{
	int a = 10;
	return &a;
}
int main()
{
	int* p = test();
	*p = 20;  //指针指向的空间释放
	return 0;
}

那该如何规避野指针呢?有两种方法

(一)指针初始化,小心指针越界

#include<stdio.h>
int main()
{
	int a = 10;
	int* pa = &a;//初始化
	int* p = NULL;//NULL用来初始化指针的,给指针赋值
}

(二)指针指向空间释放即使置NULL,指针使用之前检查有效性

#include<stdio.h>
int main()
{
	int a = 10;
	int* pa = &a;
	*pa = 20;
	pa = NULL;//使置NULL
	//
	if (pa != NULL)
	{

	}
}

3.指针运算

   1)指针+-整数

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int i = 0;
	int sz = sizeof(arr)/ sizeof(arr[0]);
	int* p = arr;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *p);
		p = p + 1;
	}
}

    2) 指针-指针(得到的是指针中间的元素个数,前提是在同一块空间内进行)

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", & arr[9] - &arr[0]);
	return 0;
}
#include<stdio.h>
int my_strlen(char* str)
{
	char* start = str;
	char* end = str;
	while (*end != '\0')
	{
		end++;
	}
	return end - start;//指针-指针
}
int main()
{
	//strlen -求字符串长度
	//递归 -模拟实现了strlen -计数器的方式1,递归的方式2
	//
	char arr[] = "bit";
	int len=my_strlen(arr);
	printf("%d\n", len);
	return 0;
}

4.指针和数组

  1) 指针

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", & arr[0]);
	//&arr - &数组名-数组名表示整个数组,&数组名,取出的是整个数组的地址
	printf("%p\n", &arr);
	//sizeof(arr) - sizeof(数组名)表示整个数组 -sizeof(数组名)表示整个数组的大小
	return 0;
}

&arr - &数组名-数组名表示整个数组,&数组名,取出的是整个数组的地址

sizeof(arr) - sizeof(数组名)表示整个数组 -sizeof(数组名)表示整个数组的大小

除以上两种情况外,所有取数组名取的是该数组的首元素地址

#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	int* p = arr;//指针存放数组首元素的地址
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}
	//for (i = 0; i < 10; i++)
	//{
	//	printf("%p   =====   %p\n", p + i, &arr[i]);
	//}
}

     2)二级指针

#include<stdio.h>
int main()
{
	int a = 10;
	int* pa = &a;
	int** ppa = &pa;//ppa就是一个二级指针
	printf("%d\n", *ppa);
	return 0;
}

    3) 指针数组,是用来存放指针的数组

#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	int c = 30;
	int* arr[3] = { &a,&b,&c };//指针数组
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%d ", *(arr[i]));
	}
	return 0;
}

5. 指针练习题

1)写一个函数求a的二进制(补码)表示中有几个1

方法一

#include<stdio.h>
int count_bit_one(unsigned int n)
{
	int count = 0;
	while (n)
	{
		if (n % 2 == 1)
		{
			count++;
		}
		n = n / 2;
	}
	return count;
}
int main()
{
	int a = 0;
	scanf("%d", &a);
	int count=count_bit_one(a);
	//13
	//00000000000000000000000000001101
	//
	printf("count=%d\n", count);
	return 0;
}

方法二

#include<stdio.h>
int count_bit_one(unsigned int n)
{
 int count=0;
 while(n)
 {  n=n&(n-1);
   count++;
 }
 return count;  
}
int main()
{
	int a = 0;
	scanf("%d", &a);
	int count=count_bit_one(a);
	//13
	//00000000000000000000000000001101
	//
	printf("count=%d\n", count);
	return 0;
}

2)求二进制中不同位的个数 比如两个整型数的二进制表达中,有多少个比特位不同

#include<stdio.h>
int get(int m, int n)
{
	int tmp = m ^ n;
	int count = 0;
	while (tmp)
	{
		tmp = tmp & (tmp - 1);
		count++;
	}
	return count;
}
int main()
{
	int m = 0;
	int n = 0;
	scanf("%d%d", &m, &n);
	int count = get(m,n);
	printf("count=%d\n", count);
	return 0;
}

3)打印二进制的奇数位和偶数位,分别进行打印序列

#include<stdio.h>
void print(int m)
{
	int i = 0;
	printf("奇数位:\n");
	for (i = 30; i >= 0; i -= 2)
	{
		printf("%d", (m >> i) & 1);
	}
	printf("\n");
	printf("偶数位:\n");
	for (i = 31; i >= 1; i -= 2)
	{
		printf("%d", (m >> i) & 1);
	}
	printf("\n");
}
int main()
{
	int m = 0;
	scanf("%d", &m);
	print(m);
}

4)使用指针打印数组内容

#include<stdio.h>
void print(int* p, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}
}
int main()
{
	int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	print(arr, sz);
}

5)实现字符串的逆序

方法一

#include<stdio.h>
#include<string.h>
void reverse(char arr[])
{
	int left = 0;
	int right = strlen(arr) - 1;
	while (left < right)
	{
		int tmp = arr[left];
		arr[left] = arr[right];
		arr[right] = tmp;
		left++;
		right--;
	}
}
int main()
{
	char arr[] = "abcdef";
	reverse(arr);
	printf("%s\n", arr);
	return 0;
}

方法二、不使用库函数strlen实现字符串的逆序

#include<stdio.h>
int my_strlen(char* str)
{
	int count = 0;
	while (*str != '0')
	{
		count++;
		str++;
	}
	return count;
}
void reverse(char arr[])
{
	int left = 0;
	int right = my_strlen(arr) - 1;
	while (left < right)
	{
		int tmp = arr[left];
		arr[left] = arr[right];
		arr[right] = tmp;
		left++;
		right--;
	}
}
int main()
{
	char arr[] = "abcdef";
	reverse(arr);
	printf("%s\n", arr);
	return 0;
}

方法三、不使用库函数并使用递归的方法实现对字符串的逆序

#include<stdio.h>
int my_strlen(char* str)
{
	int count = 0;
	while (*str != '0')
	{
		count++;
		str++;
	}
	return count;
}
void reverse_string(char* arr)
{
	char tmp = arr[0];
	int len = my_strlen(arr);
	arr[0] = arr[len - 1];
	arr[len - 1] = '\0';
	if (my_strlen(arr + 1) >= 2)
		reverse_string(arr + 1);
	arr[len - 1] = tmp;
}
int main()
{
	char arr[] = "123";
	reverse_string(arr);
	printf("%s\n", arr);
	return 0;
}

6)输入一个数,计算各位数之和

#include<stdio.h>
int DigitSum(unsigned int num)
{
	if (num > 9)
	{
		return DigitSum(num / 10) + num % 10;
	}
	else
		return num;
}
int main()
{
	unsigned int num = 0;
	scanf("%d", &num);
	int ret = DigitSum(num);
	printf("ret=%d\n", ret);
}

7)定义一个数组,将数组置为0,并且将数组的内容逆序输出

#include<stdio.h>
void Init(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		arr[i] = 0;
	}
}
void print(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void reverse(int arr[], int sz)
{
	int left = 0;
	int right = sz - 1;

	while (left<right)
	{
		int tmp = arr[left];
		arr[left] = arr[right];
		arr[right] = tmp;
		left++;
		right--;
	}
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//Init(arr, sz);//把数组初始化为0
	print(arr, sz);
	reverse(arr,sz);
	print(arr, sz);
	return 0;
}

8)把数组a和数组b的元素进行交换

#include<stdio.h>
int main()
{
	int arr1[] = { 0,1,2,3,4,5 };
	int arr2[] = { 9,8,7,6,5,4 };
	int tmp = 0;
	int i = 0;
	int sz = sizeof(arr1) / sizeof(arr1[0]);
	for (i = 0; i < sz; i++)
	{
		tmp = arr1[i];
		arr1[i] = arr2[i];
		arr2[i] = tmp;
	}
	printf(arr1[i],arr2[i]);
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值