C程序打印垃圾值

问题描述 投票:1回答:5

我正在尝试创建一个数组并为其赋值。虽然我能够正确分配值,但我无法检索这些值,我不知道为什么。

这是代码段的一部分。

  void *arr = (void *)(malloc(sizeof(void *) * 5));
  int i = 0;
  for(i = 0; i < 5; i++) {
    *(int *)(arr+i) = initial[i];
    printf("Value of array: %d\n", *(int *)(arr+i));
  }
  for(i = 0; i < 5; i++) {
    printf("Pushing: %d\n", *(int *)(arr+i));
    DArray_push(result, (arr+i));
  }

该程序的输出是

Value of array: 4
Value of array: 1
Value of array: 3
Value of array: 2
Value of array: 0
Pushing: 33751300
Pushing: 131841
Pushing: 515
Pushing: 2
Pushing: 0

为什么我的程序能够正确接受值,但是当我稍后尝试检索它时是否打印出垃圾值?

c pointers
5个回答
1
投票
Pushing: 33751300 = 4 + 1 * 256 + 3 * 256 * 256 + 2 * 256 * 256 * 256
Pushing: 131841 = 1 + 3 * 256 + 2 * 256 * 256
Pushing: 515 = 3 + 2 * 256
Pushing: 2
Pushing: 0

那部分已经错了,但大多数32或64位编译器仍然可以工作:sizeof(void *)。只是因为这至少在这些平台上的int的大小。

*(int *)(arr+i)

这是实际问题。这不访问下一个整数,它访问由void指针寻址的下一个地址,该指针通常是单个字节。访问下一个整数将等同于:

*(int *)(arr + i*sizeof(int))

或者更容易阅读:

*( ((int *)arr) + i)

请记住,通过偏移量递增指针不会添加到原始内存地址,但它取决于指针类型。


3
投票

打开警告。 (arr+i)未定义(您无法添加到void指针,只有在添加后才执行转换)。你看到未定义的行为。

您进一步分配指针大小的东西,但将其视为int(更多未定义的行为)。

为什么不写:

  int *arr = malloc(sizeof(int) * 5);
  int i = 0;
  for(i = 0; i < 5; i++) {
    arr[i] = initial[i];
    printf("Value of array: %d\n", arr[i]);
  }
  for(i = 0; i < 5; i++) {
    printf("Pushing: %d\n", arr[i]);
  }

1
投票

这里的要点是指针的算术。当我们将值加1时,对于不同类型的指针,它将不相同。那么让我们看一个例子:

(int  *)p + 1 // it's moving 4 bytes
(void *)p + 1 // it's moving 1 byte in my compiler, void * is a generic type

在您的示例中,我们知道我们正在使用整数,因此我们需要告诉编译器在执行任何操作之前将泛型指针转换为适当的类型。

尝试执行以下代码以了解我将要谈论的内容:

#include <stdio.h>
#include <stdlib.h>

void main() {
    int initial[] = {100, 101, 102, 103, 104};
    void *arr = (void *)(malloc(sizeof(void *) * 5));
    int i = 0;

    for (i = 0; i < 5; i++) {
        printf("%p\t%p\n", arr + i, ((int *)arr) + i);
    }

    for(i = 0; i < 5; i++) {
        *(((int *)arr)+i) = initial[i];
        printf("Value of array: %d\n", *(((int *)arr)+i));
    }

    for(i = 0; i < 5; i++) {
        printf("Pushing: %d\n", *(((int *)arr)+i));
    }
}

我找到了一些资源来帮助:

https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/pointer.html

https://www.viva64.com/en/t/0005/


0
投票

问题是你没有重置你的arr指针。因此,在第二个循环中,您实际上在初始数组后打印值。

您需要创建一个变量来遍历您的数组。

void *p = arr;

然后用它来遍历数组。并在第二个循环之前。

此外,不要强制转换malloc函数调用的返回值(即使将它转换为void指针,它是malloc的实际返回类型)。

编辑:你实际上不会改变arr的值。我的错。


0
投票

首先,将malloc转换为void并使用sizeof void的东西是完全不合情理的。

假设initial[]是另一个数组,修复将是:

#include <stdio.h>
#include <stdlib.h>

int initial[] = {10, 20, 30, 40, 50};

int main()
{
    //allocate memory for 5 integers
    int* arr = malloc(sizeof(int) * 5);

    //loop over and copy from inital to arr
    int i = 0;
    for(i = 0; i < 5; i++) {
        arr[i] = initial[i];
        printf("Value of array: %d\n", arr[i]);
    }

  //pointer to first element of arr
  int* arrPointer = arr;

  for(i = 0; i < 5; i++) {
    printf("Pushing: %d\n", *arrPointer);
    //DArray_push(result, (*arrPointer));
    //increment the arrPointer
    arrPointer++;
  }

  //reset pointer if needed later...
  arrPointer = arr;

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.