2010-10-31 53 views
5

从我所了解的'&'运算符开始,它返回内存中操作数的基地址。了解'&'运算符

让我们想象一下以下情形(如我的机器上):

  • 的sizeof(INT)= 4个字节
  • 的sizeof(浮动)= 4个字节
  • 的sizeof(焦炭)= 1个字节

现在,如果我写的东西是这样的:

void main() { 
int i = 5411; 
int *ip = &i; 
char *c = &i; 

printf("%d",*ip); 
printf("%c",*c); 
} 

第一个printf()应该给我5411.说到第二个printf(),我的基地址包含10101001(char类型指针的高阶8位= 1字节)。 因此* c应该给我169,当它转换成%c时是一个无效的字符。

但编译器给我'#'或其他有效的输出。为什么这样?任何投入?

编辑(从作者的评论答案的一个拍摄):

这只是一个虚拟的情况下,因为我是从实际的机器了。
实际情况是我= 5411

+0

在任何情况下,如果您尝试“打印”“字符”,它将显示为字符,而不是相应的整数代码。 – 2010-10-31 20:20:56

+0

可能与使用字符编码有关,我猜想。 – 2010-10-31 20:21:48

+0

是的,我也同意这一点。但是必须有一个从上一次printf()获得'#'值的理由。这不是垃圾值。 – 2010-10-31 20:23:03

回答

24

您似乎很难理解整数如何存储在内存中。以5411为例。

5411 = 1010100100011 

这个数13的二进制数有然而,由于int是32位的,它必须是垫32个位数

5411 = 00000000 00000000 00010101 00100011 

在一个小端机(X86,默认情况下ARM),所述至少显著字节被存储在前面,所以在存储器中:

00100011 00010101 00000000 00000000 
^ 
c   c + 1  c + 2  c + 3 
ip 

因此,*c应返回00100011即35('#')。

+0

嘿,非常感谢!这正是我所期待的:-) – 2010-10-31 20:45:22

+0

'5411'从哪里来? OP的代码清楚地用'1154'初始化'i'。 – AnT 2010-10-31 20:48:16

+0

@AndreyT:查看OP对其他答案的评论。 – kennytm 2010-10-31 20:48:47

5

ASCII只定义字符可达127除此之外,你真正想要做的是打印在*c数字对应的值,这也是采用%d完成。 ..

printf("%d",*c); 

...如你预期应显示的数量。

+0

这只是一个虚拟的案例,因为我远离了实际的机器。实际情况是i = 5411.%c给出'#',%d给出35(而不是169) – 2010-10-31 20:26:23

+0

@Guarav:ASCII仍然只定义了127个字符,而你真正想要的是打印数字,所以打印号码,而不是字符。 – 2010-10-31 20:27:41

+2

@Gaurav - 你为什么期待169?在一个小端机器上,它应该是35.在一个大端机器上,对于“扩展ASCII”应该是0. – 2010-10-31 20:32:08

1

* c的地址是i的地址,因为您已将c分配给& i。然后它将采用最高或最低(取决于末端)并打印该字符。

+0

i = 5411的情况是打印'#'作为字符。 35(10101001)的ASCII,它既不是高8位也不低8位。 – 2010-10-31 20:31:25

+0

@Gaurav - 35二进制是00100011 – 2010-10-31 20:35:09

+0

同意。 * c将不会被截断,因为字符指针足够大以保存内存位置的整个值。 – 2010-10-31 20:35:18

1

只是为了学习一些有关你的整数的编码,你应该尝试一下,做

printf("0x%X, %X|%X|%X|%X\n", 
    i, 
    i & 0xFF, 
    (i >> 8) & 0xFF 
    (i >> 16) & 0xFF 
    (i >> 24) & 0xFF 
); 

的然后做同样的c[0]c[1]等和其他格式字符串作为%c

3

首先,你的程序不合格。 C和C++都不允许初始化带有int *值的char *指针。您需要在初始化指针c时进行显式强制转换。

其次,原始整数i的哪个字节 - 高阶或低阶 - 驻留在其“基址”是实现定义的。有小端架构,其中较低阶但将通过*c(在8位char机器上具有值130,而不是114)看到。并且有大端架构,其中较高阶但是将通过*c(在8位char机器上的0)被看到。因此,您应该期望代码为130的字符或代码为0的字符使用%c格式说明符打印。

第三,在典型的实现中,通常没有“无效字符代码”之类的东西。对于任何代码,通常都会以某种方式打印。我没有看到你是如何设法获得#作为你的代码的输出。这是你正在运行的真实代码吗?

+0

嗨安德烈。 1->代码正在编译。我应该关心显式投射吗? ... 2->是的,我没有意识到这一点,KennyTM回答了...... 3->我提到,这是一个虚拟代码 – 2010-10-31 20:54:58

+1

@Gaurav Kalra:编译成什么?你标记了你的问题[C]和[C++]。这段代码不会被任何自尊的C++编译器编译为C++。过度宽松的错误检查的C编译器可能会允许(带有警告),但即使C代码仍然是非法的,所以如果您关心编写有效的C代码,则需要执行强制转换。 – AnT 2010-10-31 21:22:51