(  (  (int(*)(uint, ushort, uint *, uint, int))  (*((uint *)(TCM_BASE + 0x8)))  ) (a,b,c,d,e)  )

首先红色字部分:(*((uint *)(TCM_BASE + 0x8))),((uint *)(TCM_BASE + 0x8))将TCM_BASE + 0x8转化为指针,前面的*表示取出存于TCM_BASE + 0x8这个地址的一个32位数据;
其次蓝色字部分:(int(*)(uint, ushort, uint *, uint, int)),使用一个指向函数的指针(该指针所指向的函数原型为:返回值为int型、五个参数依次为uint、ushort、uint*、uint、int)进行强制类型转换,将上述32位的数据转换为一个指向函数的指针;
再次黄色括号对:将上述两部分括起来,表示调用该指针所指向的函数;
然后绿色字部分:(a,b,c,d,e),表示调用上述函数时所传入的参数;
最后灰色括号对:将整个宏体用括号括起来,防止宏展开时产生意外的歧义。

对指针的理解还是不熟练,特别是函数指针和指针函数。从网上找了几个例子:

一、指针函数

当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中。

格式:   类型说明符 * 函数名(参数)

当然了,由于返回的是一个地址,所以类型说明符一般都是int。

 #include <stdio.h>

 int * GetDate(int wk,int dy);

 main()
{
int wk, dy;
do
{
printf ("Enter week(1-5)day(1-7)\n");
scanf ("%d%d", &wk, &dy);
}
while (wk < || wk > || dy < || dy > );
printf ("%d\n", *GetDate(wk, dy));
} int * GetDate(int wk,int dy)
{
static int calendar[][]= {
{, , , , , , }, {, , , , , , },
{,,,,,,}, {,,,,,,},
{,,,-}};
return &calendar[wk - ][dy - ];
}

子函数返回的是数组某元素的地址,输出的是这个地址里的值。

二、函数指针

指向函数的指针包含了函数的地址,可以通过它来调用函数。声明格式如下:

类型说明符 (*函数名)(参数)

其实这里不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。指针的声明必须和它指向函数的声明保持一致。

指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整型指针的函数的原型声明。

例如:

 void (*fptr)();

把函数的地址赋值给函数指针,可以采用下面两种形式:

 fptr=&Function;
fptr=Function;

取地址运算符&不是必需的,因为单一个函数标识符就标号表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。可以采用如下两种方式来通过指针调用函数:

 x=(*fptr)();
x=fptr();

第二种格式看上去和函数调用无异。但是有些程序员倾向于使用第一种格式,因为它明确指出是通过指针而非函数名来调用函数的。下面举一个例子:

 #include <stdio.h> 

 void (*funcp)()
void FileFunc(), EditFunc(); main()
{
funcp = FileFunc;
(*funcp)();
funcp = EditFunc;
(*funcp)();
} void FileFunc()
{
printf("FileFunc\n");
} void EditFunc()
{
printf("EditFunc\n");
}

三、指针的指针

指针的指针看上去有些令人费解。它们的声明有两个星号。例如:

 char ** cp;

如果有三个星号,那就是指针的指针的指针,四个星号就是指针的指针的指针的指针,依次类推。当你熟悉了简单的例子以后,就可以应付复杂的情况了。当然,实际程序中,一般也只用到二级指针,三个星号不常见,更别说四个星号了。

指针的指针需要用到指针的地址。

 char c = 'A';
char *p = &c;
char **cp = &p;

通过指针的指针,不仅可以访问它指向的指针,还可以访问它指向的指针所指向的数据。

下面就是几个这样的例子:

 char *p1 = *cp;
char c1 = **cp;

你可能想知道这样的结构有什么用。利用指针的指针可以允许被调用函数修改局部指针变量和处理指针数组

 #include <stdio.h>

 void FindCredit(int **);

 main()
{
int vals[] = {, , , -, , , , };
int *fp = vals;
FindCredit(&fp);
printf("%d\n", *fp);
}
void FindCredit(int ** fpp)
{
while(**fpp != )
if(**fpp < )
break;
else
(*fpp)++;
}

首先用一个数组的地址初始化指针fp,然后把该指针的地址作为实参传递给函数FindCredit()。FindCredit()函数通过表达式**fpp间接地得到数组中的数据。为遍历数组以找到一个负值,FindCredit()函数进行自增运算的对象是调用者的指向数组的指针,而不是它自己的指向调用者指针的指针。语句(*fpp)++就是对形参指针指向的指针进行自增运算的。但是因为*运算符与++运算符优先级均为2,但运算符为自右向左结合,++将优先于*,如果没有圆括号,那么++运算符将作用于二重指针fpp上。

四、指向指针数组的指针

指针的指针另一用法旧处理指针数组。有些程序员喜欢用指针数组来代替多维数组,一个常见的用法就是处理字符串。

 char *Names[]=  {
"Bill", "Sam",
"Jim", "Paul",
"Charles",
}; main()
{
char **nm = Names;
while(*nm! = )
printf("%s\n", *nm++);
}

先用字符型指针数组Names的地址来初始化指针nm。每次printf()的调用都首先传递指针nm指向的字符型指针,然后对nm进行自增运算使其指向数组的下一个元素(还是指针)。注意完成上述认为的语法为*nm++,它首先取得指针指向的内容,然后使指针自增。

