您的位置:首页 > 其它

<2012 10 29> 调C记录 <有关指针 数组 声明>

2012-11-04 17:22 375 查看
<调C记录 2012 10 29>

1、指针的定义与解用
(1)如果需要解用一个指针,那么首先需要定义一个指针。首先,我们对于一般的变量指针,可以按普通方式定义
如: char *ptr
prt是一个指向char数据的指针,它本身是一个存放在某个内存地址中(编译器分配)的变量,这个变量的内容也是一个地址,该地址指向的内存空间存放着一个char型数据。

可以这样解用并赋值:*ptr = 255
但是不能解用没有被定义的空间,比如 *(ptr+1),编译能通过,但是运行时会报错。

(2)如果先定义一个数组如 char a[10] ,将该数组的地址赋予指针ptr,则可以用解用指针的方式引用数组。这经常用在调用函数传递数组变量时,当然用malloc函数申请的堆内存空间也可以用解用指针的方式进行引用。


char a[10];
char *ptr;
ptr = a ; //或者这里用 ptr = &a也是可以的,因为a = &a都表示数组首地址
*(ptr+9) = 255;
a[9] = 244;
*(char *)(a+9) = 243;


(3)注意上面程序的最后一行,为什么需要两个“*”号来解用呢? 是因为数组a和指针ptr不同,指针ptr是一个变量,虽然它存储的数据就是数组a的首地址,但它本身也需要存储空间,这样的变量才能被*解用并引用。我们不能直接用*(a+9)来解用这个数组首地址offset9个char的内存,是因为a本身不是一个变量,而是一个常量。需要先用(char *)(a+9)强制转换(或者叫做匿名定义)一个指针变量,然后再解用。所以左起第一个*是解用,第二个*是定义指针变量。

在底层编程操作功能部件的寄存器时,可能用到这样的定义方式,如:

#define WTCON (*(volatile unsigned long *)0x53000000)


这个寄存器WTCON的内存映射地址是0x53000000,该语句的含义就是先定义一个指向unsigned long的匿名指针,该指针中存放的地址是0x53000000,然后对该指针解用。这样给WTCON赋值就相当于给那个寄存器赋值。

2、关于数组的引用
定义一个数组char a[10],引用从a[0] ... a[9]共10个char。

上面说过对于数组 char a[10],a 和 &a 都表示这个数组首地址(第一个元素的地址),他们是常量。但是编译器对于他们的运算是不同的!

(a+1)表示数组下一个元素的地址,(&a+1)表示内存中连续的第二个这样的数组对象开始的元素的地址(如果没有定义,则该地址内的数据随机),即(&a+1) = (a+10)。

编译器是逻辑的,它认为a只是指向一个char,而&a指向整个数组,因此在加减运算时也依照这样的含义。

3、一个复杂声明

void ( *signal(int signo,void(*func)(int)) ) (int)


这是linux内核代码中一个注册信号量的声明
|-- P1=void(*func)(int)
| func是一个函数指针,参数int,返回void

|-- void ( *signal(int signo, P1) ) (int)
| signal是一个函数,参数int signo和P1,返回一个函数指针。
| 该返回的函数指针指向的函数f()的参数是int,返回void

### 定义一个返回函数指针、参数为ZZZ的函数,该函数指针指向的函数参数是XXX,返回值是YYY
---> YYY (*fun(ZZZ))(XXX)
调用时,fun(ZZZ)返回一个函数指针,然后用*对其解用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: