由于某种原因,我的函数只返回数组中的第一个元素,我无法弄清楚为什么数组的其余部分超出了范围。该函数接受两个整数数组,添加它们各自的元素,并将总和放入第三个返回的数组中。
这是我的代码:
#include <stdio.h>
/* count digits, white space, others */
int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len);
void main() {
int arr1[10];
size_t arr1len = 10;
int arr2[10] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
size_t arr2len = 10;
int i;
int *x;
arr1[0] = 2;
arr1[1] = 3;
arr1[2] = 2;
arr1[3] = 2;
arr1[4] = 2;
arr1[5] = 2;
arr1[6] = 3;
arr1[7] = 2;
arr1[8] = 2;
arr1[9] = 2;
//printf("%d\t%d\t%d\n", arr1, *arr1, *(arr1 + 1));
x = sumarrays(arr1, arr1len, arr2, arr2len);
for (i = 0; i < 10; i++) {
printf("Array1: %d\tArray 2: %d\tX = %d\n", arr1[i], arr2[i], x[i]);
}
//return 0;
}
int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
int i;
int total[10];
for (i = 0; i < 10; i++) {
total[i] = *(arr1 + i) + *(arr2 + i);
}
for (i = 0; i < 10; i++) {
printf("%d\t", total[i]);
}
printf("\n");
return total;
}
这是输出:
4 5 4 4 4 4 5 4 4 4
Array1: 2 Array 2: 2 X = 4
Array1: 3 Array 2: 2 X = 1974388256
Array1: 2 Array 2: 2 X = -161927102
Array1: 2 Array 2: 2 X = 2686628
Array1: 2 Array 2: 2 X = 8670801
Array1: 2 Array 2: 2 X = 0
Array1: 3 Array 2: 2 X = 27
Array1: 2 Array 2: 2 X = 2686540
Array1: 2 Array 2: 2 X = 4
Array1: 2 Array 2: 2 X = 2686916
第一行是函数中的sum数组元素。剩下的就是main()中发生的事情。
我错过了什么?
*编辑* 答案
谢谢大家的帮助!我实际上不久前学过C和C ++,但最近开始回过头来调整我的知识。非常感谢所有的帮助。
主要答案是
1)静态分配内存(使用static关键字)
2)动态分配内存(使用malloc())
3)使变量成为全局
4)将结果total()作为参数传递给函数,使其不会超出范围。
答案 0 :(得分:2)
您正在为您的阵列进行堆栈分配,并且当函数返回时,堆栈分配的存储会消失。改为使用堆分配。
更改
int total[10];
到
int* total = malloc(10*sizeof(int))
。
当然,这意味着你完成后还必须free
内存。在这种情况下,在main return 0;
之前,您需要
free(x);
答案 1 :(得分:2)
我的函数只返回数组中的第一个元素,我无法弄清楚为什么数组的其余部分超出了范围。
不,它返回指向第一个元素的指针 - 整个数组超出范围。你看到的任何数据碰巧都保留在函数中,这是运气而不是判断,你不能使用它,因为它被释放供其他函数使用。
C中的数组不是first class data types - 您无法通过副本返回数组。
正常的解决方案是让调用者拥有该数组,并将其地址和大小传递给该函数。
int* func( int* arr, int arrlen )
{
// write to arr[0] to arr[arrlen-1] ;
return arr ;
}
int main()
{
int array[256] ;
func( array, sizeof(arr)/sizeof*(*arr) ) ;
}
其他不太常见且通常不明智的可能性是返回包含数组的结构(结构是第一类数据类型),但是在许多情况下这样做效率有点低,或者在内部动态分配数组函数,但它不是一个特别好的主意,因为调用者有责任释放内存,可能不知道这个责任 - 这是内存泄漏的一个秘诀。
答案 2 :(得分:1)
您无法返回指向自动本地变量的指针。 total
是一个自动局部变量,在执行函数体之后它不存在。
可以返回指向static
局部变量或动态分配变量的指针。更改
int total[10];
到
int *total = malloc(10 * sizeof(int));
答案 3 :(得分:1)
问题是当sumarrays
返回时,total
数组不再存在 1 ,因此指针值为{{1} } receive不再有效。简而言之,您无法从这样的函数返回数组。
您有几种选择。
第一个(和IMO首选选项)是将main
数组作为您的参数之一传递,并让调用者负责留出足够的内存:
total
在这种方法中,调用者(void sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len, int *total, size_t totallen)
{
...
for (i = 0; i < totalLen; i++) {
total[i] = *(arr1 + i) + *(arr2 + i);
...
}
#define ARRLEN 10
int main( void )
{
...
int x[ARRLEN];
...
sumarrays( arr1, ARRLEN, arr2, ARRLEN, x, ARRLEN);
)负责知道目标数组需要多大,并为其留出内存。帮助将main
函数与sumarrays
分离,因为它不必依赖于参数列表未明确指定的信息(例如数组大小)。使用这种方法,您不仅限于大小为10的数组。
第二个选项是声明main
,使其在total
退出后不会消失。您可以通过在文件范围内声明(如ryyker的答案)或在sumarrays
函数中声明static
来执行此操作:
sumarrays
使用这种方法,int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
int i;
static int total[10];
...
数组将在程序启动时分配并保持到程序终止。使这种方法不那么令人满意的原因是,您只有total
个数组的单个实例,该数组在total
的所有调用中共享。该功能不再是重入;如果sumarrays
调用另一个调用sumarrays
的函数,则第一次调用写入sumarrays
的任何内容都会被第二次调用破坏(total
库函数有此问题,这在过去引起了很多胃灼热)。您的代码显然没有这个问题,但需要注意一些事项。如果您不必,请不要声明strtok
件事。
最后一个选项是static
动态分配sumarrays
的内存(如haccks&#39;和merlin2011&#39;答案)。这避免了重入问题,但现在你必须处理内存管理。 C不是您的母亲,并且不会在您之后进行清理,因此您使用total
或malloc
分配的任何内存都必须与calloc
2一起发布
<小时/> 1。从逻辑上讲,无论如何;内存显然仍然存在,但它已经可供系统的其余部分使用,并且在程序返回
free
功能所花费的时间内被覆盖。
答案 4 :(得分:0)
我同意关于自动(堆栈)和堆内存的所有其他答案。所有好的方法,但堆栈上的 全局变量也是一个选项 。重要的是要注意,不您选择使用堆栈内存,但它也是本地范围。当创建它们的函数返回时,本地范围的自动变量会死亡。但是,全局范围的变量(也使用堆栈存储器存储)在程序的持续时间内存在,因此提供了另一种方法来解决您的问题......
一行更改 将导致代码运行,将total
(自动范围)的本地副本更改为全局:
int total[10];//Put this here, outside of any function block in same file, i.e. (will give it global scope)
//note, commented this in function below
int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
int i;
//int total[10];//move this to global scope
for (i = 0; i < 10; i++) {
total[i] = *(arr1 + i) + *(arr2 + i);
}
for (i = 0; i < 10; i++) {
printf("%d\t", total[i]);
}
printf("\n");
return total;
}
使用此方法 ,全局变量范围可让您的返回成功。在程序退出之前,数组total
会将其保留在堆栈中。