目录
指针是C语言显著的优点之一,使用起来十分灵活而且能提高某些程序的效率,但是如果使用不当 则很容易造成系统错误。许多程序“挂死”往往都是由于错误地使用指针造成的。
一、地址与指针
系统的内存就好比是带有编号的小房间,如果想使用内存就需要得到房间号。
什么是地址?地址就是内存区中对每个字节的编号
那指针是什么呢?
这里仅将指针看作是内存中的一个地址,多数情况下,这个地址是内存中另一 个变量的位置
在程序中定义了一个变量,在进行编译时就会给该变量在内存中分配一个地址,通过访问这个地址可 以找到所需的变量,这个变量的地址称为该变量的“指针”
如上图地址1000是变量i的指针
变量i的地址是变量i和指针p二者之间连接的纽带
&i表示变量i的地址
“*”表示该变量是一个指针变量
二、指针变量赋值法
//定义指针变量的同时就进行赋值
int a;
int *p=&a;
//先定义指针变量,再赋值
int a;
int *p;
p=&a;
注意:不允许把一个数赋值给指针变量
案例
#include<stdio.h>
main()
{
int a, b;
int *p1, *p2; /*声明两个指针变量*/
scanf("%d,%d", &a, &b); /*输入两个数*/
p1 = &a;
p2 = &b; /*将地址赋给指针变量*/
printf("The number is:%d,%d\n", *p1 , *p2);
}
三、引用指针变量
#include<stdio.h>
main()
{
int *p,q;
printf("please input:\n");
scanf("%d",&q); /*输入一个整型数据*/
p = &q;
printf("the number is:\n");
printf("%d\n",*p); /*输出变量的值*/
}
四、“&”和“*”运算符
#include<stdio.h>
main()
{
long i;
long *p;
printf("please input the number:\n");
scanf("%ld",&i);
p=&i;
printf("the result1 is: %ld\n",&*p); //输出变量i的值
printf("the result2 is: %ld\n",&i); //输出变量i的值
}
printf("&a:%d\n", &a);//&的作用是是返回操作数地址的单目运算符
printf("*p:%d\n", *p);//*的作用是返回指定的地址内的变量的值
程序运行结果如下图所示:
指针自加自减运算
指针的自加自减运算不同于普通变量的自加自减运算,并非简单地加1减1
整形变量,指针p++;不是简单的在地址加一,而是指向下一个存放整型变量的地址
变量i是整形变量,所以执行P++后,p的值增加了4(4个字节)
短整型,执行p++后,p的值增加了2
五、常用的指针类型
字符型
char ch='w';
char *pc=& ch;//pc指向字符变量
//把字符串第一个字符h的地址给p
//const char*p="hello world";
char *pc="hello world";//常量区
"const char *”类型的值不能用于初始化"char *”类型的实体
//const修饰常量字符串时不可修改
char str1[] = "he1lo world";
char str2[] = "he1lo world";
const char* str3 = "he1lo world";
const char* str4 = "he1lo world";
if (str1 == str2)
printf("str1 == str2\n");
else
printf("str1 <> str2\n");
if (str3 == str4)
printf("str3 == str4\n");
else
printf("str3 <> str4\n");
指针指向字符串首元素的地址
指针数组:存放指针的数组
char* arr[5];//存放字符指针的数组
int* arr2[4];//存放整型指针的数组
数组指针:指向数组的指针
int arr[10] = { 0 ,1,2,3,4};
int* p = arr;//数组首元素地址
这里arr是数组名,也就是数组的首地址,把它付给指针变量p,也就是 数组arr的首地址付给p
也可以如下形式
int *p,arr[10];
p=&arr[0];
实例
#include<stdio.h>
int main()
{
int* p, * q, a[5], b[5];
p = &a[0];
q = b;
printf("please input array a:\n");
int i = 0;
for (i = 0; i < 5; i++)
{
scanf("%d", &a[i]);
}
printf("please input array b:\n");
for (i = 0; i < 5; i++)
{
scanf("%d", &b[i]);
}
printf("\n");
printf("array a is:\n");
for (i = 0; i < 5; i++)
{
printf("%d ", *(p + i));
}
printf("\n");
printf("array b is:\n");
for (i = 0; i < 5; i++)
{
printf("%d ", *(q + i));
}
printf("\n");
return 0;
}
程序运行结果如下图所示:
利用++运算可以把语句改为
for (i = 0; i < 5; i++)
{
printf("%d ", *q++);
}
数组名是首元素地址的例外:
1、sizeof(数组名) 计算整个数组的大小/字节
2、&(数组名) :取整个数组的地址
六、二维数组与指针
&a[0][0]既可以看作二维数组的首地址,又可以看作数组0行0列的首地址
a[0]+n表示第0行第n个元素的地址
示例如下
#include<stdio.h>
int main()
{
int a[3][5] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 },i,j;
printf("array is :\n");
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d ", *(a[i] + j));
}
printf("\n");
}
return 0;
}
依然可以利用指针的++运算把语句改为
#include<stdio.h>
int main()
{
int a[3][5] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 },i,j;
printf("array is :\n");
int* p = a;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d ", *p++);
}
printf("\n");
}
return 0;
}
七、字符串与指针
使用字符指针指向一个字符串
#include<stdio.h>
int main()
{
char* string = "hello suryxin";
printf("%s", string);
return 0;
}
注意:只是把该字符串的第一个字符的地址赋给指针变量string
依旧等价于如下语句
char *string;
string="hello suryxin";
实例如下:
首先让指针指向两个数组的首元素字符的地址,然后把p1的值赋给p2,p1、p1 都加1,循环直到*p1的值为"\0"为止
#include<stdio.h>
int main()
{
char str1[] = "hello suryxin";
char str2[30], * p1, * p2;
p1 = str1;
p2 = str2;
while (*p1 != '\0')
{
*p2 = *p1;
p1++;
p2++;
}
*p2 = '\0';
puts(str2);
return 0;
}
八、字符串数组
字符串数组是以字符串作为数组元素的数组
可以看成一个二位字符数组
#include<stdio.h>
int main()
{
char str[3][20] = { "hello","suryxin","hhhaha" };
for (int i = 0; i < 3; i++)
{
printf("%s\n", str[i]);
}
return 0;
}
九、指向指针的指针
整型变量i的地址是&i,将其值传递给指针p1,即p1指向i;将p1的值传递给指针p2,即p2指向p1
p2就是所谓指向指针的指针
#include<stdio.h>
int main()
{
int * * p;
//定义一个指针变量p,指向另一个指针变量,该指针变量有指向一个基本整型变量
//由指针运算符从右向左结合,所以等同于 int * (*p);
return 0;
}
实例:指向指针变量的指针变量的应用
#include<stdio.h>
int main()
{
char *str[]= { "hello","suryxin","hhhaha" };
char** p;
for (int i = 0; i < 3; i++)
{
p = str + i;
printf("%s\n", *p);
}
return 0;
}
十、返回指针值的函数
int *fun(int x,int y)
实例:求长方形面积
使用返回值为指针的函数(自定义)
将指向长方形周长的变量的指针变量返回;
#include<stdio.h>
int* per(int a, int b);
int perimeter;
void main()
{
int* iResult;
iResult = per(100, 30);
printf("iResult is:\n%d", *iResult);
}
int* per(int a, int b)
{
int* p;
p = &perimeter;
perimeter = (a + b) * 2;
return p;
}
十一、本章实例
1. 编程实现将数组中的元素值按照相反顺序存放。
#include<stdio.h>
void main()
{
int i, t, a[10];
printf("please input:\n");
for (i = 0; i < 10; i++)
scanf("%d", &a[i]);
printf("\nthe array is:\n");
for (i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
printf("\n");
for (i = 0; i < 5; i++)
{
t = a[i];
a[i] = a[9 - i];
a[9 - i] = t;
}
printf("\n");
printf("Now the array is:\n");
for (i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
}
2. 输入两个字符串,将这两个字符串连接后输出。
#include<stdio.h>
#include<string.h>
void main()
{
char str1[60], str2[30];
printf("please input string1:\n");
gets(str1);
printf("please input string2:\n");
gets(str2);
strcat(str1, str2);
printf("the string1 is:\n");
puts(str1);
}
3. 使用指针实现字符串的复制,并将字符串输出。
#include<stdio.h>
#include<string.h>
void main()
{
char str1[30], str2[30];
char* p1, * p2;
p1 = str1;
p2 = str2;
printf("please input string1:\n");
gets(str1);
while (*p1 != '\0')
{
*p2 = *p1;
p1++;
p2++;
}
*p2 = '\0';
printf("the string2 is:\n");
puts(str2);
}