简体   繁体   English

32位或64位系统中的长短指针运算

[英]Pointer Arithmetic long and short in 32bit or 64bit System

I am just studying for an exam and the following question is asked, what output does the following program generate in 32 bit or 64 bit?我只是为了考试而学习,并提出以下问题,以下程序在 32 位或 64 位中生成什么输出?

#include <stdio.h>
int main(int argc, char **argv)
{
 long *p = (long *)8;
 short *q = (short *)0;
 int c, i, l;

 p = p + 1;
 q = q + 1;

 printf("p = %p q = %p\n", p, q);

 c = (char *)p - (char *)q;
 i = (int *)p - (int *)q;
 l = (long *)p - (long *)q;

 printf("c = %d, i = %d, l = %d\n", c, i, l);

 return 0;
}

The result on 32bit is the following: 32位的结果如下:

p = 0xc q = 0x2
c = 10, i = 2, l = 2

The result on 64bit is the following: 64位的结果如下:

p = 0x10 q = 0x2
c = 14, i = 3, l = 1

Only I must confess, I can't understand these results at all, because when I count up a pointer it should point to something random in the memory, it always comes out 0xc or 0x10.只有我必须承认,我根本无法理解这些结果,因为当我计算一个指针时,它应该指向内存中的随机内容,它总是出现 0xc 或 0x10。

Can someone help me?有人能帮我吗?

Only I must confess, I can't understand these results at all, because when I count up a pointer it should point to something random in the memory, it always comes out 0xc or 0x10.只有我必须承认,我根本无法理解这些结果,因为当我计算一个指针时,它应该指向内存中的随机内容,它总是出现 0xc 或 0x10。

The program doesn't access "value in memory pointed to by the pointer" for any of the pointers.该程序不会访问任何指针的“指针指向的内存中的值”。 It only does pointer arithmetic (changing what the pointer points to).它只做指针运算(改变指针指向的内容)。

The goal of the question is likely to test if you understand how pointer arithmetic works in C.该问题的目标可能是测试您是否了解指针运算在 C 中的工作原理。

How pointer arithmetic works in C is that it hides a "multiplication by sizeof(whatever the pointer points to)".指针算法在 C 中的工作原理是它隐藏了“乘以 sizeof(无论指针指向什么)”。 In other words, p = p + n;换句话说, p = p + n; is roughly equivalent to p = (char *)p + n * sizeof(*p);大致相当于p = (char *)p + n * sizeof(*p); , or alternatively p = &p[n]; , 或者p = &p[n]; . .

First, I should point out that there's a lot of undefined behavior in this code, and it makes a lot of assumptions that aren't guaranteed by the standard.首先,我应该指出这段代码中有很多未定义的行为,并且它做出了很多标准无法保证的假设。 But that having been said, the question can be answered in terms of what you'll see on a typical implementation.但话虽如此,这个问题可以根据您将在典型实现中看到的内容来回答。

Let's assume that the data type sizes (in bytes) on the two machines are:让我们假设两台机器上的数据类型大小(以字节为单位)是:

type类型 32-bit size 32 位大小 64-bit size 64 位大小
long 4 4 8 8
int整数 4 4 4 4
short短的 2 2 2 2
char字符 1 1 1 1

Again, I don't think these are guaranteed, but they are very typical.同样,我不认为这些是有保证的,但它们非常典型。

Now consider what the code is doing.现在考虑代码在做什么。 First, it's setting首先是设置

   long *p = (long *)8;
   short *q = (short *)0;

These addresses do not refer to valid data (at least, not portably), but the code is never actually deferencing them.这些地址不引用有效数据(至少,不是可移植的),但代码实际上从未延迟它们。 All it's doing is using them to perform pointer arithmetic.它所做的只是使用它们来执行指针运算。

First, it increments them:首先,它增加它们:

   p = p + 1;
   q = q + 1;

When adding an integer to a pointer, the integer is scaled by the size of the target data type.将整数添加到指针时,整数会按目标数据类型的大小进行缩放。 So in the case of p , the scale is 4 (for 32-bit) or 8 (for 64-bit).所以在p的情况下,比例是 4(32 位)或 8(64 位)。 In the case of q, the scale is 2 (in both cases).在 q 的情况下,比例为 2(在两种情况下)。

So p becomes 12 (for 32-bit) or 16 (for 64-bit), and q becomes 2 (in both cases).因此p变为 12(对于 32 位)或 16(对于 64 位),而q变为 2(在这两种情况下)。 When printed in hex, 12 is 0xc and 16 is 0x10 , so this is consistent with what you saw.以十六进制打印时, 12 是0xc , 16 是0x10 ,因此这与您看到的一致。

Then it takes the differences between the two pointer, after first casting them to various different pointer types:然后在首先将它们转换为各种不同的指针类型之后,获取两个指针之间的差异:

 c = (char *)p - (char *)q;
 i = (int *)p - (int *)q;
 l = (long *)p - (long *)q;

These results exhibit undefined behavior, but if you assume that all pointer values are byte addresses, then here's what's happening.这些结果表现出未定义的行为,但如果您假设所有指针值都是字节地址,那么这就是正在发生的事情。

First, when subtracting two pointers of the same type, the difference is divided by the size of the target data type.首先,当两个相同类型的指针相减时,差值除以目标数据类型的大小。 This gives the number of elements of that type separating the two pointers.这给出了分隔两个指针的该类型元素的数量。

So in the case of c (type char * ), it divides by 1, giving the raw pointer difference, which is (12 - 2) = 10 (for 32-bit) and (16 - 2) = 14 (for 64-bit).因此,在c (类型char * )的情况下,它除以 1,给出原始指针差异,即 (12 - 2) = 10(对于 32 位)和 (16 - 2) = 14(对于 64-少量)。

For i (type int * ), it divides by 4 (and truncates the result), so the difference is 10 / 4 = 2 (for 32-bit) and 14 / 4 = 3 (for 64-bit).对于iint *类型),它除以 4(并截断结果),因此差异是 10 / 4 = 2(对于 32 位)和 14 / 4 = 3(对于 64 位)。

Finally, for l (type long* ), it divides by 4 (for 32-bit) or 8 (for 64-bit), again truncating the result.最后,对于l (类型long* ),它除以 4(对于 32 位)或 8(对于 64 位),再次截断结果。 So the difference is 10 / 4 = 2 (for 32-bit) and 14 / 8 = 1 (for 64-bit).所以差异是 10 / 4 = 2(对于 32 位)和 14 / 8 = 1(对于 64 位)。

Again, the C standard does not guarantee any of this, so it is not safe to assume these results will be obtained on different platforms.同样,C标准保证任何的这一点,所以它不是安全的假设,这些结果将在不同平台上获得。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM