我正在尝试创建一个数组并为其赋值。虽然我能够正确分配值,但我无法检索这些值,我不知道为什么。
以下是代码段的一部分。
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
为什么我的程序能够正确接受值,但是当我稍后尝试检索它时是否打印出垃圾值?
答案 0 :(得分: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)
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)
请记住,通过偏移量递增指针并不会添加到原始内存地址,但这取决于指针类型。
答案 2 :(得分: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
答案 3 :(得分:0)
问题是你没有重置你的arr指针。因此,在第二个循环中,您实际上会在初始数组之后打印值。
您需要创建一个变量来遍历您的数组。
void *p = arr;
然后用它来遍历数组。再次在第二次循环之前。
此外,不要强制转换malloc函数调用的返回值(即使将它转换为void指针,它是malloc的实际返回类型)。
编辑:你实际上并没有改变arr的价值。我的坏。答案 4 :(得分: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;
}