繁体   English   中英

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

[英]Output Explanation of this program in C?

我在C中有这个程序:

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

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

小端输出为556。

我试图了解输出。 这是我的解释。

问题是答案在大字节序机器中会保持不变吗?

我= 300; => i = 100101100 //以字格式的二进制格式=> BB Hb 0001 00101100其中B =字节而Hb =半字节

(A)=>在内存中(假设它是小尾数法)

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

0x12345679 - 0001 - 0000

0x1234567a - 0000 - 0000

0x1234567b - 0000 - 0000

0x1234567c-下一个整数的位置(ptr或ptr +1的位置,其中ptr是整数指针,因为ptr的类型为int =>在执行++ ptr时它将增加4个字节( int的大小 ))

什么时候

(B)我们做char * ptr =&i; ptr在执行++ ptr时将变成char =>类型,它将增加1个字节( char的大小 ),因此在执行++ ptr时它将跳转到位置-> 0x12345679(具有0001-0000),现在我们正在执行+ + ptr = 2 => 0x12345679将被2覆盖=> 0x12345679将具有00 * 10 **-0000而不是000 * 1 *-0000

因此新的内存内容将如下所示:

(C)

0x12345678 - 1100 - 0010

0x12345679 - 0010 - 0000

0x1234567a - 0000 - 0000

0x1234567b - 0000 - 0000

等价于=> BB Hb 0010 00101100,其中B =字节,Hb =半字节

我的推理正确吗,还有其他简短的方法吗? Rgds,Softy

在低字节序的32位系统中,通常将int 300 (* 0x012c )存储为4个连续字节(*),最低字节为: 2C 01 00 00 当您将原来为int指针&i的char指针递增时,您将指向该序列的第二个字节,并将其设置为2将使序列2C 02 00 00 -当返回int时, 0x22c或556。

(就您对位序列的理解而言……似乎有点不对。 字节序会影响内存中的字节顺序,因为字节是可寻址的最小单位。字节中的位不会反转;低位字节无论系统是小端还是大端,都将是2C00101100 )(即使系统确实反转了一个字节的位,它也会再次反转它们以数字的形式呈现给您,所以您不会最大的区别是该字节在序列中的位置。唯一影响比特顺序的位置是在硬件和驱动程序中,以及一次只能接收不到一个字节的位置。

在big-endian系统中,int通常由字节序列00 00 01 2C表示(*)(与little-endian表示形式完全不同的是字节顺序-最高字节在前)。 您仍然在修改序列的第二个字节,尽管...将00 02 01 2C设为int为0x02012c0x02012c

(*)许多事情在这里发挥作用,包括二进制补码(如今几乎所有系统都使用它的补码,但是C不需要), sizeof(int)的值,对齐/填充以及系统是否是真正的大尾数或小尾数或半确定的实现。 这是为什么混入较大类型的字节经常导致未定义或特定于实现的行为的重要原因。

这是你的int

int i = 300;     

这就是内存在&i处包含的内容: 2c 01 00 00使用下一条指令,将i的地址分配给ptr ,然后使用++ptr移至下一个字节并将其值更改为2

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

因此,现在内存包含: 2c 02 00 00 (即556)。 区别在于,在大端系统中,地址i可以看到00 00 01 2C ,而在更改之后: 00 02 01 2C

即使int的内部表示是实现定义的

对于有符号整数类型,对象表示的位应分为三组:值位,填充位和符号位。 不需要任何填充位; 带符号的字符不得有任何填充位。 恰好有一个符号位。 作为值位的每一位应具有与相应无符号类型的对象表示形式中相同位相同的值(如果有符号类型中有M个值位,无符号类型中有N个值,则M≤N)。 如果符号位为零,则它将不影响结果值。 如果符号位为1,则该值应通过以下方式之一进行修改:—取反符号位0的对应值(符号和大小); —符号位的值为−(2M)(二进制补码); —符号位的值为-(2M-1)(补码)。 其中哪一个是实现定义的 ,标志位为1且所有值位为零的值(对于前两个)还是标志位且所有值位为1(位的补码)是陷阱表示?或正常值。 在符号,大小和“ 1”的补码情况下,如果此表示形式是正常值,则称为负零。

这是实现定义的。 根据标准尚不清楚int的内部表示形式,因此您正在做的事情不是可移植的。 参见C标准中的6.2.6.2节。

但是,由于大多数实现都使用带符号的整数的二进制补码表示,因此字节序会影响结果,如cHaos答案中所述。

我喜欢实验,这就是拥有PowerPC G5的原因。

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;
}

生成命令:

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

输出:

131372 or 2012c

简历:cHao的答案是完整的,如果您有疑问,这里是实验证据。

暂无
暂无

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

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