当前位置: 首页 > news >正文

上海怎样做网站/新闻头条今日要闻国内新闻最新

上海怎样做网站,新闻头条今日要闻国内新闻最新,常宁网站建设常宁网站建设,如何自学网站制作1C语言里,变量存放在内存中,内存就是一组有序字节组成的数组,每个字节有唯一的内存地址。CPU 通过内存寻址。数据对象是指存储在内存中的一个指定数据类型的数值或字符串,它们都有一个自己的地址,而指针便是保存这个地…

1

C语言里,变量存放在内存中,内存就是一组有序字节组成的数组,每个字节有唯一的内存地址。CPU 通过内存寻址。数据对象是指存储在内存中的一个指定数据类型的数值或字符串,它们都有一个自己的地址,而指针便是保存这个地址的变量。也就是说:指针是一种保存变量地址的变量

  前面已经提到内存其实就是一组有序字节组成的数组,数组中,每个字节大大小固定,都是 8bit。对这些连续的字节从 0 开始进行编号,每个字节都有唯一的一个编号,这个编号就是内存地址。

示意如下图:

d789214acade8f0d1881a285a156cc8c.png

2

测试代码基于ARM公司的Cortex-M0内核芯片。
#include "log.h"int test_add(int a,int b) __attribute__((section(".ARM.__at_0x1fff5900")));int test_add(int a,int b){return (a+b);}void test_bbb(void) __attribute__((section(".ARM.__at_0x1fff5800")));void test_bbb(void){  LOG("test_bbb\n");}int test_ccc(int a){return (a+1);}void test(void){void* p1;unsigned char* p2;unsigned short* p3;unsigned int* p4;int (*p5)(int i,int j);void (*p6)(void);int *p7[10];int (*p8)[10];int (*p9[10])(int);unsigned int buf[4]={0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f};int i,j;  LOG("------------test1---------\n");  LOG("p1:%d\n",sizeof(void*));  LOG("p2:%d\n",sizeof(unsigned char*));  LOG("p3:%d\n",sizeof(unsigned short*));  LOG("p4:%d\n",sizeof(unsigned int*));  LOG("p5:%d\n",sizeof(int(*)(int i,int j)));  LOG("p6:%d\n",sizeof(void(*)(void)));  LOG("------------test2---------\n");  p2=(unsigned char*)(&buf[0]);  LOG("\n&buf[0]:0x%x\n",&buf[0]);for(i=0;i<12;i++)  {    LOG("*(p2+%d):0x%x\n",i,*(p2+i));  }  p3=(unsigned short*)(&buf[0]);  LOG("\n&buf[0]:0x%x\n",&buf[0]);for(i=0;i<6;i=i+1)  {    LOG("*(p2+%d):0x%x\n",i,*(p3+i));  }  p4=(unsigned int*)(&buf[0]);  LOG("\n&buf[0]:0x%x\n",&buf[0]);for(i=0;i<3;i=i+1)  {    LOG("*(p2+%d):0x%x\n",i,*(p4+i));  }  LOG("------------test3---------\n");  LOG("%x\n",test_add);  p5=  test_add;  j=(*p5)(1,4);  LOG("j:%d\n",j);  j=((int (*)(int,int))0x1fff5901)(6,9);  LOG("j:%d\n",j);  LOG("------------test4---------\n");  test_bbb();  ((void(*)(void))0x1fff5801)();  LOG("------------test5---------\n");  p9[0] = test_ccc;  j = (p9[0])(10);  LOG("j=%d\n", j);while(1);;}

3

指针的长度,可以看出指针的长度是4个字节。

5d7352c4c81e63a55e6ae33fdb3904e5.png

4

指针在做加减运算时,移动的单位等于它指向的单位宽度。

396dba4a7b3f28714b8884d0b6b0abde.png

5

函数指针,指向函数的指针,可以直接把一个地址转换为相应的函数指针,直接调用,前提是该地址是一个正确函数。编译时可以把函数分配在一个固定的地址中,这个地址在一定要在分散加载文件中程序的code区。

b7f653198daaa08927dd4fb78d189a78.png

6

p7:指针数组

p8:数组指针

p9:函数指针数组

8d4c3d6bb5ea493c6544bd9393de3138.png

3c50fcdaff0edbcb965a60c05fcb9537.png

7

因为C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法。不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的。右左法则的英文原文是这样说的:
The rightleft rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been parsed.