( ( (int(*)(uint, ushort, uint *, uint, int)) (*((uint *)(TCM_BASE + 0x8))) ) (a,b,c,d,e) )的更多相关文章

  1. c语言检测文件是否存在int __cdecl access(const char *, int);

    最近写代码,遇到很多地方需要判断文件是否存在的.网上的方法也是千奇百怪,“百家争鸣”. fopen方式打开的比较多见,也有其他各种方式判断文件是否存在的,由于其他方法与本文无关,所以不打算提及. 笔者 ...

  2. int main(int argc,char *argv[])与int main(int argc,char **argv)区别?

    int main(int argc,char *argv[])与int main(int argc,char **argv)区别? 这两种是一个等价的写法 而int main(int argc,cha ...

  3. Number (int float bool complex)--》int 整型、二进制整型、八进制整型、十六进制整型

    # ### Number (int float bool complex) # (1) int 整型 (正整数 0 负整数) intvar = 15 print(intvar) intvar = 0 ...

  4. 字符串转换成整型,到底使用int.Parse,Convert.ToInt32还是int.TryParse?

    当我们想把一个字符串转换成整型int的时候,我们可能会想到如下三种方式:int.Parse,Convert.ToInt32和int.TryParse.到底使用哪种方式呢? 先来考虑string的可能性 ...

  5. int to string & string to int

    #include "stdafx.h" #include <string> #include <sstream> using namespace std; ...

  6. [转] const int *a与int *const a,const int *const a的区别

    http://blog.csdn.net/zhangheng837964767/article/details/33783511 关键问题点:const 属于修饰符 ,关键是看const 修饰的位置在 ...

  7. const int *a与int *const a,const int *const a的区别

    来源:https://blog.csdn.net/zhangheng837964767/article/details/33783511 关键问题点:const 属于修饰符 ,关键是看const 修饰 ...

  8. (int)a、&a、(int)&a、(int&)a的区别,很偏僻的题

    (int)a.&a.(int)&a.(int&)a的区别,很偏僻的题 #include <iostream> #include <stdio.h> #i ...

  9. C# int转byte[],byte[]转int

    第一种方法: byte数组转int u = (uint)(b[0] | b[1] << 8 |b[2] << 16 | b[3] << 24); int转byte数 ...

随机推荐

  1. ViewBag和ViewDate以及TempDate的区别

    简单的说,就是   ViewBag 和  ViewData 是数据共享的(他们都是共享 ViewData 的数据),ViewBag 实际就是对 ViewData的一个操作的封装.  区别 : View ...

  2. C# 在多线程环境中,进行安全遍历操作

    本文以List作为操作对象MSDN官方给出的List的线程安全的说法:此类型的公共静态成员是线程安全的.但不能保证任何实例成员是线程安全的.只要不修改该集合,List 就可以同时支持多个阅读器.通过集 ...

  3. Android从文件读取图像显示的效率问题

    因为从文件读取图像到Bitmap是一件比较费时的事情,所以研究了一下几种可行的办法,并做了对比. 首先解释一下为什么耗时,这是因为,在从jpg或者png文件中读取Bitmap时,一来需要对外存进行操作 ...

  4. 第一篇 一步一步看透C++

        毕业快一年半了,这些时候,都是在底层方面做的一些工作,虽然内核的C也实现了C++中的一些抽象机制,面向对象,继承,多态,封装等等,但是,想着大学里面,电子类的学习,都是偏向底层的,有过C++的 ...

  5. 【WP8】换肤功能的实现

    主题功能在移动开发中是最常见的功能之一,用的最多的是日间模式和夜间模式的切换,下面说说如何在WP上使用主题,不同主题的差别无非就是两种(颜色和图片),在WP上我们通常使用资源来设置颜色,系统提供了两种 ...

  6. 设置wetty不需要账号登录便可进行命令行操作

    前一篇随笔我们将了Linux怎么安装部署Wetty服务,但是我们看到,在浏览器中输入http://127.0.0.1:3000进行访问的时候,还需要我们输入账号密码进行认证(如下图第一行所示). 但在 ...

  7. Genymotion模拟器无法开启的解决方法——Unable to start the virtual device,The virtual device got no IP address

    前言 最近重装了电脑的系统,由win7换成了win8.1.android开发环境也重新配置了一遍.其他的都还好,就是genymotion模拟器一直开启失败. 自己尝试了很多方法,比如卸载重装软件,重新 ...

  8. 9 云计算系列之Cinder的安装与NFS作为cinder后端存储

    preface 在前面我们知道了如何搭建Openstack的keystone,glance,nova,neutron,horizon这几个服务,然而在这几个服务中唯独缺少存储服务,那么下面我们就学习块 ...

  9. libstdc++.so.5: undefined reference to `memcpy@GLIBC_2.14'

    没有别的原因: 找正确的 libstdc++.so.5 包就成. 我这儿有,需要的可以下载奥!

  10. vs技巧总结

    工欲善其事,必先利其器,作为一个优秀的程序员很重要的一点就是要善用工具.最近专注于工具开发的我,最近觉得工具的使用,站在巨人的肩膀上进行劳作,而不是不断的造轮子,是非常重要的. 时间最贵,因为对于每个 ...