{
char* ch1;
ch1 = "abc";
return ch1;
}
char* func2()
{
char* ch2 = "def";
return ch2;
}
void main()
{
printf("%s\n%s", func1(), func2());
}
问:
1.func1与func2有效果区别吗?
2.输出结果是什么? 会输出abc和def吗?
3.ch1和ch2的生命周期是到什么?是在函数结束释放还是整个main函数结束释放?
14 个解决方案
#1
没什么区别啊 输出结果就是 abc 和 def
在函数结束时释放 使用的是它的返回值
在函数结束时释放 使用的是它的返回值
#2
这里面有临时变量的概念吗?
如果有,是否在函数func1和func2结束时指针ch1和ch2的内容会释放?如果释放了,在main函数中还会输出其赋值的内容吗?
按一般概念应该是临时变量会在其函数结束时已经释放了,返回的结果应该不确定吧?
用VC2005测试结果是会输出abc和def,不知道这里的输出是否是因为临时变量存储在静态变量区的缘故?临时变量能输出因为什么呢?
如果有,是否在函数func1和func2结束时指针ch1和ch2的内容会释放?如果释放了,在main函数中还会输出其赋值的内容吗?
按一般概念应该是临时变量会在其函数结束时已经释放了,返回的结果应该不确定吧?
用VC2005测试结果是会输出abc和def,不知道这里的输出是否是因为临时变量存储在静态变量区的缘故?临时变量能输出因为什么呢?
#3
偶晕啊。返回的又不是指向这些局部变量的地址,而是全局字符串常量的地址,当然不会有问题。
除非乃这么做:
看看叫。
除非乃这么做:
char *func(void)
{
char a[] = { 'O', 'K' };
return a;
}
int main(void)
{
char *p = func();
puts("Hello, world!");
printf("%s\r\n", p);
}
看看叫。
#4
1、没有区别,不过2的语法更好些,可能1的写法在某些编译器上不支持。
2、会正确输出。
3、ch1,ch2是临时变量,所以存在周期只在函数体内。
可能你对正确输出字符串感到疑惑吧:
ch1,ch2虽然在函数离开时释放了,但字符串的地址却被正确返回了,所以只要字符串的生命周期一直存在,则就会得到正确输出。
而字符串是存储在数据静态区,生存周期跨越整个应用程序。所以字符串能正确输出。但要明白这种写法是不好的。
2、会正确输出。
3、ch1,ch2是临时变量,所以存在周期只在函数体内。
可能你对正确输出字符串感到疑惑吧:
ch1,ch2虽然在函数离开时释放了,但字符串的地址却被正确返回了,所以只要字符串的生命周期一直存在,则就会得到正确输出。
而字符串是存储在数据静态区,生存周期跨越整个应用程序。所以字符串能正确输出。但要明白这种写法是不好的。
#5
在fun1和fun2调用结束时,ch1和ch2就释放了,但同时返回了值与ch1和ch2相同的指针。
指针ch1,ch2指向的内存空间没有释放。因此输入结果应该会是:abc和def
#6
ch1的生存期是在func1中,当func1结束之后,ch1就结束了。但是,这里有个问题,在func1中,你的“abc” 是静态字符串,他是存储在静态存储区。也就是说,虽然func1结束了,但是,“abc” 还是存在,并不会被释放。而你func1已经将 “abc” 的地址返回出去了。所以,在man函数中依然可以找到 “abc”。func2也是同理。不知道说明白没有
#7
也就是说在函数返回时字符串abc和def的空间没有释放,什么样的数据可以放在数据静态区呢?
下面的函数调用后能正常输出123? 123也放在了数据静态区吗?
int* func3()
{
int n1 = 123;
int* n2 = &n1;
return n2;
}
//注:测试后也能正常输出123?
下面的函数调用后能正常输出123? 123也放在了数据静态区吗?
int* func3()
{
int n1 = 123;
int* n2 = &n1;
return n2;
}
//注:测试后也能正常输出123?
#8
我倒明白返回的是字符串abc内容的地址,与变量ch1没有关系了,只是不清楚这个abc什么时候释放?什么样的变量能放在静态存储区?上面的123也放在了静态存储区了吗?
123应该放在了栈上吧,但怎么还能输出123呢?再做什么样的操作输出就不是123呢?
在main函数中,我这样调用的
void main()
{
int* n = func3();
int nn = 3;
printf("%d", *n); //依然输出123?
}
123应该放在了栈上吧,但怎么还能输出123呢?再做什么样的操作输出就不是123呢?
在main函数中,我这样调用的
void main()
{
int* n = func3();
int nn = 3;
printf("%d", *n); //依然输出123?
}
#9
关于char* 那个,我明白了,但关于int这个有点疑问?
int func4()
{
return 1;
}
在调用printf函数中
printf("%d\n", *n); //*n的内容是123
printf("%d\n%d", *n, func4()); //*n的内容是随机值(可能是什么地址)
?
int func4()
{
return 1;
}
在调用printf函数中
printf("%d\n", *n); //*n的内容是123
printf("%d\n%d", *n, func4()); //*n的内容是随机值(可能是什么地址)
?
#10
存储区域分为:堆、栈、静态区、全局区
临时变量为栈区
malloc分配的在堆区
static修饰的变量,或常量字符串都在静态区
全局变量存放在全局区
所以,字符串常量存放在静态区,和数字常量不同
临时变量为栈区
malloc分配的在堆区
static修饰的变量,或常量字符串都在静态区
全局变量存放在全局区
所以,字符串常量存放在静态区,和数字常量不同
#11
参考前面部分的说明:
1、你这两个函数是没有区别的,都是用局部变量指向一个静态区的数据,所以你返回的时候是静态去的内容,因此你可以得到你想要的输出;
2、如果想了解局部变量作用域可以参考一下事例:
char* StaticTest()
{
char* str = NULL;
str = "string"; //这里指向一个放在静态区的数据
return str; //返回的是静态区域数据
}
char* HeapTest()
{
char* str = (char*)calloc(1,sizeof(char)*16);//申请的堆内存,请记得free
memcpy(str,"string",sizeof("string"));
return str;
}
char * localTest()
{
char str[16]={0};
memcpy(str,"string",sizeof("string"));
return str; //这里才是返回的是栈上的地址
}
int main(int argc,char**argv)
{
char * h = localTest(); //这个时候看调试信息还看得到h的内存地址和调用函数的str相同,内容也有,但是是不可靠的,栈会覆盖这段信息,
int i=0,l=sizeof("string");
for(i;i<l;++i)
{
printf("%c",*(h+i));//这里没有做任何操作的时候你能够获取到第一个字符s,后续的字符就是乱码了!!
}
}
//总结,栈上的数据和静态区、堆内存的生存周期是不一样的,离开作用域将不可靠,会被无情的重写;静态区和堆内存是在整个程序的运行期。
#12
VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
#13
"字符串常量存放在静态区,和数字常量不同"
这句有用
#14
谢谢dx们指导,否则还迷糊呢,汗颜...
#1
没什么区别啊 输出结果就是 abc 和 def
在函数结束时释放 使用的是它的返回值
在函数结束时释放 使用的是它的返回值
#2
这里面有临时变量的概念吗?
如果有,是否在函数func1和func2结束时指针ch1和ch2的内容会释放?如果释放了,在main函数中还会输出其赋值的内容吗?
按一般概念应该是临时变量会在其函数结束时已经释放了,返回的结果应该不确定吧?
用VC2005测试结果是会输出abc和def,不知道这里的输出是否是因为临时变量存储在静态变量区的缘故?临时变量能输出因为什么呢?
如果有,是否在函数func1和func2结束时指针ch1和ch2的内容会释放?如果释放了,在main函数中还会输出其赋值的内容吗?
按一般概念应该是临时变量会在其函数结束时已经释放了,返回的结果应该不确定吧?
用VC2005测试结果是会输出abc和def,不知道这里的输出是否是因为临时变量存储在静态变量区的缘故?临时变量能输出因为什么呢?
#3
偶晕啊。返回的又不是指向这些局部变量的地址,而是全局字符串常量的地址,当然不会有问题。
除非乃这么做:
看看叫。
除非乃这么做:
char *func(void)
{
char a[] = { 'O', 'K' };
return a;
}
int main(void)
{
char *p = func();
puts("Hello, world!");
printf("%s\r\n", p);
}
看看叫。
#4
1、没有区别,不过2的语法更好些,可能1的写法在某些编译器上不支持。
2、会正确输出。
3、ch1,ch2是临时变量,所以存在周期只在函数体内。
可能你对正确输出字符串感到疑惑吧:
ch1,ch2虽然在函数离开时释放了,但字符串的地址却被正确返回了,所以只要字符串的生命周期一直存在,则就会得到正确输出。
而字符串是存储在数据静态区,生存周期跨越整个应用程序。所以字符串能正确输出。但要明白这种写法是不好的。
2、会正确输出。
3、ch1,ch2是临时变量,所以存在周期只在函数体内。
可能你对正确输出字符串感到疑惑吧:
ch1,ch2虽然在函数离开时释放了,但字符串的地址却被正确返回了,所以只要字符串的生命周期一直存在,则就会得到正确输出。
而字符串是存储在数据静态区,生存周期跨越整个应用程序。所以字符串能正确输出。但要明白这种写法是不好的。
#5
在fun1和fun2调用结束时,ch1和ch2就释放了,但同时返回了值与ch1和ch2相同的指针。
指针ch1,ch2指向的内存空间没有释放。因此输入结果应该会是:abc和def
#6
ch1的生存期是在func1中,当func1结束之后,ch1就结束了。但是,这里有个问题,在func1中,你的“abc” 是静态字符串,他是存储在静态存储区。也就是说,虽然func1结束了,但是,“abc” 还是存在,并不会被释放。而你func1已经将 “abc” 的地址返回出去了。所以,在man函数中依然可以找到 “abc”。func2也是同理。不知道说明白没有
#7
也就是说在函数返回时字符串abc和def的空间没有释放,什么样的数据可以放在数据静态区呢?
下面的函数调用后能正常输出123? 123也放在了数据静态区吗?
int* func3()
{
int n1 = 123;
int* n2 = &n1;
return n2;
}
//注:测试后也能正常输出123?
下面的函数调用后能正常输出123? 123也放在了数据静态区吗?
int* func3()
{
int n1 = 123;
int* n2 = &n1;
return n2;
}
//注:测试后也能正常输出123?
#8
我倒明白返回的是字符串abc内容的地址,与变量ch1没有关系了,只是不清楚这个abc什么时候释放?什么样的变量能放在静态存储区?上面的123也放在了静态存储区了吗?
123应该放在了栈上吧,但怎么还能输出123呢?再做什么样的操作输出就不是123呢?
在main函数中,我这样调用的
void main()
{
int* n = func3();
int nn = 3;
printf("%d", *n); //依然输出123?
}
123应该放在了栈上吧,但怎么还能输出123呢?再做什么样的操作输出就不是123呢?
在main函数中,我这样调用的
void main()
{
int* n = func3();
int nn = 3;
printf("%d", *n); //依然输出123?
}
#9
关于char* 那个,我明白了,但关于int这个有点疑问?
int func4()
{
return 1;
}
在调用printf函数中
printf("%d\n", *n); //*n的内容是123
printf("%d\n%d", *n, func4()); //*n的内容是随机值(可能是什么地址)
?
int func4()
{
return 1;
}
在调用printf函数中
printf("%d\n", *n); //*n的内容是123
printf("%d\n%d", *n, func4()); //*n的内容是随机值(可能是什么地址)
?
#10
存储区域分为:堆、栈、静态区、全局区
临时变量为栈区
malloc分配的在堆区
static修饰的变量,或常量字符串都在静态区
全局变量存放在全局区
所以,字符串常量存放在静态区,和数字常量不同
临时变量为栈区
malloc分配的在堆区
static修饰的变量,或常量字符串都在静态区
全局变量存放在全局区
所以,字符串常量存放在静态区,和数字常量不同
#11
参考前面部分的说明:
1、你这两个函数是没有区别的,都是用局部变量指向一个静态区的数据,所以你返回的时候是静态去的内容,因此你可以得到你想要的输出;
2、如果想了解局部变量作用域可以参考一下事例:
char* StaticTest()
{
char* str = NULL;
str = "string"; //这里指向一个放在静态区的数据
return str; //返回的是静态区域数据
}
char* HeapTest()
{
char* str = (char*)calloc(1,sizeof(char)*16);//申请的堆内存,请记得free
memcpy(str,"string",sizeof("string"));
return str;
}
char * localTest()
{
char str[16]={0};
memcpy(str,"string",sizeof("string"));
return str; //这里才是返回的是栈上的地址
}
int main(int argc,char**argv)
{
char * h = localTest(); //这个时候看调试信息还看得到h的内存地址和调用函数的str相同,内容也有,但是是不可靠的,栈会覆盖这段信息,
int i=0,l=sizeof("string");
for(i;i<l;++i)
{
printf("%c",*(h+i));//这里没有做任何操作的时候你能够获取到第一个字符s,后续的字符就是乱码了!!
}
}
//总结,栈上的数据和静态区、堆内存的生存周期是不一样的,离开作用域将不可靠,会被无情的重写;静态区和堆内存是在整个程序的运行期。
#12
VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
#13
"字符串常量存放在静态区,和数字常量不同"
这句有用
#14
谢谢dx们指导,否则还迷糊呢,汗颜...