指针
一些思考
关于变量值互换,我们考虑使用指针与不使用指针的差异。
#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';//错误