Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.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
Arrays 为什么我们不';在malloc数组的情况下,是否不需要取消引用指针值?_Arrays_C_Pointers_Memory Management_Malloc - Fatal编程技术网

Arrays 为什么我们不';在malloc数组的情况下,是否不需要取消引用指针值?

Arrays 为什么我们不';在malloc数组的情况下,是否不需要取消引用指针值?,arrays,c,pointers,memory-management,malloc,Arrays,C,Pointers,Memory Management,Malloc,我在试图理解C编译器如何以一种阴暗的方式解释字符数组、字符串、整数和数组时遇到了困难。谢谢你帮我。甚至许多reddit用户也指出,C中的指针在解释命令时有点模糊。 因此,我试图通过一个例子来理解malloc。但在此之前,这是我的理解。 假设*p是一个变量。然后p保持它指向的地址。 而*p引用地址所持有的值。 在动态分配的情况下, 当我这样做的时候 int *p = (int *)malloc(sizeof(int)*5); //say we want 5 locations // 当用户给出所

我在试图理解C编译器如何以一种阴暗的方式解释字符数组、字符串、整数和数组时遇到了困难。谢谢你帮我。甚至许多reddit用户也指出,C中的指针在解释命令时有点模糊。 因此,我试图通过一个例子来理解
malloc
。但在此之前,这是我的理解。 假设
*p
是一个变量。然后p保持它指向的地址。 而
*p
引用地址所持有的值。 在动态分配的情况下, 当我这样做的时候

int *p = (int *)malloc(sizeof(int)*5); //say we want 5 locations //
当用户给出所有5个值时,手动循环,我输入如下值

scanf("%d", p+i) // as p already holds address, I get that we don't have to provide the & . And i being the iterator.. //
然后用另一个循环打印,这是发生的事情,我不知道为什么

说出用户输入的55,66,77,88,99

当我用这个代码打印时

printf("%d", *p+i); // De-referencing the values in location p by using asterics, + the value of iteration,i //
我得到的值与55,56,57,58,59的值一样疯狂

所以,在互联网的一点帮助下,我尝试了这样的printf代码,效果非常好,但是 我甚至不必取消引用。这到底是为什么让人如此困惑

printf("%d", p[i]); // No asterics used. How does the compiler know I want the value and not the address? as p only should hold the addresses, and *p should give us the values in those addresses //
同样,如果我做了
printf(“%d”,*p++)
然后它也能工作。
为什么我不明白C是如何工作的

同样的,如果我尝试做同样的事情,但是这次是用
scanf(“%d”,p[I]),然后是语法错误。
我是说为什么

谢谢

假设*p是一个变量

否。变量为
p
,其类型为
int*


  • *p
    :在地址
    p
  • *p+i
    解析为
    (*p)+1
    :地址
    p
    处的值,然后将值
    1
    添加到该值中
  • p[i]
    相当于
    *(p+i)
    :地址
    p+i
    处的值,其中
    p+i
    是从
    p
    开始的整数数组的
    i
    第个元素的地址。A.k.A.整数向量中从
    p开始的
    i
    th元素
  • *p++
    解析为
    *(p++)
    :增加指针
    p
    (即使
    p
    指向下一个元素)并从
    p
    的旧值中获取值
假设*p是一个变量

否。变量为
p
,其类型为
int*


  • *p
    :在地址
    p
  • *p+i
    解析为
    (*p)+1
    :地址
    p
    处的值,然后将值
    1
    添加到该值中
  • p[i]
    相当于
    *(p+i)
    :地址
    p+i
    处的值,其中
    p+i
    是从
    p
    开始的整数数组的
    i
    第个元素的地址。A.k.A.整数向量中从
    p开始的
    i
    th元素
  • *p++
    解析为
    *(p++)
    :增加指针
    p
    (即使
    p
    指向下一个元素)并从
    p
    的旧值中获取值

    • 我认为一个小的可运行代码将帮助您更好地理解,而不是我解释

      #include <stdlib.h>
      #include <stdio.h>
      
      int main() {
          int *p = (int *)malloc(sizeof(int)*5);
          int *q = (int *)malloc(sizeof(int)*5);
          int i = 0;
          int test_val = 100;
      
          for(i = 0; i < 5; i++) {
              *(p + i) = test_val;
              q[i] = test_val;
              test_val = test_val + 10;
          }
      
          for(i = 0; i < 5; i++)
              printf("p[%d] = %d\n", i, p[i]);
      
          printf("p[i] gives the value in array p at index i \n\n");
      
          for(i = 0; i < 5; i++)
              printf("q[%d] = %d\n", i, q[i]);
          
          printf("Note that the values in p and q are equal which means that *(x + 1) and x[i] are 2 ways to access the same values \n\n");
      
          for(i = 0; i < 5; i++)
              printf("*p + %d = %d\n", i, *p + i);
      
          printf("*p + i gets value pointed by p and adds i to it in each iteration \n\n");
      
          for(i = 0; i < 5; i++)
              printf("*(p + %d) = %d\n", i, *(p + i));
      
          printf("*(p + i) gets value pointed by p + i \n\n");
      
          int *j = (int *)malloc(sizeof(int)*5);
          int *k = (int *)malloc(sizeof(int)*5);
          int *l = (int *)malloc(sizeof(int)*5);
      
          for(i = 0; i < 5; i++) {
               j[i] = test_val;
               k[i] = test_val;
               l[i] = test_val;
          }
          printf("(*j)++ = %d\n\n", (*j)++);
          printf("*(k++) = %d\n\n", *(k++));
          printf("*l++ = %d\n\n", *l++);
          
          for(i = 0; i < 5; i++) {
               j[i] = test_val;
               k[i] = test_val;
               l[i] = test_val;
          }
          printf("test_val = %d\n\n", test_val);
          printf("++(*j) = %d\n\n", ++(*j));
          printf("*(++k) = %d\n\n", *(++k));
          printf("*++l = %d\n\n", *++l);
          return 0;
      }
      

      对于scanf问题,scanf始终需要一个指针作为参数。p[I]是(p+I)处的值,因此不正确。理想情况下,您应该使用scanf(“%d”&(p[i])

      我认为一个小的可运行代码将帮助您更好地理解而不是解释

      #include <stdlib.h>
      #include <stdio.h>
      
      int main() {
          int *p = (int *)malloc(sizeof(int)*5);
          int *q = (int *)malloc(sizeof(int)*5);
          int i = 0;
          int test_val = 100;
      
          for(i = 0; i < 5; i++) {
              *(p + i) = test_val;
              q[i] = test_val;
              test_val = test_val + 10;
          }
      
          for(i = 0; i < 5; i++)
              printf("p[%d] = %d\n", i, p[i]);
      
          printf("p[i] gives the value in array p at index i \n\n");
      
          for(i = 0; i < 5; i++)
              printf("q[%d] = %d\n", i, q[i]);
          
          printf("Note that the values in p and q are equal which means that *(x + 1) and x[i] are 2 ways to access the same values \n\n");
      
          for(i = 0; i < 5; i++)
              printf("*p + %d = %d\n", i, *p + i);
      
          printf("*p + i gets value pointed by p and adds i to it in each iteration \n\n");
      
          for(i = 0; i < 5; i++)
              printf("*(p + %d) = %d\n", i, *(p + i));
      
          printf("*(p + i) gets value pointed by p + i \n\n");
      
          int *j = (int *)malloc(sizeof(int)*5);
          int *k = (int *)malloc(sizeof(int)*5);
          int *l = (int *)malloc(sizeof(int)*5);
      
          for(i = 0; i < 5; i++) {
               j[i] = test_val;
               k[i] = test_val;
               l[i] = test_val;
          }
          printf("(*j)++ = %d\n\n", (*j)++);
          printf("*(k++) = %d\n\n", *(k++));
          printf("*l++ = %d\n\n", *l++);
          
          for(i = 0; i < 5; i++) {
               j[i] = test_val;
               k[i] = test_val;
               l[i] = test_val;
          }
          printf("test_val = %d\n\n", test_val);
          printf("++(*j) = %d\n\n", ++(*j));
          printf("*(++k) = %d\n\n", *(++k));
          printf("*++l = %d\n\n", *++l);
          return 0;
      }
      
      对于scanf问题,scanf始终需要一个指针作为参数。p[I]是(p+I)处的值,因此不正确。理想情况下,您应该使用scanf(“%d”&(p[i]))

      “当我使用此代码打印时,
      printf(“%d”,*p+I);
      …我得到的值与
      55
      56
      57
      58
      59
      一样疯狂。”

      当您使用
      *p+i
      时,
      p
      首先被解除引用(它获得第一个数组元素的值,即
      55
      ),然后
      i
      被添加到值
      55
      *p+i
      等于
      (*p)+i

      这就是为什么您会得到以下输出:
      55
      56
      57
      58
      59
      ,而不是
      55
      66
      77
      88
      99

      您只需将
      i
      添加到每个迭代中的第一个元素的值中,就永远不会访问以下4个数组元素

      “我试过这样的
      printf
      代码,效果很好,但我甚至不需要取消引用….
      printf(“%d”,p[I]);

      使用
      p[i]
      时,将在数组的
      i
      第个元素处获得值,因为它在取消引用之前偏移指针本身。它等于
      *(p+i)

      “而且,如果我做了
      printf(“%d”,*p++);
      ,那么它也可以工作。”

      当您使用
      *p++
      时,
      p
      将被实际解引用,并获得
      *p
      处的值,但此后
      p
      将递增。表示在下一次迭代
      p
      时指向下一个数组元素

      循环完成后,
      p
      指向数组上方一点


      “如果我尝试做同样的事情,但这次是使用
      scanf(“%d”,p[I]);
      ,那么语法错误。我是说为什么?”

      对于
      scanf()
      来说,情况有点不同

      当您使用
      scanf(“%d”,p[i])
      p[i]
      等于
      *(p+i)
      ,因为它也在
      printf()
      调用中,但当您尝试取消引用并获得
      int
      对象而不是指向
      int
      的指针时,这是
      scanf()
      处的
      %d
      所需的,这是一个语法错误

      scanf()
      中,
      %d
      需要类型为
      int*
      的参数,而不是
      int


      关于你的主要问题:

      “为什么我们不需要取消引用
      int *p = ....
      
      p ______
             |
            \|/
           --------------------------
           | 55 | 66 | 77 | 88 | 99 |
           --------------------------
      
      printf("%d", *p+i); // De-referencing the values in location p by using asterics, + the value of iteration,i //
      
      (*p) + 0  ->  55 + 0  ->  55
      
      (*p) + 1  ->  55 + 1  ->  56
      
      (*p) + 1  ->  55 + 4  ->  59
      
      printf("%d", p[i]); // No asterics used. How does the compiler know I want the value and not the address? as p only should hold the addresses, and *p should give us the values in those addresses //
      
      p[i] -> *((p) + (i)) -> *(p + i)
      
      *(p++) -> p will be incremented but the value of p in the expression will be its value prior to the increment operation which is location of element at `0`th index
             -> *(0th location address) -> 55
      
      *(p++) -> p will be incremented but the value of p in the expression will be its value prior to the increment operation which is location of element at `1`st index
             -> *(1st location address) -> 66
      
      *(p++) -> p will be incremented but the value of p in the expression will be its value prior to the increment operation which is location of element at `4`th index
             -> *(4th location address) -> 99
      
      p[i] -> *((p) + (i)) -> *(p + i)
      
      scanf("%d", &p[i]);
      
      &p[i] -> &(p[i]) -> &(*((p) + (i)) -> ((p) + (i)) -> p + i
                |                |
        Precedence of operator   |
        [] is higher than        |
        & operator               |
                                 |
            The operator & is used to get the address and the operator * is used for dereferencing.
            These operators cancel the effect of each other when used one after another. 
      
      scanf("%d", &p[i]);
      
      scanf("%d", p + i);