一、知识点梳理
1.零碎知识点梳理
- 字符串中的数字要进行运算,首先要 -‘0’ 操作转化成数字类型,然后运算,最后 +‘0’ 转回字符串。
- 指针就是地址;
地址就是一块内存的起始地址。 - 访问:读取或修改内存单元。
- 指针变量声明(一级指针):
格式:类型 *指针变量名
指针变量可以存放某一地址,且存放的这个地址的值的类型跟声明变量的类型相同
char buf[30]={0};
int *p=buf; //错误
char *p=buf; //正确
int *p=(int *)buf; //正确
- p指向a表示:指针变量p存放的是a的地址。
- ’ * ’ :解引用符,之后必须跟地址,如果跟整数会把整数当做地址从而出现段错误;
*p表示p指向的内存的值。 - 对于地址,32位操作系统地址大小是4个字节,64位是8个字节。
- 32位操作系统每个进程都4GB的虚拟内存(但能访问的内存非常有限)。
- 访问非法地址的内存就会出现段错误,
eg:
1.
int *p;
*p; //此时p指向随机地址,极大概率为非法地址(野指针,悬挂指针)
2.int a=10;
scanf("%d",a);
- 修改只读常量会出现段错误:
eg:
char *p="1234";
*p='2'; //错,修改只读常量
strcpy(p,"1234"); //错
int a;
int *p;
p=&a; //表示a的地址
int *p2;
*p2=&*p; 等价于 *p2=p;
*p++ 等价于 *(p++) //*的结合方向自右向左
- 形参中出现 int a[] 实际上a是指针变量,而非数组。
- 以下在数组中才有意义:
地址[n] == *(地址+n)
地址++ : 指向数组的下一个元素
地址+n ; 指向数组往后第n个元素
地址1-地址2 : 相差元素个数
地址1+地址2(无意义)
14.函数 传入参数
(1)用于数据输入(既可按值传递,也可按地址传递)
(2)用于数据输出
(3)既用于数据输入,也用于数据输出
eg;
char *strcpy(char *dest,const char *src) //src用于数据输入,dest用于数据输出
void memcpy(void *dest,const void *src,size_tn)
//void *p可以指向任何类型的元素
//p不能用*解引用符
//p一般不可以做运算,如果有编译器可以,则++表示便宜一个字节
15.假若一个函数可以有多个返回值,但return只能返回一个输出值
eg:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int fun(int *a,int *b,int *c)
{
int n=0;
*b=0;*c=0;
for(int i=0;i<10;i++){
if(a[i]%2!=0){
*b+=a[i];
n++;
}
else
*c+=a[i];
}
return n;
}
int main()
{
srand(time(NULL));
int i,a[10],b=0,c=0,n;
for(i=0;i<10;i++){
a[i]=rand()%10;
}
n=fun(a,&b,&c);
for(i=0;i<10;i++){
printf("%d ",a[i]);
}
printf("\n奇数和:%d\n偶数和:%d\n奇数个数:%d\n偶数个数:%d\n",b,c,n,10-n);
return 0;
}
- 二级指针指向的是一个一级指针。
- 数组指针
int main()
{
int a[3][3];
int (*p)[3]; //数组指针,也叫行指针
}
- 指针数组:表示数组里每一个元素都是指针。
- 字符串指针:
char *p="1234";
p="5678"; //字符串指针
char buf[]="1234";
buf="5678"; //错误,buf为常量,不能给其赋值
- 函数不能返回局部变量地址。
- 声明几个指针变量去遍历二维数组
for(p=a;p<a+3;p++)
{
int *q;
for(q=*p;q<*p+5;q++)
{
printf("%d ",*q);
}
printf("\n");
}
二、今日心得
今天学习的主要内容是指针,确实不简单,弯弯绕绕,很容易把人弄迷糊。一整天下来也有所收获,之前指针部分学习的太少了,今天差不多是从零开始,课后继续查缺补漏吧。不能掉队,后边还有更大的挑战。