简体   繁体   English

输出该程序在C语言中的解释?

[英]Output Explanation of this program in C?

I have this program in C: 我在C中有这个程序:

int main(int argc, char *argv[])
{

  int i=300;
  char *ptr = &i;
  *++ptr=2;
  printf("%d",i);
  return 0;
}

The output is 556 on little endian. 小端输出为556。

I tried to understand the output. 我试图了解输出。 Here is my explanation. 这是我的解释。

Question is Will the answer remains the same in the big endian machine? 问题是答案在大字节序机器中会保持不变吗?

i = 300; 我= 300; => i = 100101100 //in binary in word format => BB Hb 0001 00101100 where B = Byte and Hb = Half Byte => i = 100101100 //以字格式的二进制格式=> BB Hb 0001 00101100其中B =字节而Hb =半字节

(A)=> in memory (assuming it is Little endian)) (A)=>在内存中(假设它是小尾数法)

0x12345678 - 1100 - 0010 ( Is this correct for little endian)

0x12345679 - 0001 - 0000

0x1234567a - 0000 - 0000

0x1234567b - 0000 - 0000

0x1234567c - Location of next intezer(location of ptr++ or ptr + 1 where ptr is an intezer pointer as ptr is of type int => on doing ++ptr it will increment by 4 byte( size of int )) 0x1234567c-下一个整数的位置(ptr或ptr +1的位置,其中ptr是整数指针,因为ptr的类型为int =>在执行++ ptr时它将增加4个字节( int的大小 ))

when 什么时候

(B)we do char *ptr = &i; (B)我们做char * ptr =&i; ptr will become of type char => on doing ++ptr it will increment by 1 byte( size of char ) so on doing ++ptr it will jump to location -> 0x12345679 (which has 0001 - 0000) now we are doing ++ptr = 2 => 0x12345679 will be overwritten by 2 => 0x12345679 will have 00 *10** - 0000 instead of 000* 1 * - 0000 ptr在执行++ ptr时将变成char =>类型,它将增加1个字节( char的大小 ),因此在执行++ ptr时它将跳转到位置-> 0x12345679(具有0001-0000),现在我们正在执行+ + ptr = 2 => 0x12345679将被2覆盖=> 0x12345679将具有00 * 10 **-0000而不是000 * 1 *-0000

so the new memory content will look like this : 因此新的内存内容将如下所示:

(C) (C)

0x12345678 - 1100 - 0010

0x12345679 - 0010 - 0000

0x1234567a - 0000 - 0000

0x1234567b - 0000 - 0000

which is equivalent to => BB Hb 0010 00101100 where B = Byte and Hb = Half Byte 等价于=> BB Hb 0010 00101100,其中B =字节,Hb =半字节

Is my reasoning correct?Is there any other short method for this? 我的推理正确吗,还有其他简短的方法吗? Rgds, Softy Rgds,Softy

In a little-endian 32-bit system, the int 300 ( 0x012c ) is typically(*) stored as 4 sequential bytes, lowest first: 2C 01 00 00 . 在低字节序的32位系统中,通常将int 300 (* 0x012c )存储为4个连续字节(*),最低字节为: 2C 01 00 00 When you increment the char pointer that was formerly the int pointer &i , you're pointing at the second byte of that sequence, and setting it to 2 makes the sequence 2C 02 00 00 -- which, when turned back into an int, is 0x22c or 556. 当您将原来为int指针&i的char指针递增时,您将指向该序列的第二个字节,并将其设置为2将使序列2C 02 00 00 -当返回int时, 0x22c或556。

(As for your understanding of the bit sequence...it seems a bit off. Endianness affects byte order in memory, as the byte is the smallest addressable unit. The bits within the byte don't get reversed; the low-order byte will be 2C ( 00101100 ) whether the system is little-endian or big-endian. (Even if the system did reverse the bits of a byte, it'd reverse them again to present them to you as a number, so you wouldn't notice a difference.) The big difference is where that byte appears in the sequence. The only places where bit order matters, is in hardware and drivers and such where you can receive less than a byte at a time.) (就您对位序列的理解而言……似乎有点不对。 字节序会影响内存中的字节顺序,因为字节是可寻址的最小单位。字节中的位不会反转;低位字节无论系统是小端还是大端,都将是2C00101100 )(即使系统确实反转了一个字节的位,它也会再次反转它们以数字的形式呈现给您,所以您不会最大的区别是该字节在序列中的位置。唯一影响比特顺序的位置是在硬件和驱动程序中,以及一次只能接收不到一个字节的位置。

In a big-endian system, the int is typically(*) represented by the byte sequence 00 00 01 2C (differing from the little-endian representation solely in the byte order -- highest byte comes first). 在big-endian系统中,int通常由字节序列00 00 01 2C表示(*)(与little-endian表示形式完全不同的是字节顺序-最高字节在前)。 You're still modifying the second byte of the sequence, though...making 00 02 01 2C , which as an int is 0x02012c or 131372. 您仍然在修改序列的第二个字节,尽管...将00 02 01 2C设为int为0x02012c0x02012c

(*) Lots of things come into play here, including two's complement (which almost all systems use these days...but C doesn't require it), the value of sizeof(int) , alignment/padding, and whether the system is truly big- or little-endian or a half-assed implementation of it. (*)许多事情在这里发挥作用,包括二进制补码(如今几乎所有系统都使用它的补码,但是C不需要), sizeof(int)的值,对齐/填充以及系统是否是真正的大尾数或小尾数或半确定的实现。 This is a big part of why mucking around with the bytes of a bigger type so often leads to undefined or implementation-specific behavior. 这是为什么混入较大类型的字节经常导致未定义或特定于实现的行为的重要原因。

