繁体   English   中英

C程序打印垃圾值

[英]C program printing garbage values

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

这是代码片段的一部分。

  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

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

打开警告。 (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]);
  }
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)

这是实际问题。 它没有访问下一个整数,而是访问了一个空指针可寻址的下一个地址,该指针通常是一个字节。 访问下一个整数将等效于此:

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

或更容易阅读:

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

请记住,将指针增加一个偏移量不会添加到原始内存地址,但这取决于指针类型。

这里的重点是指针的算法。 当我们将值加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/

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

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

void *p = arr;

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

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

编辑:您实际上不更改arr的值。 我的错。

首先,将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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM