指针?什么是指针?
从根本上看,指针(pointer)是一个值为内存地址的变量(或数据对象)。正如char类型变量的值是字符,int 类型变量的值是整数,指针变量的值是地址。假设一个指针变量名是 ptr,可以编写如下语句:
ptr=&pooh;//把pooh的地址赋给ptr
对于这条语句,我们说ptr“指向”pooh。ptr和&pooh的区别是ptr 是变量,而&pooh 是常量或者,ptr是可修改的左值,而&pooh 是右值。还可以把 ptr 指向别处:
ptr= &bah;//把ptr指向bah,而不是pooh现在ptr的值是bah的地址。
间接运算符*
假设已知ptr指向bah,如下所示:
ptr=&bah;
然后使用间接运算符找出存储在bah中的值,该运算符有时也称为解引用运算符.不要把间接运算符和二元乘法运算符()混淆,虽然它们使用的符号相同但语法功能不同。
val=*ptr;//找出ptr指向的值
语句ptr=&bah;和val= *ptr;放在一起相当于下面的语句:
val = bah;
由此可见,使用地址和间接运算符可以间接完成上面这条语句的功能,这也是“间接运算符”名称的由来
小结:与指针相关的运算符
地址运算符:&
一般注解:
后跟一个变量名时,&给出该变量的地址
示例:
&nurse 表示变量 nurse 的地址。
间接(或解引用)运算符:*
一般注解:
后跟一个指针名或地址时,*给出存储在指针指向地址上的值
示例:
nurse = 22;
ptr=&nurse;//指向nurse的指针
val=*ptr;//把ptr 指向的地址上的值赋给 val执行以上3条语句的最终结果是把 22 赋给 val。
声明指针
Pointer ptr;//不能这样声明指针
为什么不能这样声明?因为声明指针变量时必须指定指针所指向变量的类型,因为不同的变量类型占用不同的存储空间,一些指针操作要求知道操作对象的大小。另外,程序必须知道存储在指定地址上的数据类型。long和float 可能占用相同的存储空间,但是它们存储数字却大相径庭。下面是一些指针的声明示例
intpi;//pi 是指向int 类型变量的指针
charpc;//pc是指向char类型变量的指针
float*pf,pg;// pf、pg都是指向float类型变量的指针
类型说明符表明了指针所指向对象的类型,星号()表明声明的变量是一个指针。int * pi;声明的意思是pi是一个指针,*pi是int 类型(见图9.5)。
*和指针名之间的空格可有可无。通常,程序员在声明时使用空格,在解引用变量时省略空格。pc 指向的值 (*pc)是 char 类型。pc 本身是什么类型?我们描述它的类型是“指向 char 类型的指针”。pc 的值是一个地址,在大部分系统内部,该地址由一个无符号整数表示。但是,不要把指针认为是整数类型。**一些处理整数的操作不能用来处理指针,反之亦然。**例如,可以把两个整数相乘,但是不能把两个指针相乘。所以,指针实际上是一个新类型,不是整数类型。因此,如前所述,ANSIC 专门为指针提供了%p格式的转换说明
一些处理整数的操作不能用来处理指针,下文进行解释
(C语言)地址为什么要变成指针才能赋值给指针变量呢?
C语言中,指针的值就是地址,不过这个地址不是它自己的地址,而是绑定变量的地址。“指针里面存的东西才是地址”
int point = 0;
int* p = &point ;//声明+初始化
// int* p2_ = point ; wrong synatax
int* p2 = (int* )point ;
所以要初始化一个指针,你得给一个另外的地址。指针p=point 地址,即intp=&point 。此时&point 的值应该是0x010 FFBEC(假设在内存中这个地址存储point )。如果说你硬要把0给p2,你就需要告诉编译器,0是一个地址,同时你还要显式的转换将int转换为int,即intp2=(int*)point。
在不考虑隐式转换/显式转换/自定义数据类型的情况下,只有相同的数据类型才能赋值。要初始化一个指针,你就必须给地址。要给地址,对于一个非指针变量,你要取地址,对于一个指针变量,可以直接赋值。
当然了,你可以这么理解:所有的变量都是有地址属性,只不过大部分都是隐式表现的(所以要&取地址),指针变量则是显式表现的。
为了帮助程序员减少出错。如果编译器不检查数值类型而是直接把一个int数值转换为地址并且不加警告,那么很可能因为程序员的一个粗心(把一个数值错误的赋值给了一个地址)产生灾难性的后果而且几乎无法发现。如果象现在这样必须显式的调用强制类型转换语句再赋值,意味着程序员对这样的转换作了确认,最大可能避免了此类粗心错误。
灵魂问题:C语言里指针int *p=&a;相当于int *p; p=&a; int p=&a;这里面的p不是表示值吗?值可以等于地址&a?
定义变量时,星号属于类型说明的一部分;
赋值时,星号表示对指针所指地址中的值操作(读写)。
而int *p=&a;你都知道了是相当于定义并赋值的简化形式,不应该与单独的 *p=a混淆,等效如下代码:
int *p;
p=&a;
就是将两行代码合并,并省略了重复的 p。
指针赋值
可以分成两种情况
声明+初始化
修改指向
int val = 11;
int *p5 = &val; //声明+初始化
int *p6 = nullptr; //设为空指针或者指向其他合法对象
p6 = &val; //修改指向
为指针赋值,等号右边一定要是地址值,因为指针是一个对象,里面存放的是该指针所指向对象的地址值。
实例:控制LED闪烁
方式一
#if 0
void Delay(unsigned int Time)
while(Time --)
)
int main()
{*//0x11000c40通过以上分析,我们知道需要寄存器GPX2C0N写入数据0x10000000,怎么写
//0x10000000
//GPX2C0N=0x10000000;error
//*0x11000c40=0x10000000;也会报错,因为编译器不知道0x11000c40是个地址,他就把他当做数
*(unsigned int*)0x11000c40=0x10000000;//强制类型转换,显式转换声明这是个指针,
指针类型是unsigned int型,指针前边在加*,变成指针指向的内容,(定义变量时,
星号属于类型说明的一部分;赋值时,星号表示对指针所指地址中的值操作(读写))
编译器不知道0x11000c40是个地址,为何转换成int型,因为是32位,char才8位*
whtle(1)
{
*(unsigned int*)0x11000c44 =0x80;//转换成16进制
Delay(1000000);
*(unsigned int*)0x11000c44=0x00;
Delay(1000000);
}
Return 0;
}
#end if
方式二
c语言中哪种数据类型的元素的地址是连续的,数组和结构体
数组:同一数组的不同数据的类型得一样
结构体:可以是不同的数据类型,int,char,当描述同一个东西的时候,我们会把不同的变量弄到一个结构体中。
void Delay(unsigned int Time)
while(Time --)
)
#define GPX2C0N (*(unsigned int*)0x11000c40)
#define GPX2DAT (*(unsigned int*)0x11000c44)
typedef struct
{
unsigned int CON;
unsigned int DAT;
}gpx2;
//(gpx2*)0x11000c40//显式转换说明这个地址是一个指向这种类型的结构体指针,
它是结构体指针
#define GPX2 (*(gpx2*)0x11000c40)//结构体指针前边再加*,表示结构体的内容
int main()
{
GPX2.C0N =0x10000000;
whtle(1)
{
GPX2.DAT =0x80;//转换成16进制
Delay(1000000);
GPX2.DAT =0x00;
Delay(1000000);
}
Return 0;
}