输入与输出c语言_c语言基本知识点

输入与输出c语言_c语言基本知识点1、函数为什么需要传参和返回值(1)函数的作用就是处理数据,传入的参数就是被加工的数据,返回值就是输出的结果

输入与输出c语言_c语言基本知识点

1、函数为什么需要传参和返回值

(1) 函数的作用就是处理数据,传入的参数就是被加工的数据,返回值就是输出的结果。

(2)函数名就是这个函数的入口,在内存中表示就是一个函数代码段的首地址,实质是一个指针常量,所以在程序中使用函数名都是当地址来用的,用来调用这个函数。再理解指针函数的实质就比较简单了。

(3) 如果一个函数没有传参和返回值,也是可以的,也可以正常运行,那么没有返回值和形参的函数怎么运行呢?为什么会有这种函数呢?其实这种类型的函数在C语言中有很多。主要有两个作用:1) 在系统初始化的时候,我们做一些系统的配置工作,这种类型的函数都是一些配置函数,不需要形参。2)我们处理一些全局变量的数据时,会用到这种类型的函数。

2、输入型参数和输出型参数

我们举个例子来说明一下什么是输入型参数,什么是输出型参数。

int func(int a , int *p)

{

*p = a +10;

return 0;

}

int main()

{

int x , y ;

x = 10;

func(x,&y);

printf(“x = %d \n”, x);

printf(“y = %d \n”, y);

return 0;

}

运行结果:

root@ubuntu:/mnt/hgfs/share/code/c_advance/pointer# ./a.out

x = 10

y = 20

结论:

(1) func函数中a是输入型参数,p是输出型参数。

(2) 形参的传值调用是输入型参数。传址调用即有可能是输出型参数,也有可能是输入型参数。作为输入型参数使用时,一般会加入const关键字,表明是只读,不能修改。

2018.3.7更新

今天又发现了一个有趣的现象。事情是这样的:我需要申请一块内存空间,然后使用strcpy来拷贝一个字符串,最后printf打印,直接上代码:

#include

#include

#include

void GetMemory(char *p)

{

printf(“GetMemory\n”);

p = (char *)malloc(100);

printf(“GetMemory: %p\n”, p);

}

int main(void)

{

char *str = NULL;

printf(“&str = %p\n”,&str); //0xbfc6f498

printf(“str = %p\n\n”,str); //(nil)

//GetMemory(str);

GetMemory2(&str);

strcpy(str, “hello world \n”);

printf(“str = %p\n”,str);

printf(“&str = %p\n”,&str);

printf(“%s”,str);

//free(str);

return 0;

}

运行结果如下:

void@ubuntu:/mnt/hgfs/VMshare/code/c$./a.out

&str = 0xbfce7718

str = (nil)

GetMemory

GetMemory: 0x81ab410

Segmentation fault (core dumped)

结果分析:报了段错误,为什么呢? char *str;是一个局部变量,我们传入局部变量然后还想要修改该局部变量的值,这是不科学的,也是不合理的。这种虽然也是传址调用,但是本质上还是传值调用。说的有点绕,需要仔细体会下。 这种传递和上边的传入变量x的效果是一样的。

那么怎么改呢?

两个思路:

1、将char *str = NULL;定义为全局变量,这样我们是把地址空间传递给了一个全局变量,这样函数返回的时候地址空间还在。已验证,就不贴代码和运行结果了。

2、我们使用二维指针来试一下,直接上代码:

#include

#include

#include

void GetMemory2(char **p)

{

*p = (char *)malloc(100);

printf(“p = %p \n”, p);

printf(“*p = %p \n”, *p);

}

int main(void)

{

char *str = NULL;

printf(“main:”);

printf(“&str = %p\n”,&str); //0xbfc6f498

printf(“str = %p\n\n”,str); //(nil)

printf(“\n”);

//GetMemory(str);

GetMemory2(&str);

strcpy(str, “hello world \n”);

printf(“str = %p\n”,str);

printf(“&str = %p\n”,&str);

printf(“%s”,str);

//free(str);

return 0;

}

运行结果如下:

void@ubuntu:/mnt/hgfs/VMshare/code/c$./a.out

main:

&str = 0xbff03f88

str = (nil)

GetMemory2

&p = 0xbff03f70

p = 0xbff03f88

*p = 0x8c6d410

str = 0x8c6d410

&str = 0xbff03f88

hello world

满足了我们的要求。

3、总结

函数在传参的时候,其实在栈空间又复制了一份,比如我们定义函数:int fun(int x),当我们在调用fun(10);的时候,其实编译器内部操作可以看为两步:int x ; x = 10;,且在调用完成后释放该函数申请的变量。我们再看一下这个函数:void GetMemory(char *p),在被调用的时候,函数内部申请了一个char *p的变量,所以我们把这个变量的值是传递不到调用的函数内部的。

我们定义:void GetMemory2(char **p),虽然它内部也定义了一个变量char **p = &str,我们看到被分配了地址空间:0xbff03f70。但是*p指向了malloc申请出来的内存空间。所以我们的str也指向了malloc申请的内存空间。当函数调用结束,**p被释放,但是str指向的内存空间的地址确没有改变,所以就可以正常调用了。换句话说,我申请了一个二重指针指向你,然后修改了你的指向(本来指向null,后来指向malloc申请出来的空间),然后我申请的二重指针被释放掉,但是你的指向还在。

引申:其实传址调用和C++语言的引用&很相似,但又有一点不同(传参调用本身也申请了变量),但是本质都是一样的,我用多个指针变量指向同一块内存,这个指针修改完被释放,但是还有其他指针指向该内存,以此来达到间接修改的目的。在Python中,我们也可以使用多个变量来指向同一个对象,当没有变量指向这个对象的时候,对象空间就会被自动回收。

最后,C语言是一门博大精深的语言,需要我们认真体会。

今天的文章输入与输出c语言_c语言基本知识点分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/81620.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注