浅谈C指针,数组,函数指针

        工作中发现很多初入职场的同事不会使用指针,或者惧怕指针。作为C语言老鸟,在这里写一些有利于初学者理解C指针的东西,希望对他们有帮助吧。

1.C语言里,指针可以说是地址变量。

比如

int n;
int *p; 

n是一个变量。它的类型是int;

p也是一个变量。可以这么理解:它的类型是(int*); 官方说法是:一个指向int的指针;直白说法是:p这个地址,是按照int的形式保存数据。

本质上,p的值是一个内存地址。而(*p),也就是对p进行“地址取值”运算,指的是获取p这个内存地址所保存的内容,而怎么去取呢?换句话说,取几个字节?这就看p的类型,(int*)那就是取sizeof(int)个字节。如果你强制(*(char*)p),即对p强制转换再取值,那就取sizeof(char)个字节,得到的结果类型为char;

2.不理解指针,通常是因为不了解CPU/MCU与内存,不了解编译。也不需要很深入了解,其实知道基本概念,CPU的简单工作原理与运行流程,内存是什么在哪里,编译器做了什么,搞ARM移植的,至少知道有个叫ATPCS/APCS的东西。

3.通常我看一个新的单片机,一般最先看内核和存储器映射。下面是CM3的存储器映射


上图描述了4GB的地址空间对应的功能区域。

这个东西跟指针有什么关系?当然有关系。

以stm32为例,地址线32位,2的32次方=4G;各种寄存器,RAM,ROM等等就映射到特定的地址范围。

我们所说的内存,一般就是指上图的片上SRAM与片外RAM这两块。

我们定义指针,一般都是指向这两块地址范围内。但是指针本身可以指向内存以外的区域,比如代码区,外设区,甚至保留区(有的可能会引发异常吧,得看手册说明)等等。这些非RAM地址区域,有的可读,有的可写,有的可读写,不一而足。

比如说,

int *p;p=(int*)0x2000 0000; //就是定义一个指向地址0x2000 0000的int指针;
int a = *p; //则表示获取内存地址为0x2000 0000处的内容给变量a,一共sizeof(int)=4字节;0x2000 0000~0x2000 0003;
char c=*(char*)p; //也可以按char的形式取值,取一个字节的内容。
a=*(int*)0x00000008; //直接获取某地址处的值。

4.指针与数组。作为函数形参时,比如void f(char a[])与void f(char *a)是一样的,这个时候数组会退化为指针。但是本身数组与指针是非常不同的。数组是一片连续的内存空间,数组名代表起始地址,但数组名不仅仅作为地址。数组的首地址是不能改变的,而指针地址可以改变。

int *p;
int n=0;
int a[2]={1,1};
p=&n;//p可变
p=&a[0];//p可变
a=p;//错误,a不可以改变

另外,sizeof(p)==4 ;sizeof(a)==8;

5.多重指针。比如

int **p;

此为二重指针,即指针的指针。本质是也是指针,只不过此指针保存的内容也是做指针用。

若将int*理解为某种类型,比如写作pint ,则 int **p 可理解为 pint *p;

无论三重,四重指针,也是同样的道理,一层包一层的,并没有多复杂。

6.函数指针与函数名

定义一个函数

void fun(void){}

fun为函数名,代表函数的入口地址。函数名有些像指针,但不是指针;函数指针才是指针(有点废话了)。如下

void (*pfun)(int);
void fun(int i)
{
	printf("%d\r\n",i);
}
int main(int argc, char *argv[]) {
   //对函数指针赋值 
    pfun=&fun;
    //4种调用方法 
    fun(1);
    (*fun)(2);
    (*pfun)(3);
    pfun(4);
    
    printf("  fun:%d\r\n",fun);
    printf(" &fun:%d\r\n",&fun);
    printf(" pfun:%d\r\n",pfun);
    printf("&pfun:%d\r\n",&pfun);
    
	return 0;
}

DEV C++运行结果是

1
2
3
4
  fun:4199712
 &fun:4199712
 pfun:4199712
&pfun:4215760

可见函数名与函数指针可以用同样的方式调用函数。

注意有些编译器可能无法通过。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值