第八章 其他话题
指针应用的地方还有很多,这里列举了几个高级应用话题。
指针类型转换
访问特殊地址
例如int num=10; int *ptr = (int *)num
就是将ptr
指向地址10,这样做是很危险的,因为我们无法知道地址10到底可用不可用。除非我们所要指向的地址是明确的,否则不建议使用这种操作。
但是在嵌入式系统中,这么做确有明显意义。嵌入式系统中,我们经常要做某些地址访问。这里的地址就是明确的,所以我们可以使用指针的类型转换。例如
#define VIDEO_BASE 0xB8000
int *videoAddress = (int *)VIDEO_BASE;
*videoAddress=FFFFFF;
这里便可以直接使用videoAddress
来读写地址上的数据了
访问端口
在嵌入式系统中,我们还可以使用指针的类型转换来访问特定的端口来方便方便操作。例如:
#define PORT 0x0000FFF0
volatile unsigned int *const port = (unsigned int *) PORT;
这里声明很长,有几点要注意
volatile
限制编译器优化。编译器在编译时会进行一定的优化操作,导致指针指向的地址并不是我们想要的,所以此字段阻止了编译器的优化操作。unsigned int * const
定义了一个指向无符号整型的常量指针。也就意味着指针指向区域内容可写可读,但是指针指向哪个区域确不可改变。保证了地址安全。
判断大小端
可以使用如下代码来判断系统的字节序
int num = 0x12345678;
char *adr = (char *)#
int i;
for (i = 0; i < 4; ++i)
printf("%p: %02x\n",adr+i,(unsigned char )*(adr+i));
通过前两行使用指针的类型转换,adr
指向了num
的地址。该区域一共有4个字节。通过循环,依次读出了每个字节中的值。
别名
- 当两个指针指向同一位置时,那么其中一个指针就是另一个指针的别名
- 编译器编译指针时,默认指针都有别名,这会有一定的性能下降问题。我们可以使用关键字
restrict
来告诉编译器,该指针没有别名,来提高编译器性能。 - 对于
restrict
关键字来说,指针不能有别名,否则操作结果是未定义的