这段代码是做我想做的吗?

时间:2011-10-18 21:30:58

标签: c pointers malloc

我想创建一个整数指针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填充每个元素。

那么,我的代码是否正常工作?谢谢你的时间。

7 个答案:

答案 0 :(得分:3)

首先:

*p += sizeof(int);

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

p++;

这使p指向下一个对象。

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

while (i < sizeof(array)){

这没有意义。您不希望循环次数等于数组占用的 bytes 的数量。

最后,您不需要任何数组。只需删除它并使用:

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

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

答案 1 :(得分:2)

数组的

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

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

如果您致电malloc,则必须#include <stdlib.h>。此外,演员阵容是不必要的,并且可能会引入危险的错误,尤其是在与缺少的malloc定义配对时。


如果将指针递增1,则会到达指针类型的下一个元素。因此,您应该将底部写为:

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

答案 2 :(得分: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 :(得分:1)

*p += sizeof(int);

应该是

p += 1;

因为指针的类型为int *

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

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

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

答案 4 :(得分:1)

//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);
}

这将数组的第一个元素设置为9次,10次。看起来你想要更像的东西:

//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,则无法释放内存,并且内存泄漏。

答案 5 :(得分:1)

不,不是。但是,以下代码。你应该阅读指针算术。 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 :(得分:1)

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

此时,您已经为堆栈上分配的数组中的10个整数分配了两倍的内存空间,并为堆上分配的10个整数分配了空间。在一个需要为十个整数分配空间的“真正”程序中,堆栈分配不是正确的事情,分配将如下所示:

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

请注意,无需从malloc(3)转换返回值。我希望您忘记包含<stdlib>标题,这将正确地对函数进行原型化,并为您提供正确的输出。 (如果没有标题中的原型,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而不存储副本它的价值在某处。我的小'惯用'重写方面 - 解决问题,但没有指出为什么使用订阅比递增指针更惯用 - 这也是订阅首选的一个原因。我也更喜欢订阅,因为通常更容易推理数组基础不会改变的代码。 (这取决于。)

相关问题