C和指针_1
基本知识:
-
int p; //这是一个普通的整型变量
-
int p; //首先从P 处开始,先与结合,所以说明P 是一个指针,然后再与int 结合,说明指针所指向的内容的类型为int
型.所以P是一个返回整型数据的指针 -
int p[3]; //首先从P 处开始,先与[]结合,说明P 是一个数组,然后与int 结合,说明数组里的元素是整型的,所以P
是一个由整型数据组成的数组 -
int p[3]; //首先从P 处开始,先与[]结合,因为其优先级比高,所以P 是一个数组,然后再与*结合,说明数组里的元素是指针类型,然后再与int 结合,说明指针所指向的内容的类型是整型的,所以P 是一个由返回整型数据的指针所组成的数组
-
int (p)[3]; //首先从P 处开始,先与结合,说明P是一个指针然后再与[]结合(与"()"这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以P 是一个指向由整型数据组成的数组的指针
-
int **p; //首先从P 开始,先与结合,说是P 是一个指针,然后再与结合,说明指针所指向的元素是指针,然后再与int结合,说明该指针所指向的元素是整型数据.由于二级指针以及更高级的指针极少用在复杂的类型中,所以后面更复杂的类型我们就不考虑多级指针了,最多只考虑一级指针.
-
int p(int); //从P 处起,先与()结合,说明P是一个函数,然后进入()里分析,说明该函数有一个整型变量的参数,然后再与外面的int 结合,说明函数的返回值是一个整型数据
-
int (*p)(int); //从P 处开始,先与指针结合,说明P是一个指针,然后与()结合,说明指针指向的是一个函数,然后再与()里的int 结合,说明函数有一个int 型的参数,再与最外层的int结合,说明函数的返回类型是整型,所以P 是一个指向有一个整型参数且返回类型为整型的函数的指针
-
int (p(int))[3]; //可以先跳过,不看这个类型,过于复杂从P 开始,先与()结合,说明P是一个函数,然后进入()里面,与int结合,说明函数有一个整型变量参数,然后再与外面的结合,说明函数返回的是一个指针,然后到最外面一层,先与[]结合,说明返回的指针指向的是一个数组,然后再与结合,说明数组里的元素是指针,然后再与int结合,说明指针指向的内容是整型数据.所以P 是一个参数为一个整型数据且返回一个指向由整型指针变量组成的数组的指针变量的函数.
dates + 2 == &date[2] // 相同的地址
(dates + 2) == dates[2] // 相同的值
c语言中,利用&运算符访问地址,通过运算符来获取地址上的值 。例如,&barn表示 变量barn的地址,使用函数 名即可获得变量的数值。例如,printf("%d\n", barn)打印barn的值,使用运算符 即可获得储存在地址上的值。如果pbarn= & barn; 那么pbarn表示的是储存在&barn地址上的值。
数组名是数组首元素的地址
a = &a[0];都是常量
/*#include <stdio.h>
void change(int *u,int *v);//利用指针对两个指针指向的值进行交换
int change1(int *u,int *v);//利用指针返回指针指向的值的和
int main(int argc, char *argv[])
{
/*int i = 2;
int* ptr = &i;
printf("%d\n",*ptr);*/
/*int bah = 2;
int *ptr;
printf("%p\n",ptr);
ptr= &bah;
printf("%p\n",bah);
int val = *ptr;
printf("%p\n",val);
printf("%d\n", val);*/
/* printf("Hello World!\n");
int x = 5, y = 16;
printf("x= %d,y = %d\n",x,y);
change(&x,&y);
printf("x = %d, y = %d\n",x,y);
int m = change1(&x,&y);
printf("m = %d\n",m);*/
/* int st = 7;
printf("%d",&st);//打印的是st的地址
int * p;
p = &st;
printf("%d\n",*p);//打印的是p中存储的st的地址
return 0;
}
void change(int *u,int *v)
{
*u = 10;
*v = 20;
}
int change1(int *u,int *v)
{
return *u+*v;
}
*/
重点难点:
#include<stdio.h>
int main()
{
// int a = 5;
// int *p = &a;
//int *p = NULL;//
int(*p)[4][3] = NULL;//p是一个三维指针 0
printf("%d\n", *p);//0 *p 是一个二维指针 0
printf("%d\n",**p); //**p 降到一维
printf("%d\n",***p); //不会打印,***p是对一维指针取值,
//*在下面三行代码中表示的是升维操作
int a = 0;
int *p1 = &a;//一级指针
int **p2 = &p1;//二级指针
//
int a[3][4] = {0};
int *p = a[0][0];
**
#
*************************************************************************
//&对指针变量来说永远是取值
//&对数组名相关的,有时是取地址,有时是升唯
*************************************************************************
**
//下面的代码中&的作用是进行升维操作,代码有误,重在理解升维的概念和&的不同的作用
----------------------------------------------------------------------------------
&a[0][0] == a[0];
&a[0] == a;
getchar();
getchar();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main1(void)
{
int a[5] = {1,2,3,4,5};
int *p;
p = a;
printf("ap = %p\tpp = %p\n", a,p);//0060FE98
printf("%p\n",p+1);//输出0060FE9C
//printf("%d--%p\n",p+1, p+1);
return 0;
}
int main2()
{
int a = 104;
int *p = &a;
printf("%d\n",p);//6356648 打印的是地址值
printf("%p\n",p);//0060FEA8 打印的是p存储的地址
printf("%#x\n",p);//0060FEA8 以16进制格式打印地址
printf("%d\n",*p);//104
printf("%d\n",*(int*)0x0060FEA8);//强转为int*类型后再取值 结果是104
// printf("%d\n");
// printf("%d",);
return 0;
}
****************************************************************************
-----------------------------------------------------------------------------------------
# 传值分割显示
-----------------------------------------------------------------------------------------
long func()
{
int a=5;
char b = 6;//C里面 char字符类型本质就是整型。是短短整型。
//charheint 可以相互无条件转换。
//&a int* +1 走4个字节
*((char*)&a+1) = b;
return a;
}
//通过虚函数表讲个
int main3()
{
int value = func();
int a = *(char*)&value;
int b = *((char*)&value+1);
printf("%d,%d\n",a,b);
}
************************************************************************************
/*
int main4()
{
int a[2][5];
int i,j;
for(i = 0;i<2;i++)
{
for(j = 0;j<5;j++)
{
a[i][j];
}
}
int (*p)[5] = a; int[5]
for(i = 0;i<2;i++)
{
for(j = 0;j<5;j++)
{
p[i][j];
}
}
for(i = 0;i<2;i++)
{
for(j = 0;j<5;j++)
{
//先访问 *(char*)a;
//再移动 (int*)a + 1;
}
}
char *q;
q = (char*)a;
}
*/
遍历:
/*int main5()
{
int a[5] = {1,2,3,4,5};
int * p;
p = &a;
int i;
// printf("%d\n", *p++);
for(i = 0; i<strlen(a); i ++)
{
printf("%d\t",*p++);
p++;
}
return 0;
}*/
//你所想的指向的数组中的基本(非最小)元素是什么类型的 ,就定义什么类型指针
/*
int main()
{
//int ss[5][6][7]; ss[5] int[6] p;
//int (*p) [6] [7]=ss;//数组指针,二维指针,指针
int *s1[1][2][3];
int *(*ps1)[2][3] = s1;
int s[5] = {1,2,5,6,8};
//int (*p)[5] = &s;
int *p = s;
int i;
for(i = 0; i < 5; i++)
{
i = (int*)i;
printf("%d\t",*p+i);//每次给首元素加1,输出1 2 3 4 5
printf("\n");
//printf("%d\t",*(p+i));//遍历输出s中的每一个元素
}
return 0;
}
*/
//个人对于二维数组的内部访问,地址的变化过程
int main()
{
/*
int a[2][3] = {
{1,2,3},
{4,5,6}
};
printf("sizeof a %d\n",sizeof(a));//输出24,6个int类型数据,4*6
printf("a = %p, a+1 = %p a[]+\n",a, a+1 );//a = 0060FE98, a+1 = 0060FEA4 输出a的地址和a地址+sizeof(int)*3
printf("a[0]= %p, a[0]+1 = %p \n",a[0],a[0]+1);//a[0]= 0060FE98, a[0]+1 = 0060FE9C 输出a[0]地址,a[0]+1的地址
printf("*a = %p, *a+1 = %d *(*a+1) = %d\n",*a,*a+1,*(*a+1));//a[0]= 0060FE98, a[0]+1 = 0060FE9C 输出的就是a的地址和a的地址+sizeof(int)
printf("a[0][0] = %d\n",a[0][0]);//输出a[0][0]元素的值
printf("*a[1] = %d *a[0]+1 = %d\n",*a[1], *a[0]+1);//*a[1] = 4 *a[0]+1 = 2 输出的是数组a[1]首元素 和a[0]首元素+1
printf("**a = %d\n", **a);//输出的是a[0][0]的值
printf("*(*a+2) +5= %d\n", *(*a+1)+5);//先把a指向第一行a[0]数组,然后访问a[0]数组的第二个元素2,再给2加上5
printf("a[1][2]= %d\n",a[1][2]);//输出a[1][2]的元素的值
printf("*(*(a+1))+4 = %d\n",*(*(a+1))+4);//输出的是a[1][1] + 4
printf("*(*(a+1)+2) = %d\n",*(*(a+1)+2));//输出的是a[1][2]上面的值*/
return 0;
}
**************************************************************
![二维数组内部地址和元素的实现](https://img-blog.csdnimg.cn/20190124094901203.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mjc5NTI2OA==,size_16,color_FFFFFF,t_70)
//指针和二维指针是完全不同的概念。
// int a = 5;
//int *p = &a;
//int *p = NULL;报错
int(*p)[3][4] = NULL;//三维
// printf("%d\n",*p);//0 p == a,降为二维
//printf("%d\n",**p);//0 **p就是访问a,此处降为一维
//printf("%d\n",**p);//不会打印,p是访问a,降到一维之后,这里的(**p),前面的是取值
![*的两种作用:降维和解引用](https://img-blog.csdnimg.cn/20190124095041218.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mjc5NTI2OA==,size_16,color_FFFFFF,t_70)
******************************************************************************
一直需要注意的:
#include<stdio.h>
#include <stdlib.h>
void fun(int q)
{
// *q = (int *)malloc(sizeof(int));
//注意:函数形式参数是q
// q = 5; //error 类型不一致
// *q = 5;//error p = 5
//**q = 5; //正确,此处代表:*p=5
}
int main(void)
{
int p;
int q = (int)&p;
fun((int)(&p)); //int* &p
printf("%d\n",*p);//本语句语法没有问题,但逻辑上有问题
printf("%d\n",sizeof§);
int a[3][4];
a
a+1 sizeof(a)
a[0]
a[0]+1 sizeof(a[0])
a[0][0]+1 sizeof(a[0][0])
&a[0][0]+1
&a[0]+1
*a +1
*a[0]
(*a)[0]
研究指针所指向的空间的大小。 指针+1,一次走多少字节。走多少个元素单位。
int p;
p = malloc(sizeof(int4));
a[0]
return 0;
}
指针方面的知识,重在操作和练习,要比昨天更努力,更有收获。
2019年1月23日
莫问离殇