指针之 *((volatile unsigned long *)(x))解析

  今天重新温习了一下C语言的指针部分,突然想到了经常会碰见的一种宏定义:#define PGAS (*((volatile unsinged long *)(x)))

  在解析该宏定义前,先看看指针变量的声明

声明一个int类型的指针变量:int* p;

仅仅是这样定义,这个指针是不能够直接拿来使用的,还必须给它赋值(初始化),例如:

  int a = 10;

  int* p = &a;

  或:

  int a = 10;

  int* p;

  p = &a;

  其中,&a表示变量a所代表的内存地址,所以指针变量p存储的是一个内存地址(这个地址要和指针变量p自身的地址区分开),而*p是指针变量p所指内存地址中存储的数据(上述代码中既是变量a的值),经过初始化的指针我们是可以拿来使用的。

例如:给这个指针所指内存地址赋值:*p = 15;

读取这个指针所指地址中存储的数据的值 printf(“d\n”,*p);

  运行下面的代码,可以很清楚的了解指针变量的地址和指针变量所指的地址的关系:

void main()
{
    int a = 10;
    int* p = &a;

    printf("变量 a 的值:%x\n",a);
    printf("变量 a 的地址:%x\n",&a);
    printf("指针变量 p 的值:%x\n",p);
    printf("指针变量 p 的地址:%x\n",&p);
    system("pause");
}

运行结果:

从图中可以看出变量a的地址和指针变量p的值是一样的:0x23febc

回归正题:#define PGAS (*((volatile unsinged long *)(x)))

其中,x 是一个常量,代表内存地址值,(volatile unsinged long *)(x) 是把这个常量x强制转换为一个unsigned int 指针,(*((volatile unsinged long *)(x)))表示的是地址x中的数据。

在上面的代码中我们可以进行类似数学公式的带入替换:

int a = 10;

int* p;

p = &a;

一般我们要对指针变量p所指地址赋值或要读取指针变量p所指地址中的数据时,是这样操作的:

int b = *p;

*p = 20;

等价于:

int b = *(&a);

*(&a) = 20;

上面说了&a表示的是变量a的地址,也就是一个无符号整型(unsigned int)常量。

再看一段代码:

#include <stdio.h>

#define A (*((volatile unsigned int*)(0x23febc)))

void main()
{
    A = 20;
    printf("%d\n",*((unsigned int*)(0x23febc)));
    printf("%d\n",A);

    system("pause");
}

记得刚接触到这种宏定义时,查查资料当时可以弄懂,可是等到下次再遇见时,又不明白了,总之是时而明白,时而糊涂。

以文字的形式记录下来,可以帮自己整理整理思路加深理解和记忆。

时间: 2024-12-17 09:32:10

指针之 *((volatile unsigned long *)(x))解析的相关文章

C语言之强制类型转换与指针--#define DIR *((volatile unsigned int *) 0x0022)

强制类型转换形式:(类型说明符) (表达式) 举例说明:1) int a; a = (int)1.9; 2)char *b; int *p; p = (int *) b; //将b的值强制转换为指向整型数据的指针类型,后赋给p 注示:类型说明符和表达式都必须加括号,表达式为单个变量可不加括号. 总结:只要看到(类型说明符) (表达式) 的一定为强制类型转换:如(int *) 0x0022; 再举一例:#define DIR *((volatile unsigned int *) 0x0022)

(*(volatile unsigned long *)详解

(*(volatile unsigned long *) 对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的.如果系统结构支持独立的IO地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因为C语言并没有提供真正的"端口"的概念.如果是内存映射,那就方便的多了. 以 #define IOPIN (*((volatile unsigned long *) 0xE0028000)) 为例:作为一个宏定义语句,define是定义一个变量或常量的伪指令.首先( vo

嵌入式开发中对(*(volatile unsigned long *)) 的理解

一.说明 (*(volatile unsigned long *)) 这个语句对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的.如果系统结构支持独立的IO地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因为C语言并没有提供真正的"端口"的概念.如果是内存映射,那就方便多了. 二.举例讲解 以 #define IOPIN (*((volatile unsigned long *)0xE0028000))为例: 作为一个宏定义语句,define是定义一个变

#define GPFCON (* (volatile unsigned long * )0x56000050 )

int a; int *p; p = &a; *p = 0x100; //a=0x100 p = (int *)0x56000050; *p =0x100; *( ( int * ) 0x56000050) = 0x100 加上volatile是为了防止编译器优化这个寄存器 #define GPBCON (*(volatile unsigned long *)0x56000010)#define GPBDAT (*(volatile unsigned long *)0x56000014) #de

java中volatile关键字的含义解析及用途

在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制. synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰的方法 或者 代码块.

右左法则----复杂指针解析

核心提示:因为C语言所有复杂的指针声明,都是由各种声明嵌套构成的.如何解读复杂指针声明呢?右左法则是一个既着名又常用的方法 因为C语言所有复杂的指针声明,都是由各种声明嵌套构成的.如何解读复杂指针声明呢?右左法则是一个既着名又常用的方法.不过,右左法 则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法.C标准的声明规则,是用来解决如何创建声明的,而右左法则是用 来解决如何辩识一个声明的,两者可以说是相反的.右左法则的英文原文是这样说的: The right-left rule:

复杂指针解析

因为C语言所有复杂的指针声明,都是由各种声明嵌套构成的.如何解读复杂指针声明呢?右左法则是一个既 著名又常用的方法.不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法.C标准的声明规则,是用来解决如何创建声明的, 而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的.右左法则的英文原文是这样说的: The right-left rule;Start reading the declaration from the innermost parentheses,

娓娓道来c指针 (4)解析c的声明语句

(4)解析c的声明语句 在继续探索c指针之前,有必要来解析下c语言中复杂的声明语法. 只需要记住两点:一个原则,一个规则. 原则:先看标示符. 规则:运算符优先级是规则. 举例说明 1.最简单的 int array[3]; 结论:array是数组,数组规模是3,元素类型是int. 解析过程:先看标示符:array,只有一个运算符[],那么array就是数组,元素类型是int,完了. 2.难一点的 (1)数组指针 int(*array)[3]; 结论:array是一指针,指向一数组,数组规模是3,

C语言复杂表达式与指针应用

基础知识 (1)指针数组:int *a[10] 理解:a和[]先结合,构成数组a[10](同时说明这变量的本质是数组,所以最终应该叫做**数组),紧接着与*号结合说明这个数组中10个元素都是指针,且指向的是int型变量.因此他是一个指针数组. (2)数组指针:int (*a)[10] 理解:a首先和*号结合表明变量a是一个指针变量(本质就是个指针,所以最终应该叫**指针),紧接着和[]结合,表明这个指针变量指向一个数组,这个数组由10个int类型元素构成.所以名称为数组指针. (3)函数指针 譬