C语言 这段代码是否在做我希望它做的事情



我想创建一个整数指针 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: %dn", sizeof(array));
while (i < sizeof(array)){
    *p = 5;
             printf("Current value of array: %pn", *p);
    *p += sizeof(int);
    i += sizeof(int);
}

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

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

首先:

*p += sizeof(int);

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

p++;

这使p指向下一个对象。

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

while (i < sizeof(array)){

这说不通。您不希望循环的次数等于数组占用的字节数。

最后,您不需要数组进行任何操作。只需将其删除并使用:

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

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

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

/* Just allocate the array into your pointer */
int arraySize = 10;
int *p = malloc(sizeof(int) * arraySize);
printf("Size of array: %dn", 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: %dn", i, p[i]);
}

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

数组的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++;
}
*p += sizeof(int);

应该是

p += 1;

由于指针的类型为 int *

此外,数组大小应按如下方式计算:

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

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

不,不是。但是,以下代码将。您应该阅读指针算术。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 bytesn", (int)sizeof(array));
    for(i = 0, tmp = p; i < LEN; tmp++, i++) *tmp = 5;
    for(i = 0, tmp = p; i < LEN; i++) printf("%dn", tmp[i]);
    free(p);
    return EXIT_SUCCESS;
}
//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) 强制转换返回值。我希望您忘记包含 <stdlib> 标头,这将正确制作函数原型,并为您提供正确的输出。(如果没有原型在标头中,C 编译器假定该函数将返回一个 int,并且强制转换使其将其视为指针。二十年来不需要演员阵容。

此外,要警惕学习习惯sizeof(array)。这将适用于数组与 sizeof() 关键字分配在同一块中的代码,但当像这样使用时它会失败

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

看起来是正确的,但实际上sizeof()会看到一个char *而不是完整的数组。C 的新可变长度数组支持非常强烈,但不要与许多其他语言中可用的知道其大小的数组混淆。

//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %dn", 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而不在某处存储其值的副本。我的小"惯用语"重写回避了这个问题,但没有指出为什么使用订阅比增加指针更惯用——这就是首选订阅的原因之一。我也更喜欢订阅,因为在数组基数不变的情况下,对代码进行推理通常要容易得多。(视情况而定。

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

相关内容

  • 没有找到相关文章

最新更新