菜单开关

周梦康 发表于 2017-09-28 913 次浏览 标签 : C语言快速入门

免费领取阿里云优惠券 我的直播 - 《PHP 进阶之路》

实验1

假如我们有一个函数a,他的返回值是一个int,然后我们需要在main函数里接收a的返回值。

#include <stdio.h>

int a();

int main(int argc, char const *argv[]) {
    
    printf("%d",a());

    return 0;
}

int a()
{
    int b = 1;
    return b;
}

实验2

现在改为返回一个char *字符串

#include <stdio.h>

char * a();

int main(int argc, char const *argv[]) {

    printf("%s",a());

    return 0;
}

char * a()
{
    char *b = "string";
    return b;
}

实验3

如果是返回一个字符数组或者一个int数组呢?

#include <stdio.h>

char * a();

int main(int argc, char const *argv[]) {

    printf("%s",a());

    return 0;
}

char * a()
{
    char b[] = {'a','b','\0'};
    return b;
}

新人困惑:为什么明明是数组,却要返回一个指针呢?

数组在 C 语言里是无法返回的,假设可以返回数组,那么返回返回值类型如何写呢?既然是函数都是动态的,返回数组的长度也是动态的,所以只能返回一个指针。

因为数组是连续的内存,而指针的类型正好可以用来计算数组各个元素内存的步长(需要偏移的字节数),这样就可以依次取出数组中的值了。这里我们用了一个\0来标识字符的结束。

编译出错,为什么呢?

$ gcc test.c -o test
test.c:15:12: warning: address of stack memory associated with local variable
      'b' returned [-Wreturn-stack-address]
    return b;
           ^
1 warning generated.

因为b是在栈上分配的,当函数执行完毕之后就内存就回收了,所以返回b的首地址是没有意义的,里面的数据已经被清空。这就是局部变量的作用域。

相比之,实验2也是返回的指针,为什么就没问题呢?
因为字符串是在常量区申请的内存,函数结束后,内存不会回收。
参考 字符串初始化的原理

堆内存的使用

假如就是要返回数组,那应该怎么办呢?那么堆内存就可以派上用场了,因为堆上内存是使用者自己来控制内存申请和释放。

#include <stdio.h>
#include <stdlib.h>

char *a();

int main(int argc, char const *argv[]) {

    char *c = a();
    printf("%s", c);
    free(c);// 记得释放内存哦

    return 0;
}

char *a() {
    char *b = (char *) malloc(sizeof(char) * 3);
    b[0] = 'a';
    b[1] = 'b';
    b[2] = '\0';

    return b;
}

嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

评论列表