[英]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
問題是您不重置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.