Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C for循环中*(&a&x2013;i)的含义。那是乘法吗?_C - Fatal编程技术网

C for循环中*(&a&x2013;i)的含义。那是乘法吗?

C for循环中*(&a&x2013;i)的含义。那是乘法吗?,c,C,我正在为即将到来的考试做准备,突然发现: 假设字大小为32位,int为32位,内存分配顺序与从地址位置68开始的声明相反 绘制一个图表,显示执行以下代码行的效果 for (i = 0; i < 8; i++) *(&a – i) = 'z'; (i=0;i0时已经是未定义的行为。但是在你的问题中,如果有独角兽和UB是过去的事情,你必须假设变量分配是按照声明的相反顺序进行的,并且没有任何填充,这将覆盖变量b和ai,我想我们可以假设这是一个理论上的问题问题,考虑到问题中未定义

我正在为即将到来的考试做准备,突然发现:

假设字大小为32位,int为32位,内存分配顺序与从地址位置68开始的声明相反

绘制一个图表,显示执行以下代码行的效果

for (i = 0; i < 8; i++)
    *(&a – i) = 'z';
(i=0;i<8;i++)的

*(&a-i)=‘z’;

这听起来可能很奇怪,但我是C语言的新手,这是我第一次看到for循环的乘法。请对循环和应用于循环的乘法进行解释。

这不是乘法,而是解引用指针。但是,
*(&a–i)
i>0
时已经是未定义的行为。但是在你的问题中,如果有独角兽和UB是过去的事情,你必须假设变量分配是按照声明的相反顺序进行的,并且没有任何填充,这将覆盖变量
b
ai

,我想我们可以假设这是一个理论上的问题问题,考虑到问题中未定义的其他假设(即字节顺序、填充)-问题是可以回答的。但是,正如@chux所指出的,有一些标准反对这种行为。因为,如果允许,代码将导致堆栈内存损坏。作为一个考试题,它实际上是要求你绘制出哪个内存被破坏了

如果我正确解释了这个问题,内存的一种可能表示形式(假设整数是LSB,有1字节填充,声明的顺序相反):


|地址|值|描述|
| ---- | ----- | ------------------------------ |
|55 | 0x00 |//int i=0|
|56 | 0x00 ||
|57 | 0x00 ||
|58 | 0x00 ||
|59 | 0x01 |//int-ai[]={1,2}|
|60 | 0x00 ||
|61 | 0x00 ||
|62 | 0x00 ||
|63 | 0x02 ||
|64 | 0x00 ||
|65 | 0x00 ||
|66 | 0x00 ||
|67 | 0x62 |//字符b='b'|
|68 | 0x61 |//字符a='a'|

展开的循环的计算结果为:


[68]=0x7a;/'z′;
[67]=0x7a;/'z′;
[66]=0x7a;/'z′;
[65]=0x7a;/'z′;
[64]=0x7a;/'z′;
[63]=0x7a;/'z′;
[62]=0x7a;//'z′;
[61]=0x7a;/'z′;

因此,由变量a、b和ai[]数组的部分表示的内存将被破坏。(纳入了@chux对endianess的观察。此外,我还根据@chux和@Peter A.Schneider的评论调整了ai[]元素的显示顺序。)


|地址|值|描述|
| ---- | ----- | ----------------------------------------- |
|55 | 0x08 |//int i=8|
|56 | 0x00 ||
|57 | 0x00 ||
|58 | 0x00 ||
|59 | 0x01 |//int ai[]={0x7a7a0001,0x7A7A}|
|60 | 0x00 ||
|61 | 0x7a ||
|62 | 0x7a ||
|63 | 0x7a ||
|64 | 0x7a ||
|65 | 0x7a ||
|66 | 0x7a ||
|67 | 0x7a |//字符b='z'|
|68 | 0x7a |//字符a='z'|

*(&a-i)
是一个可怕的想法,考虑到代码。这不是乘法,这是去引用指针。假设未定义行为的方法可以以某种方式量化。我会完全画一些鼻子和一些恶魔。使用
i
而不是0,
*(&a-i)
是未定义的行为(UB)。嗯,在任何情况下,这都是未定义的行为。当然,本术语所涵盖的行为包括覆盖恰好位于计算地址的值。但是编译器可以自由地忽略该表达式之后的所有代码,等等,例如当违反了严格的别名时(程序员的意图更加明确).@PeterA.Schneider非常正确,我只是在回答毫无意义的考试问题。当然
59 | 0x02 |//int-ai[]={1,2}有问题。我希望
59 | 0x01…
Comment
//int-ai[]={0x02007a7a,0x7a7a}看起来错误,endian不一致。建议“假设整数是LSB”->“假设整数是little endian”@chux是正确的:虽然问题定义堆栈分配朝着更小的地址进行,导致定义的实体以声明的相反顺序驻留在内存中,数组是复合但单个的对象,其成员按标准指定的顺序排列。具体来说,数组元素的地址始终可以通过将索引添加到第一个元素的地址来计算,该地址在数字上等于数组的地址。因此,
ai
的第一个元素(不是第二个)的某个地方有0x02字节。顺便说一句,答案很清楚,我想你在第一个表中给出的数组//int ai[]={1,2};`相反:对于
ai[0]
,它必须是地址59处的0x01,对于
ai[1]
,它必须是地址63处的0x02。因此,在第二个表中,注释是错误的:它必须是
//int ai[]
for (i = 0; i < 8; i++)
    *(&a – i) = 'z';