This is your int : 这是你的int

int i = 300;     

And this is what the memory contains at &i : 2c 01 00 00 With the next instruction you assign the address of i to ptr , and then you move to the next byte with ++ptr and change its value to 2 : 这就是内存在&i处包含的内容: 2c 01 00 00使用下一条指令,将i的地址分配给ptr ,然后使用++ptr移至下一个字节并将其值更改为2

char *ptr = &i;
*++ptr = 2;

So now the memory contains: 2c 02 00 00 (ie 556). 因此,现在内存包含: 2c 02 00 00 (即556)。 The difference is that in a big-endian system in the address of i you would have seen 00 00 01 2C , and after the change: 00 02 01 2C . 区别在于,在大端系统中,地址i可以看到00 00 01 2C ,而在更改之后: 00 02 01 2C

Even if the internal rappresentation of an int is implementation-defined : 即使int的内部表示是实现定义的

For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit. 对于有符号整数类型,对象表示的位应分为三组:值位,填充位和符号位。 There need not be any padding bits; 不需要任何填充位; signed char shall not have any padding bits. 带符号的字符不得有任何填充位。 There shall be exactly one sign bit. 恰好有一个符号位。 Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type (if there are M value bits in the signed type and N in the unsigned type, then M ≤ N). 作为值位的每一位应具有与相应无符号类型的对象表示形式中相同位相同的值(如果有符号类型中有M个值位,无符号类型中有N个值,则M≤N)。 If the sign bit is zero, it shall not affect the resulting value. 如果符号位为零,则它将不影响结果值。 If the sign bit is one, the value shall be modified in one of the following ways: — the corresponding value with sign bit 0 is negated (sign and magnitude); 如果符号位为1,则该值应通过以下方式之一进行修改:—取反符号位0的对应值(符号和大小); — the sign bit has the value −(2M) (two's complement); —符号位的值为−(2M)(二进制补码); — the sign bit has the value −(2M − 1) (ones' complement). —符号位的值为-(2M-1)(补码)。 Which of these applies is implementation-defined , as is whether the value with sign bit 1 and all value bits zero (for the first two), or with sign bit and all value bits 1 (for ones' complement), is a trap representation or a normal value. 其中哪一个是实现定义的 ,标志位为1且所有值位为零的值(对于前两个)还是标志位且所有值位为1(位的补码)是陷阱表示?或正常值。 In the case of sign and magnitude and ones' complement, if this representation is a normal value it is called a negative zero. 在符号,大小和“ 1”的补码情况下,如果此表示形式是正常值,则称为负零。

This is implementation defined. 这是实现定义的。 The internal representation of an int is not known according to the standard, so what you're doing is not portable. 根据标准尚不清楚int的内部表示形式,因此您正在做的事情不是可移植的。 See section 6.2.6.2 in the C standard. 参见C标准中的6.2.6.2节。

However, as most implementations use two's complement representation of signed ints, the endianness will affect the result as described in cHaos answer. 但是,由于大多数实现都使用带符号的整数的二进制补码表示,因此字节序会影响结果,如cHaos答案中所述。

I like experiments and that's the reason for having the PowerPC G5. 我喜欢实验,这就是拥有PowerPC G5的原因。

stacktest.c: stacktest.c:

int main(int argc, char *argv[])
{
  int i=300;
  char *ptr = &i;
  *++ptr=2;
  /* Added the Hex dump */
  printf("%d or %x\n",i, i);
  return 0;
}

Build command: 生成命令:

powerpc-apple-darwin9-gcc-4.2.1 -o stacktest stacktest.c

Output: 输出:

131372 or 2012c

Resume: the cHao's answer is complete and in case you're in doubt here is the experimental evidence. 简历:cHao的答案是完整的,如果您有疑问,这里是实验证据。

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

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