指针一
1. 指针就是内存单元的地址;存放地址的变量称为指针变量。
一般形式:
<存储类型> <数据类型> * <指针变量名> eg: char * pName;
数据类型:指针指向的数据类型;
int *p; int a; p = &a;
向一个指针变量赋值时,送的值必须是地址常量或者指针变量,不能是普通的整数(除了赋零)
指针的大小与操作系统的位数有关
指针算术运算表(指针运算一般与数组相结合)
指针加减得到的不是地址量,而是两指针之间相隔数据的个数、
#include<stdio.h>
int main(int argc, const char *argv[])
{
int a[5]= {4 , 5 , 9, 7, 2};
int *p,*q,*c;
q = &a[3];
p = a;
printf("%p %p\n",p,q);
printf("%d %d\n",*p,*q);
printf("%d\n",q-p);//(结果为3)
c = p++;
printf("%p %d\n",p,*p);
printf("%p %d\n",c,*c); ( *c=4,*p = 5)
return 0;
}
指针的p++等
#include<stdio.h>
int main(int argc, const char *argv[])
{
int a[] = {5 , 8 , 4,2,9};
int *p;
int y;
p = &a[1];
y = (*--p)++; (先赋值到y,然后进行++)
printf("%d\n",*p);
printf("%d\n",y);
printf("%d\n",a[0]);
return 0;
}
输出: 6 5 6 *p = a[0]
注意指针的位置:
#include<stdio.h>
int main(int argc, const char *argv[])
{
int i,*p,a[7];
p = a;
for(i = 0; i< 7;i++)
{
scanf("%d",p++);
}
printf("\n");
p = a; //作用是用来调整指针位置
for(i=0;i<7;i++)
{
printf("%d ",*p);
p++;
// printf("%d ",*p++); //证明指针具有简洁性
// printf("%d ",a[i]); (这样两种输出也可)
}
puts(""); //换行符
return 0;
}
指针与数组
数组名是常量,所以x++ 会报错
数组名与指针变量都是地址量,但是指针变量是地址变量,而数组的指针是地址常量
x[i] *(p+i) *(x+i) p[i] 具有一样的功能 : 访问数组第 i+1 个数组元素
#include<stdio.h>
int main(int argc, const char *argv[])
{
int a[] = {1,3,4,54,21,0};
int *p;
int i,n;
p = a;
n = sizeof(a) / sizeof(int);
for(i=0;i<n;i++)
{
printf("%d %d %d %d\n",a[i],*(p+i),*(a+i),p[i]);
}
return 0;
}
程序举例: 编写一个函数,将整形数组中n个数反序存放
#include<stdio.h>
#define N 5
int main(int argc, const char *argv[])
{
int a[N]= {1,2,3,4,5};
int t;
int *p,*q;
p = a;
q = a+N-1;
while(p<q)
{
t = *p;
*p = *q;
*q = t;
p++;
q--;
}
for(t = 0;t<N;t++)
{
printf("%d",a[t]);
}
puts("");
return 0;
}
指针与二维数组
二维数组的元素连续存储,按行优先存储
编程实现,使用一级指针遍历 二维数组
#include<stdio.h>
int main(int argc, const char *argv[])
{
int a[3][2] = {{1,2},{3,4},{5,6}};
int *p,i,n;
n = sizeof(a) / sizeof(int);
//p = a; 会出现警告
p =&a[0][0];//或者 p = a[0];
for(i = 0;i<n;i++)
{
printf("%d ",p[i]);
}
puts("");
return 0;
}
将二维数组看做是多个一维数组组成
二维数组名称为行地址 *(a+1) 等价于a[1] a+1走一行,a[1]+1 走一个元素大小
a[0] a[1] 同样是数组名,不可以后接++
数组指针
<存储类型> <数据类型> (* <指针变量名>)[表达式]
int (*p)[3]; 3列
编程实现,使用行指针表示二维数组 的元素a[1][1] ,并实现二维数组的遍历
#include<stdio.h>
int main(int argc, const char *argv[])
{
int a[3][2] = {{1,2},{3,4},{5,6}};
int (*p)[2],i,j;
p = a;
printf("%d %d %d %d\n",a[1][1],*(* (a+1)+1),*(*(p+1)+1),p[1][1]);
for(i = 0; i <3;i++){
for(j=0;j<2;j++)
printf("%d %d %d %d\n",a[i][j],* (*(a+i)+j),*(*(p+i)+j),p[i][j]);
puts("");
}
return 0;
}
区别就是 a是地址常量 p是地址变量
指针二
字符指针与字符串
C语言通过使用 字符数组 来处理 字符串
1.初始化字符指针是把内存中字符串的首地址赋予指针,并不是吧该字符串复制到指针
char str[] = "hello world"; (存放在栈)
char *p = str;
这种类型可以通过指针改变字符串中的字符
2.C编程中,当一个字符指针指向一个字符串常量时,不能修改指针指向的对象的值
char *p = "hello world";(hello world 为字符串常量,存放在只读数据段)
*p = 'h'; //错误,字符串常量不能修改
程序举例:
#include<stdio.h>
#include<string.h>
int main(int argc, const char *argv[])
{
char ch[] = "welcome";
char *p = "hello world";
strcpy(ch,p);
strcpy(p,ch);//会发生段错误
return 0;
}
编程实现:不利用任何字符串函数,编程实现字符串连接函数的功能
#include<stdio.h>
int main(int argc, const char *argv[])
{
char ch[100] = "welcome";
char *p = " hello world";
int i=0;
while(*(ch + i) !=0)
i++;
while(*p !=0)
{
ch[i] = *p;// *(ch+i) = *p;
p ++;
i++;
}
ch[i] = *p;
puts(ch);
puts(p);
return 0;
}
指针数组
指的是由若干个具有相同存储类型和数据类型的指针变量构成的集合
指针数组经常和二维数组结合,二维数组的每一行都可以用一个指针变量指向
数组指针需要说明二维数组的列数
<存储类型> <数据类型> *<指针数组名> [<大小> ]
double * p[2]; // double *p[0]; double *p[1];
double * p[2] ,a[2][3];
p[0] = a[0]; //等价于 p[0] = &a[0][0];
p[1] = a[1]; //等价于 p[1] = &a[1][0];
#include<stdio.h>
int main(int argc, const char *argv[])
{
int a[2][3] ={ {1,2,3},{4,5,6}};
int * p[2]; //sizeof(p)=8 因为存放了两个指针
p[0] = a[0];
p[1] = a[1];
printf("%d\n",a[0][1]);
printf("%d\n", *(a[0]+1));
printf("%d\n", *(p[0]+1));
printf("%d\n", *(p[1]-2));
return 0;
}
指针数组名加1,移动4个字节(指针大小)
指针数组名相当于二级指针
程序举例:利用指针数组处理一个二维数组,要求求出二维数组所有元素的和
#include<stdio.h>
int main(int argc, const char *argv[])
{
int a[2][3] ={ {1,2,3},{4,5,6}};
int *p[2],i,j;
int sum = 0;
p[0] = a[0];
p[1] = a[1];
for(j=0;j<2;j++){
for(i=0;i<3;i++)
{
sum += *(p[j]+i);
}
}
printf("sum = %d\n",sum);
return 0;
}
void指针
#include<stdio.h>
int main(int argc, const char *argv[])
{
int a = 10;
double b = 3.13;
void *p,*q;
p = &a;// p = (void *)&a;
printf("%d %d\n",a,*(int *)p);
q= &b; // q = (void *)&b; //赋值是可以不转换
printf("%.2lf %.2lf\n",b,*(double *)q); //void指针使用的时候必须强制类型转换,
return 0;
}