意外的c指针结果

时间:2017-08-18 13:33:41

标签: c pointers

您好我最近开始学习c指针并且无法理解为什么我得到的指针值不同于预期。 这是函数

int test(void){
    int i,j; 
    int **p = (int **)malloc(2 * sizeof(int *)); 
    p[0] = (int *)malloc(2 * sizeof(int)); 
    printf("p[0] = %d\n",p[0]);
    p[1] = p[0]; 
    printf("p[1] = %d\n",p[1]);
    for(i = 0; i < 2; i++){ 
            for(j = 0; j < 2; j++) {
                    p[i][j] = i + j;
                    printf("p[%d][%d] = %d\n",i,j,p[i][j]);
            }
    } 
    printf("result p[0][0] = %d\n",p[0][0]); 
 return 0;
}

我期待从for循环中打印出p [0] [0] = 0,但是它等于1并且值似乎来自p [1] [0],我在这里缺少什么?

printf输出:

p[0] = 1224416
p[1] = 1224416
p[0][0] = 0
p[0][1] = 1
p[1][0] = 1
p[1][1] = 2
result p[0][0] = 1

3 个答案:

答案 0 :(得分:5)

首先 - 您将int*传递给printf(),期望int%d),使用(%p)代替打印地址。< / p>

第二 -

p[1] = p[0];

p[0]p[1]指针都指向同一地址。这意味着如果您修改一行(p[0]),则第二行(p[1])也会被修改。

这是你问题的根源

  

我期待从for循环中打印出p [0] [0] = 0,但它是   等于1,值似乎来自p 1 [0],我是什么   在这里失踪?

+---+---+
| 0 | 0 |
+---+---+
 ^ ^
 | |
 | -------------------- p[0]
 ---------------------- p[1]

现在您修改p[1],它看起来像这样。换句话说,0的值1p[0]会被覆盖

+---+---+
| 1 | 2 |
+---+---+
 ^ ^
 | |
 | -------------------- p[0]
 ---------------------- p[1]

而不是p[1] = p[0],也可以在堆上分配p[1](不同的)内存。

p[0] = malloc(2 * sizeof(int)); 
p[1] = malloc(2 * sizeof(int));

现在p[0][0]正确0

第三 - 重新制作malloc是多余的,可能会导致问题。 Do i cast malloc return value?

C++中,您可以( )使用内置运算符newdelete

也不要忘记在堆上free()分配的内存。

答案 1 :(得分:0)

逐行分解:

int **p = (int **)malloc(2 * sizeof(int *)); 

执行此行后,您将拥有以下内容:

   +---+                +---+
p: |   | --------> [0]: |   | ---?
   +---+                +---+
                   [1]: |   | ---?
                        +---+

?表示p[0]p[1]包含不确定指针值(malloc未初始化其分配的内存);这些指针值很可能无效(即,不对应于程序中对象的地址)。

p[0] = (int *)malloc(2 * sizeof(int));

执行此行后,您将拥有以下内容:

   +---+                +---+              +---+
p: |   | --------> [0]: |   | ------> [0]: | ? |
   +---+                +---+              +---+
                   [1]: |   | ---?    [1]: | ? |
                        +---+              +---+

同样,?表示不确定的值。

p[1] = p[0]; 

执行此行后,您将拥有以下内容:

   +---+                +---+              +---+
p: |   | --------> [0]: |   | ---+--> [0]: | ? |
   +---+                +---+    |         +---+
                   [1]: |   | ---+    [1]: | ? |
                        +---+              +---+

现在,p[0]p[1]指向同一块内存。因此,p[0][0]p[1][0]会解析为同一个对象。如果我们展开你的循环,我们会看到以下分配顺序:

p[0][0] = 0 + 0;

   +---+                +---+              +---+
p: |   | --------> [0]: |   | ---+--> [0]: | 0 |
   +---+                +---+    |         +---+
                   [1]: |   | ---+    [1]: | ? |
                        +---+              +---+

p[0][1] = 0 + 1;

   +---+                +---+              +---+
p: |   | --------> [0]: |   | ---+--> [0]: | 0 |
   +---+                +---+    |         +---+
                   [1]: |   | ---+    [1]: | 1 |
                        +---+              +---+

p[1][0] = 1 + 0;

   +---+                +---+              +---+
p: |   | --------> [0]: |   | ---+--> [0]: | 1 |
   +---+                +---+    |         +---+
                   [1]: |   | ---+    [1]: | 1 |
                        +---+              +---+

p[1][1] = 1 + 1;

   +---+                +---+              +---+
p: |   | --------> [0]: |   | ---+--> [0]: | 1 |
   +---+                +---+    |         +---+
                   [1]: |   | ---+    [1]: | 2 |
                        +---+              +---+

这就是你看到你所看到的输出的原因。 p[0]p[1]在您的输出中显示相同值的事实应该是一个很大的暗示。

如果p[1]意在指向与p[0]不同的数组,那么您需要为p[1]分配另一个内存块来指向到:

p[1] = malloc( 2 * sizeof *p[1] );

作为一种惯例,你需要明确free你分配的所有内容,即使你的程序即将退出 - 这只是一个很好的习惯:

free( p[0] ); // free each p[i] *before* freeing p
free( p[1] ); // assuming you added the malloc for p[1]
free( p );

如果这是C代码,则丢失对malloc调用的强制转换 - 这是不必要的,它只会增加视觉混乱,如果您忘记包含stdlib.h,在C89下可能会掩盖错误。编写这些调用的更好方法是

int **p = malloc( 2 * sizeof *p );

p[0] = malloc( 2 * sizeof *p[0] );

如果这是C ++代码,请使用newdelete代替mallocfree

答案 2 :(得分:-1)

我回答了我自己的问题,因为它正在进行大量无关的讨论。

因为我有 指向第1行以与第2行共享相同的已分配内存 这里 - &gt; p [1] = p [0]; &#34; for&#34;循环使用第二行中的值覆盖第一行中的值。

示例函数来自cppinstitute.org CLA课程第5章。希望这将为将来像我这样的人提供更多的清晰度。