【问题标题】:Is this code doing what I want it to do?这段代码在做我想做的事吗?
【发布时间】:2011-10-18 21:30:57
【问题描述】:

我想创建一个整数指针 p,为一个 10 元素的数组分配内存,然后用值 5 填充每个元素。这是我的代码:

//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );

//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
    *p = 5;
             printf("Current value of array: %p\n", *p);
    *p += sizeof(int);
    i += sizeof(int);
}

我在这段代码周围添加了一些打印语句,但我不确定它是否真的用值 5 填充每个元素。

那么,我的代码工作正常吗?感谢您的宝贵时间。

【问题讨论】:

  • 你试过运行它吗?因为它……不。它甚至不会按照你说的去做。
  • 是的,它会运行,并打印出 '5' 10 次。
  • 我建议你买一本很好的 C 初学者书。stackoverflow.com/questions/562303/…
  • 很好的 sizeof(array) 问题。
  • 我正在阅读的书不在该列表中,而且由于我的书所说的与答案所说的相矛盾,我会说我的书被省略是有充分理由的来自good C 初学者书籍列表。

标签: c pointers malloc


【解决方案1】:

第一:

*p += sizeof(int);

这将获取p 所指向的内容,并将整数的大小添加到其中。这没有多大意义。你可能想要的只是:

p++;

这使得p 指向下一个对象。

但问题是p 包含指向第一个对象的指针的唯一副本。因此,如果您更改它的值,您将无法再访问内存,因为您将没有指向它的指针。 (因此,您应该将从malloc 返回的原始值的副本保存在某处。如果没有别的,您最终需要将它传递给free。)

while (i < sizeof(array)){

这没有意义。您不想循环的次数等于数组占用的 字节数

最后,你不需要数组来做任何事情。只需将其删除并使用:

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

对于 C,不要转换 malloc 的返回值。它不是必需的,并且可以掩盖其他问题,例如未能包含正确的标题。对于while 循环,只需跟踪单独变量中的元素数量即可。

【讨论】:

  • 恕我直言,不强制转换的更好理由是,如果 p 的类型发生变化,p = malloc(10 * sizeof *p); 将无需更改即可工作,而 p = (int *)malloc(10 * sizeof(int)); 将要求您更改行。如果您使用大量reallocs,这尤其令人讨厌。
【解决方案2】:

这是一种更惯用的做事方式:

/* Just allocate the array into your pointer */
int arraySize = 10;
int *p = malloc(sizeof(int) * arraySize);

printf("Size of array: %d\n", arraySize);

/* Use a for loop to iterate over the array */
int i;
for (i = 0; i < arraySize; ++i)
{
    p[i] = 5;
    printf("Value of index %d in the array: %d\n", i, p[i]);
}

请注意,您需要单独跟踪数组大小,无论是在变量(如我所做的)或宏(#define 语句)中,还是仅使用整数文字。但是,使用整数字面量容易出错,因为如果以后需要更改数组大小,则需要更改更多代码行。

【讨论】:

  • 这是我决定为作业实施的解决方案。非常感谢大家的所有精彩回答!
【解决方案3】:

数组的sizeof返回数组占用的字节数,以字节为单位。

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

如果你调用 malloc,你必须#include &lt;stdlib.h&gt;。此外,强制转换是不必要的,并且可能会引入危险的错误,尤其是与缺少的 malloc 定义配对时。


如果将指针加一,则到达指针类型的下一个元素。因此,你应该把底部写成:

for (int i = 0;i < sizeof(array) / sizeof(array[0]);i++){
    *p = 5;
    p++;
}

【讨论】:

    【解决方案4】:
    *p += sizeof(int);
    

    应该是

    p += 1;
    

    因为指针的类型是int *

    数组大小也应该这样计算:

    sizeof (array) / sizeof (array[0]);
    

    事实上,您的代码不需要该数组。

    【讨论】:

      【解决方案5】:

      不,不是。但是,以下代码将。您应该阅读指针算法。 p + 1 是下一个整数(这是指针具有类型的原因之一)。还要记住,如果你改变 p 的值,它将不再指向你记忆的开始。

      #include <stdio.h>
      #include <stdlib.h>
      #include <assert.h>
      #define LEN 10
      
      int main(void)
      {
          /* Allocate memory for a 10-element integer array. */
          int array[LEN];
          int i;
          int *p;
          int *tmp;
      
          p = malloc(sizeof(array));
          assert(p != NULL);
      
          /* Fill each element with the value of 5. */
          printf("Size of array: %d bytes\n", (int)sizeof(array));
      
          for(i = 0, tmp = p; i < LEN; tmp++, i++) *tmp = 5;
          for(i = 0, tmp = p; i < LEN; i++) printf("%d\n", tmp[i]);
      
          free(p);
      
          return EXIT_SUCCESS;
      }
      

      【讨论】:

        【解决方案6】:
        //Allocate memory for a 10-element integer array.
        int array[10];
        int *p = (int *)malloc( sizeof(array) );
        

        此时你已经分配了两倍的内存——在堆栈上分配了十个整数的空间,而在堆上分配了十个整数的空间。在需要为十个整数分配空间并且堆栈分配不是正确的事情的“真实”程序中,分配将按如下方式完成:

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

        请注意,不需要从malloc(3) 转换返回值。我希望您忘记包含 &lt;stdlib&gt; 标头,它可以正确地对函数进行原型化,并为您提供正确的输出。 (如果头文件中没有原型,C 编译器会假定该函数将返回 int,并且强制转换使其将其视为指针。二十年来都不需要强制转换。)

        此外,请注意学习习惯sizeof(array)。这将在数​​组与 sizeof() 关键字分配在同一块中的代码中起作用,但在这样使用时会失败

        int foo(char bar[]) {
            int length = sizeof(bar); /* BUG */
        }
        

        它会看起来正确,但sizeof() 实际上会看到char * 而不是完整的数组。 C 的新 Variable Length Array 支持非常好,但不要与知道其大小的数组在许多其他语言中可用。

        //Fill each element with the value of 5.
        int i = 0;
        printf("Size of array: %d\n", sizeof(array));
        while (i < sizeof(array)){
            *p = 5;
            *p += sizeof(int);
        

        啊哈!与我一样遇到 C 指针问题的其他人!我想您过去主要编写汇编代码并且不得不自己增加指针? :) 编译器知道p 指向的对象的类型(int *p),因此如果您只写p++,它将正确地将指针移动正确的字节数。如果您将代码交换为使用longlong longfloatdoublelong doublestruct very_long_integers,编译器将始终使用p++ 做正确的事情。

            i += sizeof(int);
        }
        

        虽然这没有错误,但稍微重写最后一个循环肯定会更习惯:

        for (i=0; i<array_length; i++)
            p[i] = 5;
        

        当然,您必须将数组长度存储到一个变量中或#define 中,但这样做比依赖于有时很挑剔的数组长度计算更容易。

        更新

        在阅读了其他(优秀的)答案后,我意识到我忘了提及,因为 p 是您对数组的唯一引用,最好不要更新 p 而不在某处存储其值的副本.我的小“惯用”重写回避了这个问题,但没有指出 为什么 使用订阅比增加指针更惯用 - 这就是首选订阅的原因之一。我也更喜欢订阅,因为它通常更容易推理数组基数不变的代码。 (视情况而定。)

        【讨论】:

          【解决方案7】:
          //allocate an array of 10 elements on the stack
          int array[10];
          //allocate an array of 10 elements on the heap.  p points at them
          int *p = (int *)malloc( sizeof(array) );
          // i equals 0
          int i = 0;
          //while i is less than 40 
          while (i < sizeof(array)){
              //the first element of the dynamic array is five
              *p = 5;
              // the first element of the dynamic array is nine!
              *p += sizeof(int);
              // incrememnt i by 4
              i += sizeof(int);
          }
          

          这会将数组的第一个元素设置为九、十次。看起来您想要的更像是:

          //when you get something from malloc, 
          // make sure it's type is "____ * const" so 
          // you don't accidentally lose it
          int * const p = (int *)malloc( 10*sizeof(int) );
          for (int i=0; i<10; ++i) 
              p[i] = 5;
          

          ___ * const 阻止您更改 p,以便它始终指向已分配的数据。这意味着free(p); 将始终有效。如果更改p,则无法释放内存,并且会出现内存泄漏。

          【讨论】:

          • 您能详细说明为什么将 malloc 指针设为 const 吗?
          猜你喜欢
          • 1970-01-01
          • 2020-05-24
          • 2011-02-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-06
          • 2020-04-21
          • 2022-10-15
          相关资源
          最近更新 更多