C语言指针详细介绍

一些思考

关于变量值互换,我们考虑使用指针与不使用指针的差异。

#include<stdio.h>
 
void change(int *a, int *b)
{
	int temp;
	temp = *a;
	*a = *b;
	*b = temp;
}
 
void main()
{
	int a = 10, b = 100;
	//方法一:使用中间变量
	//注意当使用中间变量且没有指针时,采用方法二的方法会造成形参互换值成功而实参没有互换值,得不到想要的结果
	int temp;
	temp = a;	//temp=10,a=10,b=100
	a = b;		//temp=10,a=100,b=100
	b = temp;	//temp=10,a=100,b=10
	printf("a = %d, b = %d\n", a, b);
 
	//方法二:使用指针,封装函数
	a = 10;
	b = 100;
	change(&a,&b);
	printf("a = %d, b = %d\n", a, b);
 
	//方法三:使用异或运算
	a = 10;		//二进制:00001010
	b = 100;	//二进制:01100100
	a = a ^ b;	//a=01101110(110),b=01100100(100)
	b = a ^ b;	//a=01101110(110),b=00001010(10)
	a = a ^ b;	//a=01100100(100),b=00001010(10)
	printf("a = %d, b = %d", a, b);
	getchar();

通过指针引用数组元素对比

//下标法
#include<stdio.h>
int main()
{
	int i;
	int a[10];
	printf("please input 10 numbers:");
	for (i = 0;i < 10;i++)
	{
		scanf_s("%d", &a[i]);
	}
	for (i = 0;i < 10;i++)
	{
		printf("%d ", a[i]);
	}
	return 0;

}

//数组名计算元素值
#include<stdio.h>
int main()
{
	int i;
	int a[10];
	printf("please input 10 numbers:");
	for (i = 0;i < 10;i++)
	{
		scanf_s("%d", &a[i]);
	}
	for (i = 0;i < 10;i++)
	{
		printf("%d ", *(a+i));
	}
	return 0;

}

//指针变量
#include<stdio.h>
int main()
{
	int i,*p;
	int a[10];
	printf("please input 10 numbers:");
	for (i = 0;i < 10;i++)
	{
		scanf_s("%d", &a[i]);
	}
	//for (p=a;p<(a+10);p++)
	//    scanf_s("%d", p);
	for (p=a;p<(a+10);p++)//先使指针变量p指向a数组的首元素,p++
	使p指向下一个元素
	{
		printf("%d ", *p);
	}
	return 0;
}

第一二种方法相同,但每次都需要计算元素的地址,费时较多
第三种方法比第一二种快,指针变量直接指向元素,不必每次都计算地址。
注意在循环中不用p变化的方法而用a变化的方法是不行的。如:for(p=a;a<(p+10);a++)
a代表数组首元素地址,是指针型常量,值是固定不变的。a++无法实现

//另外一些输出方法
for(i=0;i<10;i++,p++)
	printf("%d",*p)


for(i=0;i<10;i++)
	printf("%d",*p++)//先取p值 ,再加1


for(p=a;p<a+10;p++)
	printf("%d",*p);


//若想输出100个数字
p=a;//先使p指向某一个值
while(p<a+100)
	{printf("%d",*p);p++;}

//其他输入方法
for(i=0;i<10;i++)
	scanf("%d",p++);

调转数字顺序

#include<stdio.h>
int i, j;
int main()
{
	void cal(int* a, int n);
	void cal2(int* a, int n);
	int a[10] = { 1,3,5,2,3,6,7,8,5,9 };
	int * p;
	p = a;
	for (i = 0;i < 10;i++)
		printf("%d", *p++);
	printf("\n");
	cal(a, 10);
	p = a;
	for (i = 0;i < 10;i++)
		printf("%d", *p++);
	printf("\n第二种\n");
	//数字顺序与原来一样即为正确
	cal2(a, 10);
	p = a;
	for (i = 0;i < 10;i++)
		printf("%d", *p++);
	return 0;
}
//采用了两种调用方法
void cal(int* a, int n)
{
	int temp, m = (n - 1) / 2;
	for (i = 0;i < m;i++)
	{
		j = n - 1 - i;
		temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}
}
void cal2(int* a, int n)
{
	int* p, temp, * i, * j, m = (n - 1) / 2;
	i = a;//指定数组第一个位置
	j = a + n - 1;//1与10换,2与9换,以此类推
	p = a + m;
	for (;i <= p;i++, j--)
	{
		temp = *i;
		*i = *j;
		*j = temp;
	}

}

输出二维数组任一数值

#include<stdio.h>
int i, j;
int main()
{
	int a[3][4] = { 1,3,5,7,9,11,13,15,17,19,21,23 };
	int(*p)[4], i, j;//表示p为一个指针变量,指向包含4个元素的一维数组,一定要加括号,不加括号,含义表示不同
	p = a;
	printf("please input colunm and row:");
	scanf_s("%d%d", &i, &j);
	printf("a[%d,%d]=%d\n", i, j, *(*(p + i) + j));//主要知道表示某一行某一列元素怎么表达就行了
	return 0;
}

注意指向对象的基类型区别,p指向的是数组而不是元素。


p=a;//指向&a[0]
p=&a;//指向一维数组(即行)
(*p)[3];//指向行中序号为3的元素,如在上个例子中输入该式,
则会输出第3个元素:7(0为第一个元素)
int (*p)[4];//p的类型为int(*)[4]型,代表指向一维数组的整型变量,此一维数组有4个元素,长度为16个字节
*(p+2);//行运算得到&a[2][0],已经转化为指向列元素的指针了,若再加3;*(p+2)+3,则代表加了3*4个字节
score  //score[0]的起始地址
*score   //score[0][0]的起始地址。注意形参与实参的匹配

字符指针

#include<stdio.h>
int main()
{
char *string="hgkjjs ss";
printf("%s",string);
return 0;
}

将字符串a复制为字符串b(指针)

#include<stdio.h>
int i, j;
int main()
{
	char a[] = "I am a student.", b[20];
	int i;
	for (i = 0;*(a + i) != 0;i++)
		*(b + i) = *(a + i);
	*(b + i) = '\0';//必须要复制字符串结束标志,要不会出现乱码
	printf("string a is:%s\n", a);
	for (i = 0;*(b + i) != 0;i++)
		printf("%c", *(b+i));
	printf("\n");
	return 0;
}

将字符串a复制为字符串b(指针变量)

#include<stdio.h>
int main()
{
	char a[] = "I am a boy", b[20], * p1, * p2;
	p1 = a;
	p2 = b;
	for (;*p1 != 0;p1++, p2++)
		*p2 = *p1;
	*p2 = '\0';
	printf("The string a is:%s\n", a);
	printf("The string b is:%s\n", b);

	return 0;
}

指针作为函数参数

字符数组名作为函数参数

#include<stdio.h>
int main()
{
	void copy_string(char from[], char to[]);
	char a[] = "I like math";
	char b[] = "I like English";
	printf("The string a is:%s\n", a);
	printf("The string b is:%s\n", b);
	copy_string(a, b);//数组名作为参数
	printf("The string a is:%s\n", a);
	printf("The string b is:%s\n", b);
	return 0;
}
void copy_string(char from[], char to[])
{
	int i = 0;
	for (;from[i] != '\0';i++)
		to[i] = from[i];
	to[i] = '\0';
}

字符型指针变量作为函数参数

#include<stdio.h>
int main()
{
	void copy_string(char from[], char to[]);
	char a[] = "I like math";
	char b[] = "I like English";
	char* from = a, * to = b;
	printf("The string a is:%s\n", a);
	printf("The string b is:%s\n", b);
	copy_string(from, to);//传首元素地址实参
	printf("The string a is:%s\n", a);
	printf("The string b is:%s\n", b);
	return 0;
}
void copy_string(char from[], char to[])
{
	for (;*from != '\0';from++,to++)
		*to = *from;
	*to = '\0';
}

字符指针变量作形参和实参

#include<stdio.h>
int main()
{
	void copy_string(const char *from, char *to);
	const char *a = "I like math";//不加const,会出现如下图片出现的错误
	char b[] = "I like English";
	char* p = b;
	printf("The string a is:%s\n", a);
	printf("The string b is:%s\n", b);
	copy_string(a, p);
	printf("The string a is:%s\n", a);
	printf("The string b is:%s\n", b);
	return 0;
}
void copy_string(const char* from, char* to)
{
	for (;*from != '\0';from++, to++)
		*to = *from;
	*to = '\0';
}

在这里插入图片描述
a为字符指针变量,指向首字符。b是字符数组。p是字符指针变量,它的值是b数组首元素的地址。

字符指针变量和字符数组的比较

1.字符数组由若干个元素组成,每个元素中存放一个字符,而字符指针变量中存放的是地址。
2.可以对字符指针变量赋值,但不能对数组名赋值。
char *a;
a="ksdhks";


char str[14];
str[0]='s';//对字符数组赋值合法
str="jkhkh";//数组名为地址,是常量不能被赋值
3.初始化
char *a="hjkk";
等价于
char *a;
a="hjkk";


数组初始化
char str[14]="jsjjla";
不等价于
char str[14];
str[]="jsjjla";//企图把字符串赋给数组中各元素,错误
4.存储单元内容
char* a;//未及时把字符变量地址赋给它
scanf("%s",a);//此时向该指针变量指向的对象赋值,造成错误

正确:
char* a,str[10];
a=str;
scanf("%s",a);
5.指针变量的值可以改变,而字符数组名不能改变
char str[]={"jcsjisjsi"};
str=str+4;//错误
printf("%s",str);

char *a={"jcsjisjsi"};
a=a+4;//正确
printf("%s",a);
6.字符数组中各元素的值可以改变,但字符指针变量指向的字符串常量的内容不可以改变
char str[]="jcsjisjsi";
char *a="jcsjisjsi";
str[2]='r';//正确
a[2]='r';//错误
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

看星河的兔子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值