这段英文的翻译如下:
右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。
        应该是从未定义的标识符开始阅读,而不是从括号读起,之所以是未定义的标识符,是因为一个声明里面可能有多个标识符,但未定义的标识符只会有一个。

int (*func)(int *p);

函数指针,这类函数具有int*类型的形参,返回值类型 是 int。

int (*func)(int *p, int (*f)(int*));

函数指针,这类函数具有int*类型、int (*f)(int*)类型的形参,返回值类型是 int。

int (*func[5])(int *p);

func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针;
要注意这里的*不是修饰func的,而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合,因此*修饰的是func[5];
跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针;
再看左边,是int类型,即函数的返回值类型为int;
最后分析入参int* p。

int (*(*func)[5])(int *p);

func被一个圆括号包含,左边又有一个*,那么func是一个指针;
跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针,现在往左看,左边有一个*号,说明这个数组的元素是指针;
再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针;
再看左边,是int类型,函数的返回值是int类型。
总结一下,就是:func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int*形参,返回值为int类型的函数。

int (*(*func)(int *p))[5];

   func被一个圆括号包含,左边是个*,那么func是个指针;

    跳出这个括号,看右边,也是一对圆括号,说明func是指向函数的指针;再看左边,是个*,说明函数func的返回值是指针;看入参(int *p),说明func函数的入参是int*类型的;

    再跳出这个括号,看右边是[5],说明func的返回值是数组指针,该数组有5个元素;再看左边,是int类型,说明func返回值是数组指针,且数组的元素是int类型;

    总结以下:func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。

(*((void (*)())0x80004000))()
    以上表达式,可相应的写成(*((void(*func)())0x80004000))()再作分析
    func被一个圆括号包含,左边是个*,那么func是个指针
    跳出这个括号,看右边,也是一对圆括号,说明func是一个函数指针;再看左边,是void,说明函数func的返回值是void类型;
    再跳出这个括号,右边是0x80004000,左边直接是括号,说明func是作为强制转换的基础类型,用来说明0x80004000;即0x80004000是返回void,入参为空的函数指针(函数地址)
    再跳出这个括号,左边是*,右边直接是括号,说明是取指针0x80004000的值,即所指向的函数;
    最外层,仅右边是括号,则表示函数执行
    总结以下:执行函数,指向该函数的指针(函数地址)为0x80004000,该函数返回值为void,入参无

参考资料:

https://blog.csdn.net/linksafe2014/article/details/89189220

https://blog.csdn.net/sunyiping1988/article/details/82712690

https://www.cnblogs.com/DWVictor/p/10074967.html

http://www.jmfq.cn/news/4784833.html

相关文章:

  • 苏州网站优化推广/网站关键词全国各地的排名情况
  • 无锡网站制作推荐/免费网络项目资源网
  • app推广营销公司/seo优化排名百度教程
  • 做网站好的公司有哪些/口碑营销的产品
  • discuz 旅游网站模版/企业的网络推广
  • 泉州手机模板建站/营销培训讲师
  • wordpress 图片比例/互联网关键词优化
  • wordpress顶部滑动/搜索引擎优化关键词
  • 网站的开发方法/站长seo工具
  • django做的购物网站/推广普通话手抄报简单又好看内容
  • au网站怎么注册/2024年8月爆发新的大流行病毒吗
  • 长沙广告网页设计最新招聘信息/seo站长网怎么下载
  • 移动外贸网站建设/长沙专业seo优化推荐
  • 仿一个展示型网站多少钱/企业网络组网设计
  • 做摄影网站的目的是什么/搜狐财经峰会
  • 学做网站好吗/北京seo公司哪家好
  • vps如何做网站/如何进行seo
  • 可以做众筹的网站有哪些/优化网站广告优化
  • 哪里做百度网站/上海做网络口碑优化的公司
  • 青岛建设网站制作/外贸推广平台哪个好
  • 如东住房和城乡建设局网站/seo推广哪家公司好
  • 电子商务网站建设实训个人总结/品牌营销策划方案怎么做才好
  • 常德网站建设费用/外贸营销网站制作
  • 宁波外包seo服务/网站推广和seo
  • 做网站的经验和体会/搜索引擎关键词优化方案
  • 济南网站制作工具/互联网营销师证书有用吗
  • 效果好的网站建设公司/惠州网络营销
  • 网站开发语言java和php/宁波seo网络推广外包报价
  • 广州企业网站建设推荐/seo推广怎么样
  • wordpress当下载站/国外域名注册网站