2013-10-12 29 views
0

我对C中的指针进行了一些回顾,而且我遇到了一些我遇到的代码时感到困惑。我是在做qeeksquiz.com/pointers测验复习,而我整个这一段代码来:关于机器相关指针值的困惑

#include<stdio.h> 
int main() 
{ 
    int a; 
    char *x; 
    x = (char *) &a; 
    a = 512; 
    x[0] = 1; 
    x[1] = 2; 
    printf("%d\n",a); 
    return 0; 
} 

,当我遇到x = (char *) &a来到我有点糊涂了。我知道x是一个指针,它包含a的地址,但当我们指定x[0] = 1x[1] = 2;时,答案在打印时为513.答案说明它如何依赖于我们正在使用的机器以及小端机器改变它如何读取二进制文件。我完全困惑于我们如何从512到513.我猜这是因为x [0] = 1,但我不是100%确定。有人可以帮忙解释一下吗?如果我们分配了x[0] = 2,那么变化的值是多少?

感谢您的帮助!

+0

INT存储为一个字节序列。这里只有2个字节被初始化:然后将值计算为x [0] + 256 * x [1] = 1 + 256 * 2 = 513.如果它是一个不同的endian机器,那么(假设int使用2个字节,这并不总是正确的),这可能是另一种方式:x [1] + 256 * x [0] = 2 + 256 = 258。 – Ashalynd

+0

你从哪里获得256乘以x [1]? – user1871869

+0

256是2 ** 8,而8是一个字节中的位数。 – Ashalynd

回答

2

为x是字符指针,就意味着X [0]和X [1]是参照单个字节的数据,所以在存储你有像这样的数据:

1 2 

但是,输出过程中你试图引用与16/32位相同的数据,所以我们没有2个单字节,而是1个字,它在内存中存储为0x01 0x02,对于小端,这意味着我们应该交换它们,所以我们得到编号0x201 ,这是十进制表示法中的513

对于大端序列它将是0x102它是十进制的258

+0

它不依赖于'sizeof(int)'吗? –

+0

只有16位“int”才会有258个。对于32位'int',它将是0x01020000 – kotlomoy

+0

@kotlomoy你是对的 –

2

ASCII艺术!

    Little endian    Big endian 

       +----+----+----+----+  +----+----+----+----+ 
a = 0x200:  | 00 | 02 | 00 | 00 |  | 00 | 00 | 02 | 00 | 
       +----+----+----+----+  +----+----+----+----+ 

       +----+----+----+----+  +----+----+----+----+ 
x[0] = 1:  | 01 | 02 | 00 | 00 |  | 01 | 00 | 02 | 00 | 
       +----+----+----+----+  +----+----+----+----+ 

       +----+----+----+----+  +----+----+----+----+ 
x[1] = 2:  | 01 | 02 | 00 | 00 |  | 01 | 02 | 02 | 00 | 
       +----+----+----+----+  +----+----+----+----+ 

result:   1x1 + 2x256 = 513  1x16777216 + 1x65536 + 2x256 + 0x1 = big 
1

整数由一系列字节组成。但是在不同的系统中字节的顺序是不同的。例如,请考虑编号134480385(二进制= 00001000000001000000001000000001)。在小端系统,它是(在左侧用最低的地址)

00000001 00000010 00000100 00001000

但大端系统上,则字节存储周围的其他方式。 LEFT仍然是最低的地址。

00001000 00000100 00000010 00000001

当你把整数及演员地址为char(字节)的指针,它指向整数的第一个字节(最低的地址)。向指针写入1时,最低字节设置为00000001.但是,char只有1个字节长,所以其他字节不变。然后,第二个字节被设置为00000010

在您的例子,512小尾数是

00000000 00000010

大端是更棘手的,因为结果取决于有多少字节在INT。它通常是4,但可能是2或更多。作为2个字节的INT,512内存

00000010 00000000

,并为4个字节的诠释是

00000000 00000000 00000010 00000000

(它不小端无所谓,因为多余的字节都只是零)

1写入第一个字节,2到第二个字节后,在内存中得到一个4字节的小端

00000001 00000010 00000000 00000000

4字节大端

00000001 00000010 00000010 00000000

注意,在第三个字节的位仍然存在。这是因为我们只写了前两个字节。第三和第四个字节保持不变。

和2字节的大端

00000001 00000010

解读2或4个字节的存储器(忽略2字节的额外的零),为小端号码作为一个正常的二进制数是

00000000000000000000001000000001 = 513

解读4字节存储器作为大端数作为一个正常的二进制数是

00000001000000100000001000000000 = 16908800

解读2个字节的内存一样大尾数号码作为一个正常的二进制数是

0000000100000010 = 258

我可能犯了一个错误在我的计算,但希望你的想法。这就是为什么在不同类型的指针之间进行转换时需要小心。

0

正如其他人指出的,诀窍是了解如何在内存中表示整数和字符。我已经编写了一些C++代码,试图向您展示这一点。将其粘贴到一个文件中,编译&运行;然后更改main中的值并查看会发生什么情况。下面的代码:

#include <stdio.h> 

// print one byte as a binary number 
void print_binary(unsigned u) { 
    for (int i = 7; i >= 0; --i) 
     printf("%d", (u >> i) & 1); 
} 

// print a number's binary representation 
template <typename T> 
void print_int_binary(T i) { 
    char *cp = (char*)&i; 
    for (int i = 0; i < sizeof(T); ++i) { 
     print_binary(cp[i]); 
     printf(" "); 
    } 
    printf("\n"); 
} 

// show how the variable is represented in memory 
template <typename T> 
void print_var_binary(const char *name, T t) { 
    printf("%s is stored as %d bytes:\n", name, (int)sizeof(t)); 
    print_int_binary(t); 
} 

#define PRINT(a) print_var_binary(#a, a); 

int main() { 
    PRINT((int)513) 
    PRINT((char)2) 
} 

当我在我的(小端)计算机上运行它,它打印:

(int)513 is stored as 4 bytes: 
00000001 00000010 00000000 00000000 
(char)2 is stored as 1 bytes: 
00000010