函数始终将指针返回null

时间:2018-10-22 17:42:35

标签: c pointers

为什么createArray函数将指针返回0? 我想我应该使用malloc来修复它,但是为什么呢?

   int *createArray(int size)
{
    int i;
    int arr[size];

    i = 0;
    while (i < size)
    {
        arr[i] = i;
        i++;
    }
    return arr;
}

int main()
{
    int *ar;
    printf("%i", (createArray(10)));
}

3 个答案:

答案 0 :(得分:1)

arr变量分配在堆栈上。 从函数返回时,将释放堆栈。 然后,您返回的指针将指向一个无效的内存位置,该位置可能设置为null。

答案 1 :(得分:1)

从函数返回数组时,实际上是在返回指向数组第一个元素的指针。当函数返回时,其局部变量使用的内存不再有效。

因此,您将返回一个指向不再存在的变量的指针。以任何方式使用该指针都会调用undefined behavior。在这种特殊情况下,无效地址可以被取消引用,并且恰好包含值0,但是不能保证在更改程序时行为会保持一致。

为此,您需要动态分配内存。然后可以在程序的整个生命周期内使用它。

int *arr = malloc(sizeof(*arr) * size);

这也意味着您在使用完该内存后需要free

int *ar = createArray(10);
printf("%i", ar[0]);
free(ar);

答案 2 :(得分:1)

基本问题是您的函数正在返回局部变量的地址。函数返回后,该局部变量将不再存在,因此指向它的任何指针都是无效的。

为更正您的代码中的某些问题,我在顶部添加了func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell: EmojiCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "EmojiCollectionViewCell", for: indexPath) as! EmojiCollectionViewCell return cell } func collectionView(_ collectionView: UICollectionView, willDisplay c: UICollectionViewCell, forItemAt indexPath: IndexPath) { let cell = c as! EmojiCollectionViewCell let imageName = String(format:"%@-%@", categories[selectedCategory], NSNumber(value: indexPath.row + 1)); let emojiImage = UIImage(named: imageName) cell.setupWithEmojiImage(image: emojiImage) } func collectionView(_ collectionView: UICollectionView, didEndDisplaying c: UICollectionViewCell, forItemAt indexPath: IndexPath) { let cell = c as! EmojiCollectionViewCell cell.setupWithEmojiImage(image: nil) } #include <stdio.h>必需),并将您的printf调用从更改为

printf

printf("%i", (createArray(10)));

当我使用gcc编译并运行程序时,输出为:

printf("%p\n", (void*)createArray(10));

表示您的函数正在返回空指针。 (这不是“指向null的指针”;指针为null。)这不是我期望的;我期望一个无效的垃圾指针值。 (当我使用tcc而不是gcc时,会得到(nil) 。)

很显然,gcc识别出您的代码具有未定义的行为,并将0x7fffd95a7140语句替换为return。这是一个完全合法的转换(它可能会阻止您的程序使用无效的指针进行令人讨厌的操作,从而修改程序不拥有的内存)。

底线:您的程序具有未定义的行为,并且您无法假设其将执行的操作。是的,使用return NULL;分配数组并返回分配的数组的地址是修复它的一种方法。