指针
这里讲的很细
https://blog.csdn.net/weixin_43624626/article/details/130715839
内存地址:内存中每个字节单位都有一个编号(一般用十六进制表示)
存储类型 数据类型 *指针变量名;
int *p; //定义了一个指针变量p,指向的数据是int类型的。
访问指针所指向空间的内容用取内容运算符*
&:取地址符:取变量的地址
*:取内容符:取地址里面存放的内容
*&a=a;//*和&是互逆运算
&*a//错误(因为运算符优先级)
普通变量赋值
#include <stdlib.h>
int main()
{
int a = 5;
int *p = &a;
char c='v';
char *q=&c;
printf("%p %p\n", p, &a);//p为a的地址
printf("%p %p\n",q,&c);//q为c的地址
printf("%d %d\n",a,*p);//*p是取地址中的值
printf("%c %c\n",c,*q);//*q取地址中的值
printf("Hello, World");
return(0);
}
注意:指针变量使用前不仅要定义,还要初始化。未初始化的指针变量不能随便使用,不然可能会产生野指针。
通过改变指针指向,改变值
int a=10;
int *p=&a;
int *q=p;
printf("%d %d %d\n",a,*p,*q);//10 10 10
*q=20;//通过指针改变变量a的值
printf("%d %d %d\n",a,*p,*q);//20 20 20
数组
1.数组的首地址赋值给指针变量
char s[10]="hello";
char *p = s;
int arr[5]={1,2,3,4,5};
int *q=arr;
printf("%c\n",*p);//h
printf("%d\n",*q);//1
2.指针加减操作其实就是让指针向前向后移动
(1)char 移动1
char str[32]="hello";
char *p=str;
printf("%c\n",*p);//h
p++;
printf("%c\n",*p);//e
p--;
printf("%c\n",*p);//h
(2)int 移动4
double 移动 8
偏移了多少字节=n*sizeof(数据类型)
char str[32]="hello";
int *p=str;
printf("%c\n",*p);//h
p++;
printf("%c\n",*p);//o
p--;
printf("%c\n",*p);//h
运算方法
(1)++和*都是单目运算符
(2)单目运算符从右向左运算
(3)++在前是先移动再取值,++在后是先取值再移动。
int x[] = {10, 20, 30};
int *px = x;
printf("%d,", ++*px);//11
printf("%d\n%d", *px,x[0]);//11
这个++*px
把数组里的值给改了
int x[] = {10, 20, 30};
int *px = x;
printf("%d,", ++*px);//11
printf("%d\n", *px); //11
px = x;
printf("%d,", (*px)++);//11 先取值再+1,所以直接打印x[0]的值,然后再x[0]=11+1=12
printf("%d\n", *px);//12
px = x+1;
printf("%d,", *px++);//20 先取值再移位
printf("%d\n", *px);//30
px = x+1;
printf("%d,", *++px);//30 先移位再取值
printf("%d\n", *px);//30
二维数组
int a[2][3]={1,2,3,4,5,6};
a是数组名,表示第一行的首地址。
a+1表示第二行的首地址,以此类推。
在a前面加*,表示将行地址降级称为列地址。
*a;//第一行第一列的地址
*a+1;//第一行第二列的地址
*(a+1);//第二行第一列的地址
*(a+1)+1;//第二行第二列的地址
原文链接:https://blog.csdn.net/weixin_43624626/article/details/130715839
二级指针
存放指针的地址
int a = 10;
int *p = &a;
int **q = &p;
数组指针(指向数组)
本质还是指针,指向的是数组(又称为行指针)
存储类型 数据类型(* 指针变量名)[列数];
例如:
int a[2][3]={1,2,3,4,5,6};
int (*p)[3]=a;
p可以代替进行元素访问,但本质不同,p是指针变量,a是地址常量。
把p进行运算的时候,例题中情况要3个单位3个单位进行运算。
访问数组元素地址(a[i][j]的地址):
*(p+i)+j
p[i]+j
访问数组元素值:
((p+i)+j)
*(p[i]+j)
sizeof(p)=4//因为本质还是指针,所以大小都是四字节。
指针数组
指若干个具有相同存储类型和数据类型的指针变量构成的集合。其本质是数组,里面存放的是指针。
存储类型 数据类型 *数组名[元素个数];
指针数组名表示的是该指针数组的首地址。
例如:
int *arr[2];
int a=10,b=20,c=30;
int *p[3]={&a,&b,&c};
访问b的值:
*p[1]
**(p+1)
访问b的地址:
p[1]
*(p+1)
ASCII
A-65
a-97
相差32
循环队列
循环队列的相关条件和公式:
队尾指针是rear,队头是front,其中QueueSize为循环队列的最大长度
1.队空条件:rearfront
2.队满条件:(rear+1) %QueueSIzefront
3.计算队列长度:(rear-front+QueueSize)%QueueSize
4.入队:(rear+1)%QueueSize
5.出队:(front+1)%QueueSize
char
char s[]="abcd";
char ss[]={'a','b','c','d'};
printf("size=%ld\n",sizeof(s));//5
printf("size=%ld\n",sizeof(ss));//4
printf("size=%ld\n",strlen(s));//4
printf("size=%ld\n",strlen(ss));//8
‘abcd’=‘a’,‘b’,‘c’,‘d’,‘\0’ 在C语言中,字符串以’\0’作为结束符
所以s长度比s多1
strlen()遇到’\0’停止计数,而数组y中没有’\0’,所以strlen()一直向后查找,直至查找到某个’\0’为止。
strlen统计字符串长度,遇到\0结束,且不统计\0。sizeof计算开辟的空间大小。
字符串
把字符串储存在char类型的数组中,如果char类型的数组末尾包含一个表示字符串末尾的空字符\0,则该数组中的内容就构成了一个字符串。
因为字符串需要用\0结尾,所以在定义字符串的时候,字符数组的长度要预留多一个字节用来存放\0,\0就是数字0。这是约定。
字符串采用双引号包含起来,如:“hello”、“你好”、“A”、“”,这是约定。
例题
1.内存占用大小和初始化
个字符占用一字节的内存,字符串定义时数组的大小就是字符串占用内存的大小。
memset(strname,0,sizeof(strname)); // 把全部的元素置为0
2.在C语言中,数组名是数组元素的首地址,字符串是字符数组,所以在获取字符串的地址的时候,不需要用&取地址
char strname[21];
memset(strname,0,sizeof(strname));
scanf("%s",strname);//acc
printf("%s\n",strname); //acc
printf("%c",strname[1]);//c
字符串的结尾标志是0
char strname[21];
memset(strname,0,sizeof(strname));
scanf("%s",strname);//ac0cc
printf("%s\n",strname); //ac0cc
strname[3]=0;//或strname[3]='\0';// 强制把第4个元素赋值0
printf("%s\n",strname); //ac0
printf("%c",strname[1]);//c
把赋值为0或’/0’后面的不要,变成内存中的垃圾值
4.字符串是字符数组,字符串越界就是数组越界。
5.
char i = 1;则i的ASCII就是1,在内存中就是0 0 0 0 0 0 0 1
char i = ‘1’;则i的ASCII就是字符‘1’的ASCII码49,就是0 0 1 1 0 0 0 1
将一个字符常量放到一个字符变量中,实际上并不是把该字符本身放到内存单元中去,而是把该字符的相应ASCII代码放到存储单元中。
6.
【A选择:】数组越界。所以错误。
【B选择:】声明char类型,传入了数值数组,而数值会以char类型的ASCII编码写入。所以正确。
【C选择:】 数组声没明显不符合规范,左侧声明名后应加上[]。所以错误。
【D选择】:这种声名只能用字符型char等。所以错误。
对于D选项:
int a[5]={'1'};//49,0,0,0,0 这样行,但D中等号右侧没有{}
int a[5]={1};//1,0,0,0,0
‘e’ 的ASCII是101,而字符s第一个是’a’。也就是说只写这么个s就代表它的第一个值是s[0]
‘e’ - 'a’为两个字符之间的ASCII差值=4
8.
gets和scanf输入都是需要取地址,数组名a等价于首元素地址&a[0],a+1相当于&a[1]。所以D选项没有取地址才错。
参数类型为 char* 型,即 str ,它可以表示这个数组的首地址,所以B 正确
9.
BC选项:
int *s[8]; //定义一个指针数组,该数组中每个元素是一个指针,每个指针指向哪里就需要程序中后续再定义了。
int (*s)[8]; //定义一个数组指针,该指针指向含8个元素的一维数组,每个都指向对应的数组的每列 。
主要在于看运算符优先级:int *p[n]; 中,运算符[ ]优先级高;int (*p)[n]; 中( )优先级高。
数组作为实参时必须指定列数,
否则可能产生歧义,所以D正确 。