簡體   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