3

我做了以下事情:

char * copyact(char * from)
{
    return ++from;
}

int main()
{

    char *string = "school";
    char *copy;
    copy = copyact(string);
    printf("%s", copy);
}

这是打印chool,但是我的想法是当我们尝试在 main() 中打印它时应用程序必须崩溃。根据作用域规则,参数 from 是 copyact 函数的局部变量。我正在做 from = from + 1; 并将地址返回到那个地方。那么当我们回到 main 时,现在分配给那个位置的内存不应该是无效的,因为所有的局部变量都必须被销毁吗?为什么这东西还能用?

澄清:我们不是为指针 &from 分配一个内存位置,它存储字符串的地址吗?当函数退出时,我们不是也销毁了持有有效地址的指针的地址吗?还是因为在执行 return 时,它指向的地址已经发送到 copy= ?

4

3 回答 3

2

它可以工作,因为您的函数获取了对已经存在于它之外的对象的引用。它返回的结果只是一个值。虽然从代码来看,它返回的指针指向从开始移位的字符串。我不确定这是不是这个想法,如果原始字符串是空字符串,它也可能会崩溃。

于 2013-10-13T08:43:09.047 回答
2

1.未定义的行为不是崩溃

首先请记住,当你对内存做坏事时(比如在变量被销毁后处理变量),结果是未定义的行为,这意味着与“崩溃”完全不同的事情。

未定义的行为意味着任何事情都可能发生(包括崩溃),但任何事情也可能意味着“什么都没有”。实际上,最糟糕的错误类型是那些未定义的行为不会立即做出任何明显的事情,而只会在稍后执行一百万条指令的代码的其他一些不相关且无辜的部分中引发疯狂行为。或者仅当在广大观众面前展示您的节目时。

所以请记住,未定义的行为不是崩溃。只有当你幸运时,它才会崩溃。

您越早了解错误和崩溃之间的区别,它就越好。错误是您的敌人,崩溃是您的朋友(因为它们揭示了错误)。

2.这段代码没有做坏事

该函数返回 a char *,并且这个值(一个指针)是通过预先增加一个局部变量来计算的。当函数返回时,局部变量被销毁,但是因为函数返回了它的(一个指针),所以代码是完全安全的。

如果函数定义为

char *& copyact(char * from)
{
    return ++from;
}

因为在这种情况下,返回值是对指向 char 的指针的引用,并且它会返回对它的引用from,但是当调用者可以访问返回的引用时,它已经被销毁了。

顺便说一下,g++当您编译修改后的版本时,编译器会发出警告:

vref.cpp:在函数 'char*& copyact(char*)' 中:
vref.cpp:3:9:警告:返回对局部变量“from”的引用

但是请注意,即使在这种情况下,您也不能期望运行代码肯定会导致崩溃。例如,在我的计算机上运行带有修改版本的错误代码只是打印"school"而不是"chool".

这没有多大意义,但是一旦您进入未定义的行为领域,这是很正常的。

于 2013-10-13T09:22:07.073 回答
1
char * copyact(char * from)
{
    return ++from;
}

    char *string = "school"; 
    char *copy;
    copy = copyact(string);

你正在制作农场点"school",它已经存在于内存中

并且您从指向“chool”的+1返回

例如,在这种情况下您不应该返回。

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. 
 }
于 2013-10-13T09:05:48.120 回答