( ( (int(*)(uint, ushort, uint *, uint, int)) (*((uint *)(TCM_BASE + 0x8))) ) (a,b,c,d,e) )
| ( ( (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) )的更多相关文章
- c语言检测文件是否存在int __cdecl access(const char *, int);
最近写代码,遇到很多地方需要判断文件是否存在的.网上的方法也是千奇百怪,“百家争鸣”. fopen方式打开的比较多见,也有其他各种方式判断文件是否存在的,由于其他方法与本文无关,所以不打算提及. 笔者 ...
- 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 ...
- Number (int float bool complex)--》int 整型、二进制整型、八进制整型、十六进制整型
# ### Number (int float bool complex) # (1) int 整型 (正整数 0 负整数) intvar = 15 print(intvar) intvar = 0 ...
- 字符串转换成整型,到底使用int.Parse,Convert.ToInt32还是int.TryParse?
当我们想把一个字符串转换成整型int的时候,我们可能会想到如下三种方式:int.Parse,Convert.ToInt32和int.TryParse.到底使用哪种方式呢? 先来考虑string的可能性 ...
- int to string & string to int
#include "stdafx.h" #include <string> #include <sstream> using namespace std; ...
- [转] const int *a与int *const a,const int *const a的区别
http://blog.csdn.net/zhangheng837964767/article/details/33783511 关键问题点:const 属于修饰符 ,关键是看const 修饰的位置在 ...
- const int *a与int *const a,const int *const a的区别
来源:https://blog.csdn.net/zhangheng837964767/article/details/33783511 关键问题点:const 属于修饰符 ,关键是看const 修饰 ...
- (int)a、&a、(int)&a、(int&)a的区别,很偏僻的题
(int)a.&a.(int)&a.(int&)a的区别,很偏僻的题 #include <iostream> #include <stdio.h> #i ...
- C# int转byte[],byte[]转int
第一种方法: byte数组转int u = (uint)(b[0] | b[1] << 8 |b[2] << 16 | b[3] << 24); int转byte数 ...
随机推荐
- 如何让Snippet Compiler 2008 支持linq
转载自:http://www.cnblogs.com/hbb0b0/archive/2009/09/01/1557832.html 注意,下面的图和上面的图,有些不同 上面是在 FileSystem ...
- linux stat命令参数及用法详解
功能说明:显示inode内容.语 法:stat [文件或目录]补充说明:stat以文字的格式来显示inode的内容. ls 命令及其许多参数提供了一些非常有用的文件信息.另一个不太为人所熟知的命令 s ...
- HTML5 Canvas 超炫酷烟花绽放动画教程
这是一个很酷的HTML5 Canvas动画,它将模拟的是我们现实生活中烟花绽放的动画特效,效果非常逼真,但是毕竟是电脑模拟,带女朋友看就算了,效果还是差了点,呵呵.这个HTML5 Canvas动画有一 ...
- ASP.NET获取文件名,后缀名
using System.IO; //引入命名空间 string path = "text.aspx"; string pathName = Path.GetFileName(pa ...
- MysqlHelper使用反射机制智能推算数据类型以及属性名称
public class MySqlHelper { private string ConnString; public MySqlHelper(string connectionString) { ...
- 如何在Linux系统中安装VMware
首先打开vmware官网的下载链接:https://my.vmware.com/web/vmware/info/slug/desktop_end_user_computing/vmware_works ...
- 利用opencv作透明重叠人群密度热度图
在作热度图的时候我们经常需要将热度图调整透明度后叠加在原图上达到更好的展示效果.比如检测人气密度的热度图: (来自sensetime) 一般作图的时候会第一时间想到matplotlib,因为可以很方便 ...
- actor mysql 持久化之 specified actor
持久化到mysql,要求一次操作涉及到的多次读写的事务性.使用的 library 是 postgresql-async, akka 版本是 2.11. 1. 实现 per-user 逻辑,简单来讲,就 ...
- 在SSH框架中,如何得到POST请求的URL和参数列表
在做项目的API通知接口的时候,发现在SSH框架中无法获取到对方服务器发来的异步通知信息.最后排查到的原因可能是struts2对HttpServletRequest进行了二次处理,那么该如何拿到pos ...
- 在vue中优雅的使用LocalStrong
h5的LocalStrong帮我们缓存一些数据到本地,最常用的使用场景,比如京东购物在未登陆的状态下,把商品加入购物车,收藏某个商品.当我们把url复制到另外一个浏览器,购物车就是空的. 以下是一个简 ...