1、数据类型————引入
基本类型 char short int long float double
char 占1字节空间
short 占2字节空间
int 占4字节空间
long 占4字节空间
float 占4字节空间
double 占8字节空间
2、指针与内存的那些事
内部存贮器,暂存程序/数据–掉电丢失
内存两个概念:物理存储器和存储地址空间
物理存储器:实际存在的具体存储器芯片
内存地址空间:对存储器编码的范围
内存的管理:将内存抽象抽象成一个很大的一维字符数组
将内存中的每一个字节分配一个32位或64位的编号(与32位或者64位处理器相关)
这个编号成为内存地址
2.1指针变量
内存区的每一个字节都有一个编号,即为“地址”
指针的实质就是内存地址,指针就是地址,地址就是指针
指针是内存单元的编号,指针变量是存放地址的变量
一个变量的地址称为该变量的指针。
重要的两个运算符:
“&” 取地址运算符
“*” 指针运算符
例如:
int num=100;
int *p; //定义指针变量 int为该指针的基类型
p=& num; //去变量的地址用&,这里就将num的地址给了指针变量p
printf("%d",*p);
输出:100
这里*p表示取保存的地址编号对应的空间的内容,即100
需求:定义一个指针变量保存num的地址
指针变量前面加上“ * ”表示该变量的类型是指针型变量
指针变量有两种类型:一是自身的类型,二是指向的类型,即基类型
自身的类型:在指针变量定义的时候,将变量名类型拖黑(即遮挡住),剩下的就是指针变量的自身类型
例如:int p 拖黑p 剩下int ,p自身的类型就是int
指向的类型:在指针变量定义的时候,将变量名和离它最近的一个拖黑,剩下的即为指针变量指向的类型
例如:int p 应该拖黑p 剩下int 即int为p的指向的类型
指向的类型的作用:决定了指针变量所取空间的宽度,决定了指针变量+1跨过的单位跨度
空间的宽度就是该数据类型占用的空间大小
在我们通过指针引用一个变量时,必须需要知道该数据的类型,才能按照存储单元的长度以及数据的存储形式正确的取出该数据。
例如:在定义int num=100时候,这里100占了4个字节,我们定义指针变量p时候,如果不用int,而是用short定义
结果就是我们不能完全将10取出,因为short占两个字节
所以在"指针移动一个位置"和"使指针+1"代表着移动4个字节
2.2 指针变量作为函数参数
在函数调用时,将实参变量的值传递给形参,采用的是“值传递”方式。
在指针变量作为函数参数时候,也需要遵循这个规则。
2.3 通过指针引用数组
数组元素的指针就是数组元素的地址。
当指针指向数组元素的时候,我们可以对指针变量进行加减运算,相当于指向距离指针所在位置的向前或向后第几个元素。
引用数组的方法:
(1)下标法
(2)指针法
需要注意的是,p+1并不是简单地将地址+1,而是指向数组的下一个元素。
指针变量初始化:
int a[10]={1,2,3,4,5,6,7,8,9,10};
int *p=&a[ ];
这句话等价于:int *p;
p=&a[0];
或者定义为:int *p=a;
这里是将a数组首元素(即为a[0])的地址赋给指针变量p(而不是赋给 *p);
引用数组时指针的运算:
如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素,p-1则是指向同一数组上的上一个元素。(这里和上面指针变量指向的类型所述一致)
通过指针指向数组元素:
(1)下标法,如a[ i ]
(2)指针法,如 *(a+i)或者 *(p+i)
例如:
#include<stdio.h>
int main()
{
int a[10];
int *p,i;
printf("please enter 10 integer numbers:");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
for(p=a;p<(a+10);p++)
printf("%d",*p);//用指针指向当前的数组元素
printf("\n");
return 0;
}
#include<stdio.h>
int main()
{
int a[10];
int *p,i;
p=a;//p指向a[0]
printf("please enter 10 integer numbers:");
for(i=0;i<10;i++)
scanf("%d",p++);//这里p的起始值已经不是a[0]
p=a;//所以需要重新定义,使指针重新指向a[0]
for(i=0;i<10;i++,p++)
printf("%d",*p);
printf("\n");
return 0;
}
用数组名作为函数参数:
当变量作为函数参数时,传递的是变量的值,通过函数调用不能改变实参的值。
当数组名作为函数参数时,如果形参数组的各个元素的值发生变化,实参数组的元素也会随之变化。实参数组名代表该数组首元素的地址,而形参是用来接收从实参传递过来的数组首元素地址的。
等价写法:
fun(int arr[ ],int n)
fun(int * arr,int n)
重要说明:C语言调用函数时虚实结合的方法都是采用“值传递”的方式,当用数组名作为函数参数时,由于数组名代表的是数组首元素地址,因此传递的是地址,所以要求形参为指针变量。在函数执行期间,可以再被赋值。
例如:将数组a中n个整数按照相反顺序存放
#include<stdio.h>
int main()
{
void inv(int *x,int n);
int i,a[10]={1,2,3,5,6,8,7,8,9,0};
printf("The original array:\n");
for(i=0;i<10;i++)
printf("%d",a[i]);
printf("\n");
inv(a,10);
printf("The array has been inverted:\n");
for(i=0;i<10;i++)
printf("%d",a[i]);
printf("\n");
return 0;
}
void inv(int *x,int n)
{
int *p,temp,*i,*j,m=(n-1)/2;
i=x;j=x+n-1;p=x+m;
for(;i<=p;i++,j--)
{
temp=*i;
*i=*j;
*j=temp;
}
return;
}