我做了以下事情:
char * copyact(char * from)
{
return ++from;
}
int main()
{
char *string = "school";
char *copy;
copy = copyact(string);
printf("%s", copy);
}
这是打印chool
,但我的想法是当我们尝试在main()中打印它时应用程序必须崩溃。根据范围规则,参数from是copyact函数的本地变量。我是从= + 1开始做的;并将地址返回该地点。因此,当我们返回main时,现在给予该位置的内存是否应该无效,因为必须销毁所有局部变量?为什么这件事仍然有效?
澄清:我们不指定指针和存储位置的内存位置吗?当函数退出时,我们是否还要破坏保存有效地址的指针的地址?或者是因为在执行返回时,它指向的地址已经发送到copy =?
答案 0 :(得分:2)
它有效,因为你的函数获取了对它之外已经存在的对象的引用。它返回的结果只是一个值。虽然通过代码判断,它返回指向从开始移位一的字符串的指针。我不确定这是不是这个想法,如果原版是一个空字符串,它也可能崩溃。
答案 1 :(得分:2)
首先请记住,当你用内存做坏事(比如在变量被破坏后处理它)时,结果是未定义的行为,这意味着与“崩溃”完全不同的东西
未定义的行为意味着任何事情都可能发生(包括崩溃),但任何事情都可能意味着“没有”。实际上,最糟糕的类型的错误是那些未定义的行为不能立即发生任何明显的行为,而只是在代码的其他一些无关和无辜的部分中引发疯狂的行为。或者只有在广大受众面前展示您的节目时才会这样做。
所以请记住,未定义的行为不会崩溃。只有当你很幸运时才会崩溃。
您越早了解错误和崩溃之间的区别就越好。错误是你的敌人,崩溃是你的朋友(因为他们揭示了一个错误)。
该函数返回char *
,并且通过预先递增局部变量来计算该值(指针)。当函数返回时,局部变量被销毁,但由于函数返回其值(指针),因此代码非常安全。
如果函数定义为
,那将是不安全的char *& copyact(char * from)
{
return ++from;
}
因为在这种情况下,返回值是指向char的指针的引用,它会返回对from
的引用,但是当时它已经被销毁了调用者可以访问返回的引用。
顺便说一句,例如g++
编译器在编译修改后的版本时会发出警告:
vref.cpp: In function ‘char*& copyact(char*)’: vref.cpp:3:9: warning: reference to local variable ‘from’ returned
但请注意,即使在这种情况下,您也不能指望运行代码肯定会导致崩溃。例如,在我的计算机上运行带有修改版本的错误代码只会打印"school"
而不是"chool"
。
这没有多大意义,但是一旦你进入未定义的行为领域,这是很正常的。
答案 2 :(得分:1)
char * copyact(char * from)
{
return ++from;
}
char *string = "school";
char *copy;
copy = copyact(string);
您正在将农场积分指向"school"
,这已经存在于内存中
你从+ 1返回,指向“chool”
例如,在这种情况下你不应该返回。
char * copyact(char * from)
{
char a[10]; //declared array, has automatic scope.
return a; // you should not return a and can't be accessed outside of function.
}