[英]How to get the actual address of a pointer in C?
BACKGROUND: 背景:
I'm writing a single level cache simulator in C for a homework assignment, and I've been given code that I must work from. 我正在C中编写一个单级缓存模拟器来完成作业,我已经获得了必须使用的代码。 In our discussions of the cache, we were told that the way a small cache can hold large addresses is by splitting the large address into the position in the cache and an identifying tag.
在我们对缓存的讨论中,我们被告知小缓存可以容纳大地址的方式是将大地址分成缓存中的位置和识别标记。 That is, if you had an 8 slot cache but wanted to store something with address larger than 8, you take the 3 (because 2^3=8) rightmost bits and put the data in that position;
也就是说,如果你有一个8槽缓存但想要存储地址大于8的东西,你可以取3(因为2 ^ 3 = 8)最右边的位并将数据放在那个位置; so if you had address 22 for example, binary 10110, you would take those 3 rightmost bits 110, which is decimal 5, and put it in slot 5 of the cache.
因此,如果您有地址22,例如二进制10110,您将获取那些最右边的位110,即十进制5,并将其放入缓存的插槽5中。 You would also store in this position the tag, which is the remaining bits 10.
您还可以在此位置存储标记,即剩余的位10。
One function, cache_load, takes a single argument, and integer pointer. 一个函数cache_load接受一个参数和整数指针。 So effectively, I'm being given this int* addr which is an actual address and points to some value.
所以有效的是,我正在给这个int * addr这是一个实际的地址,并指向一些值。 In order to store this value in the cache, I need to split the addr.
为了将此值存储在缓存中,我需要拆分addr。 However, the compiler doesn't like when I try to work with the pointer directly.
但是,当我尝试直接使用指针时,编译器不喜欢。 So, for example, I try to get the position by doing:
所以,例如,我试图通过这样做来获得这个位置:
npos=addr%num_slots
The compiler gets angry and gives me errors. 编译器生气并给我错误。 I tried casting to an int, but this actually got me the value that the pointer was pointing to, not the numerical address itself.
我尝试转换为int,但这实际上得到了指针指向的值,而不是数字地址本身。 Any help is appreciated, thanks!
任何帮助表示赞赏,谢谢!
[edit] [编辑]
int load(int * addr) {
int value = (use_memory ? (*addr) : 0);
intptr_t taddr=(intptr_t) addr;
int npos=taddr % blocks;
int ntag=taddr / blocks;
printf("addr is %p, taddr is %p, npos is %d and ntag is %d\n",addr,taddr,npos,ntag);
When addr is passed in, it's actual address is 58, and it points to a value of 88. The output I'm getting from that printf is: 当传入addr时,它的实际地址是58,它指向值88.我从该printf得到的输出是:
addr is 58, taddr is 58, npos is 0 and ntag is 11 addr是58,taddr是58,npos是0,ntag是11
So it seems taddr is getting 58 (when printed with %p, still shows 88 when printed with %d), but npos and ntag are showing up as 0 and 11 (as though the mathematical operations are being run with 88) instead of 2 and 7 as I'd like. 所以似乎taddr得到58(当用%p打印时,在打印%d时仍然显示88),但是npos和ntag显示为0和11(好像数学运算用88运行)而不是2和我一样。
The code is used like this: 代码使用如下:
void load_words (int n, int words[]) {
int i;
for (i=0; i<n; i++) {
load( (int *) (words[i] * 4));
cache_print();
}
}
You should use something like 你应该使用类似的东西
int *pointer;
intptr_t address=(intptr_t) pointer;
and this is mainly just a correction on @Andrew's post 这主要只是对@ Andrew的帖子的修正
So your function should become 所以你的功能应该成为
(oops forgot this was homework. I'll roll back this question in a while. Can't straight give you the answer :) ) (哎呀忘了这是家庭作业。我会在一段时间内回复这个问题。不能直接给你答案:))
C99标准表示从指针类型到整数类型的转换(反之亦然)是实现定义的行为(6.3.2.3.5和6.3.2.3.6),除非使用<stdint.h>
定义的intptr_t
或uintptr_t
但是7.18.1.4说这两种类型不是强制性的,并且实现不需要提供它们。
int *pointer;
uint32_t address = (uint32_t) pointer;
Except of course, you have no guarantee that an int* fits in an uint32_t, so you need to pick the right types for your platform. 当然,除了你不能保证int *适合uint32_t,所以你需要为你的平台选择正确的类型。
Decimal 88 is 0x58 (hex 58). 十进制88是0x58(十六进制58)。 When you use the %p specifier with printf, the hex representation is printed out.
将%p说明符与printf一起使用时,将打印出十六进制表示。 So both addr and taddr are decimal 88, and your calculations are correct.
所以addr和taddr都是十进制88,你的计算是正确的。
One important thing not already mentioned here. 这里还没有提到一个重要的事情。 When you print a pointer with the %p specifier, then you should cast the argument:
当您使用%p说明符打印指针时,您应该转换参数:
printf("addr is %p\n", (void *)addr);
%p expects a pointer to void, and a specifier/argument mismatch for printf is undefined behavior. %p期望指向void,而printf的说明符/参数不匹配是未定义的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.