首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

一个比较偏的类型转换有关问题

2012-05-12 
一个比较偏的类型转换问题得到一个field在结构体(struct)中的偏移量#define FPOS(type,field) ((dword)&((

一个比较偏的类型转换问题

得到一个field在结构体(struct)中的偏移量
#define FPOS(type,field) ((dword)&((type *)0)->field)



这里我有个疑问,(type *)0 把0进行强制转换,这样的依据是什么,转换后的内存地址是多少,这个地址是不是有效的?







[解决办法]
偏移量是相对值,所以可以那样做。你甚至可以这样做:

C/C++ code
#define FPOS(type,field) ((int)&((type *)10000)->field - 10000)// 1. 假定一个type变量的起始地址在10000,((type *)10000)就是将该地址开始,后面的sizeof(type)的内//    存中的内容,看成是type。// 2. (int)&((type *)10000)->field,这个是取field的绝对地址,并将其转换为int(大致和你上面的dword相当)// 3. (int)&((type *)10000)->field - 10000,这个是用field的绝对地址减去起始地址,自然就是偏移量了// 4. 很明显,将10000改成0,就可以省去减号及其后面的部分,看起来更简洁一些而已。typedef struct _A{    int a;    int b;    char c;    char d;    char e;    char f;} A;int main(int argc, char** argv){    cout << FPOS(A, d) << endl;    return 0;}
[解决办法]
探讨

它要的只是地址,并没有真正去访问这个存储单元,这么做是没问题的,从0取值才能得到偏移量,如果从某结构体变量取值,那就成绝对线性地址了,这个应该好理解的!

[解决办法]
ISO C11 N1570
6.3.2.3
3 An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.66) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
4 Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.
5 An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.67)
6 Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.
7.19
3 The macros are
NULL
which expands to an implementation-defined null pointer constant; and
offsetof(type, member-designator) which expands to an integer constant expression that has type size_t, the value of which is the offset in bytes, to the structure member (designated by member-designator), from the beginning of its structure (designated by type). The type and member designator shall be such that given
static type t;
then the expression &(t.member-designator) evaluates to an address constant. (If the specified member is a bit-field, the behavior is undefined.)
某种意义上来说,正因为这个impl-def造成实现的不确定性,所以标准库有必要包含offsetof。


[解决办法]
#define FPOS(type,field) ((int)&((type *)10000)->field - 10000)

编译器在展开这个宏时,并不会真正去访问这个地址(10000)的,而是假设10000是某个type类型的变量的地址,然后得这个变量的field字段的的偏移,在减去这个变量的地址,就得到field字段相对于结构体第一个程序的偏移。

实际上,这个宏,编译器在编译期就可其确定其值,而不是在运行期计算的。下面是我做的一个实验,分别给出我实验的源代码和汇编代码

源代码
#define FPOS(type,field) ((int)&((type *)10000)->field - 10000)

typedef struct
{
int f1;
char f2;
int f3;
char f4;
}MY_ST;

int main()
{
int n=FPOS(MY_ST,f2);
printf("n=%d\n",n);
return 0;

}

汇编代码
_mainPROC; COMDAT
; 17 : int n=FPOS(MY_ST,f2);
; 18 : printf("n=%d\n",n);

push4
pushOFFSET ??_C@_05HKPJIDL@n?$DN?$CFd?6?$AA@
callDWORD PTR __imp__printf
addesp, 8

; 19 : return 0;
xoreax, eax
}





热点排行