为什么我的循环在C中无法正常工作?

huangapple go评论59阅读模式
英文:

Why isn't my loop working correctly in c?

问题

这是我的代码。首先应该扫描2个数字m和n。然后扫描一个包含n个数字的数组x[n]。第二行中扫描的数字数量应该是n。但它不正常工作。

#include <stdio.h>

int main()
{
    int m = 0;
    int n = 0;
    int x[n];
    scanf("%d", &m);
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &x[i]);
    }
}

它只扫描了1个数字然后退出了循环。应该从0到n-1扫描(i)的值。

英文:

This is my code. It is supposed to first of all scan 2 number m and n. Then scan an array of numbers that is x[n]. Number of scanned numbers in second line should be n. But it doesn't work correctly.

#include &lt;stdio.h&gt;

int main()
{
    int m = 0;
    int n = 0;
    int x[n];
    scanf(&quot;%d&quot;, &amp;m);
    scanf(&quot;%d&quot;, &amp;n);
    for(int i = 0 ;i &lt; n;i++)
    {
        scanf(&quot;%d&quot;, &amp;x[i]);
    }
}

It just scans 1 number and breaks out of the loop. We should have (i)s from 0 until n-1;

答案1

得分: 3

This attempts to declare a Variable Length Array of size zero, which already is undefined behaviour. And even if that (having a VLA with room for zero elements) were somehow possible, scanf("%d", &x[i]); would also be undefined behavior.

英文:
int n = 0;
int x[n];

This attempts to declare a Variable Length Array of size zero, which already is undefined behaviour.

And even if that (having a VLA with room for zero elements) were somehow possible,

    scanf(&quot;%d&quot;, &amp;x[i]);

...would also be undefined behavior.

答案2

得分: 1

以下是代码段的翻译部分:

"Let me try to explain the behavior of the code considering x86_64 architecture and gcc7.5x compiler."

"This answer and this answer to the questions provides the direction of stack growth on different architectures for x86 it is downward, meaning the stack will grow from high memory to low memory address (0xFF --> 0x00)"

"If we slightly modify your code to print the addresses and values of the variable during runtime as shown:"

#include <stdio.h>;

int main()
{
    int m = 0;
    int n = 0;
    int x[n];

    printf("Size of int: %d\n", sizeof(int));
    printf("Address of\nm: %p\nn: %p\nx: %p\n", &m, &n, &x);
    printf("Enter a value of m: ");
    scanf("%d", &m);
    printf("Enter a value of n: ");
    scanf("%d", &n);

    for(int i = 0; i < n; i++)
    {
        scanf("%d", &x[i]);
        printf("Addr: %p\n", &x[i]);
    }
    for(int j = 0; j < n; j++)
    {
        printf("x[%d]: %d\n", x[j]);
    }
    printf("m: %d n: %d\n", m, n);
}

"After compiling and running the above code on x86, we can notice that the addresses to the local variables get assigned in decreasing order as shown below for one of the code execution session:"

Address of
m: 0x7ffdfb2b1704
n: 0x7ffdfb2b1700
x: 0x7ffdfb2b16f0

"If you notice the difference in the address of n and x, they are 16-Bytes apart, ideally they should have been 4-bytes apart on the stack."

"But as int x[n] is declared to be an array of 0 integers, ideally it should occupy 4-bytes of memory, even though the underlying compiler and architecture mechanism is treating it as an array of 4 integers, which gets translated to 4 integers * sizeof(int) = 16-bytes."

"Looking at further execution output of the code, we can see that the value of n at address 0x7ffdfb2b1700 gets overwritten as the code executes further."

"Note that the code will work properly for values of n < 5, because for the value of n = 4, the loop will terminate at n = 3 in which case the value of n will not get overwritten because of loop iteration as (n * sizeof(int)) ==> 3 * 4 = 12-bytes:"

Enter a value of m: 1
Enter a value of n: 10
1
Addr: 0x7ffdfb2b16f0
2
Addr: 0x7ffdfb2b16f4
3
Addr: 0x7ffdfb2b16f8
4
Addr: 0x7ffdfb2b16fc
5
Addr: 0x7ffdfb2b1700  <--- address of variable `n` getting overwritten with a new value
x[1]: 0
x[2]: 1
x[3]: 2
x[4]: 3
x[5]: 4
m: 1 n: 5

"And this is the reason why @DevSolar answered that this will result in an undefined behavior."

"I hope I was able to provide some clarification."

英文:

Let me try to explain the behavior of the code considering x86_64 architecture and gcc7.5x compiler.

This answer and this answer to the questions provides the direction of stack growth on different architectures for x86 it is downward, meaning the stack will grow from high memory to low memory address (0xFF --> 0x00)

If we slightly modify your code to print the addresses and values of the variable during runtime as shown:

#include &lt;stdio.h&gt;

int main()
{
    int m = 0;
    int n = 0;
    int x[n];
    
    printf(&quot;Size of int: %d\n&quot;, sizeof(int));
    printf(&quot;Address of\nm: %p\nn: %p\nx: %p\n&quot;, &amp;m, &amp;n, &amp;x);
    printf(&quot;Enter a value of m: &quot;);
    scanf(&quot;%d&quot;, &amp;m);
    printf(&quot;Enter a value of n: &quot;);
    scanf(&quot;%d&quot;, &amp;n);
    
    for(int i = 0; i &lt; n; i++)
    {
        scanf(&quot;%d&quot;, &amp;x[i]);
        printf(&quot;Addr: %p\n&quot;, &amp;x[i]);
    }
    for(int j = 0; j &lt; n; j++)
    {
        printf(&quot;x[%d]: %d\n&quot;, x[j]);
    }
    printf(&quot;m: %d n: %d\n&quot;, m, n);
}

After compiling and running the above code on x86, we can notice that the addresses to the local variables get assigned in decreasing order as shown below for one of the code execution session:

Address of
m: 0x7ffdfb2b1704
n: 0x7ffdfb2b1700
x: 0x7ffdfb2b16f0

If you notice the difference in the address of n and x, they are 16-Bytes apart, ideally they should have been 4-bytes apart on stack.
But as int x[n] is declared to be an array of 0 integers ideally it should occupy 4-bytes of memory, even though the underlying compiler and architecture mechanism is treating it as an array of 4 integers, which gets translated to
4 integers * sizof(int) = 16-bytes

Looking at further execution output of the code, we can see that the value of n at address 0x7ffdfb2b1700 gets overwritten as the code executes further.

> Note that the code will work properly for values of n &lt; 5, because for the value of n = 4 the loop will terminate at n = 3 in which case the value of n will not get overwritten because of loop iteration as (n * sizeof(int)) ==&gt; 3 * 4 = 12-bytes:

Enter a value of m: 1
Enter a value of n: 10
1
Addr: 0x7ffdfb2b16f0
2
Addr: 0x7ffdfb2b16f4
3
Addr: 0x7ffdfb2b16f8
4
Addr: 0x7ffdfb2b16fc
5
Addr: 0x7ffdfb2b1700  &lt;--- address of variable `n` getting overwritten with new value
x[1]: 0
x[2]: 1
x[3]: 2
x[4]: 3
x[5]: 4
m: 1 n: 5

And this is the reason why @DevSolar answered that this will result in an undefined behavior.

I hope I was able to provide some clarification.

huangapple
  • 本文由 发表于 2023年4月11日 14:59:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75983181.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定