前言
写这篇文章,是因为同学在leetcode上遇到了这样一个错误:
- 题目:Two Sum
- 代码如下:
int* twoSum(int* nums, int numsSize, int target)
{
int i,j;
int res[2]; /* 加上static之后正常运行 */
for (i=0; i<numsSize; i++) {
for (j=i; j<numsSize; j++) {
if (nums[i]+nums[j]==target) {
res[0]=i;
res[1]=j;
break;
} else {
continue;
}
}
}
return res;
}
- 运行时出现错误:
load of null pointer of type 'const int'
- Google之后发现,在声明res[2]的时候加上static就可以正常运行。于是在《The C Programming Language》(P70,4.6 静态变量)找到了相关内容:
用static限定外部变量与函数,可以将其后声明的对象的作用域限定为被编译源文件的剩余部分。该外部变量/函数除了对该所在的文件可见外,其他文件都无法访问。
用static声明内部变量,则该变量是某个特定函数的局部变量,只能在该函数中使用。但它与自动变量不同的是,不管其所在函数是否被调用,它一直存在,而不像自动变量那样,随着所在函数的被调用和退出而存在和消失。换句话说,static类型的内部变量是一种只能在某个特定函数中使用但一直占据存储空间的变量。
分析上面的代码,函数返回了一个int类型的指针,但是报错却说是一个空指针。猜想是int res[2];的声明导致res是一个自动变量的数组指针,在退出该函数之后,res指针指向的内存被覆盖,所以导致出错。使用static进行声明,可以保证res[2]不会因为函数的退出而消失。下面进行验证。
验证
参考资料
平台和工具
- Windows 10, Code::Blocks-16.01(mingw)
测试代码
#include <stdio.h> char *test1(void) { /* * 编译时出现warning,运行时打印乱码。 * char b[10] 是局部变量,其存放在栈上,在函数执行完成就会被释放。 * 而返回它存放的地址,此时已经是可能是个非法地址。 * 运行时打印乱码,验证了b[10]的内存被释放。 */ char b[10] = "abcde"; return b; // warning: function returns address of local variable [-Wreturn-local-addr]| } char *test1_ver2(void) { /* * 正确运行。 * 定义static char b[10]; 将其存放在静态存储区,只有在程序运行结束后才会被系统回收。 * 即使退出该函数,b[]数组存放的静态存储区始终存在,所以,我们再对其进行访问,不会出现错误。 */ static char b[10] = "abcde"; return b; } char *test2(void) { /* * 可以运行,但打印出错。 * c[10]和*pStr均为自动变量,保存在栈中;函数返回时,c[]数组和pStr指针的内存空间被释放 * 所以,在外部访问c[]数组时,指向的内存空间无效。 */ char c[10] = "abcde"; char *pStr = c; return pStr; } char *test3(void) { /* * 正确运行。 * 指针c保存在栈中,但是"abcdef"字符串保存在常量区,其内存空间直到程序运行结束才会被释放。 * 所以,返回的地址是一个实际存在的有效地址。 */ char *c = "abcdef"; return c; } int main() { char *p_test1, *p_test1_ver2, *p_test2, *p_test3; p_test1 = test1(); p_test1_ver2 = test1_ver2(); p_test2 = test2(); p_test3 = test3(); printf("test1:%s\n", p_test1); printf("test1_ver2:%s\n", p_test1_ver2); printf("test2:%s\n", p_test2); printf("test3:%s\n", p_test3); return 0; }输出结果1:
test1:[w骾 A test1_ver2:abcde test2:` test3:abcdef输出结果2:
test1:[w詡? test1_ver2:abcde test2:` test3:abcdef
本文探讨了在C语言中遇到的返回局部指针变量导致的错误,通过分析《The C Programming Language》中的静态变量概念,解释了使用`static`关键字的原因。在示例代码中,由于没有使用`static`,函数返回的`int`类型指针在函数退出后所指向的内存被回收,从而引发错误。通过添加`static`,确保了变量在函数退出后依然存在,解决了问题。文章通过测试验证了这一解决方案。

1307

被折叠的 条评论
为什么被折叠?



