C语言传值操作
C语言中的函数参数传递都是传值操作,所以要使被调用函数改变调用函数的属性内容,则需要传递所需修改属性的指针——属性地址。
例1:
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
请问运行Test
函数会有什么样的结果?
答:
因为GetMemory函数接收的是str指针的拷贝
,所以,当其退出时,str的拷贝p在栈中的内容会被释放,并且以上操作对Test
函数中的str没有影响,
str一直都是 NULL
,
strcpy(str, "hello world");
将使
程序崩溃。
例2:
Void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
请问运行Test
函数会有什么样的结果?
答:
(
1
)能够输出hello;
(2
)内存泄漏
原因:以上两个对照说明形参只能传递地址不能传递值。
例3:
char *GetMemory(void)
{
char p[] = "hello world"; //此行将p[]改成*p就对了,此时p[]存在
return p; //于栈里边,*p的话字符串存于常量区
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
请问运行Test
函数会有什么样的结果?
请问运行Test
函数会有什么样的结果?
答:
可能是乱码。
因为GetMemory
返回的是指向“栈内存”的指针,该指针的地址不是 NULL
,但其原现的内容已经被清除,新内容不可知。
例4:
void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL)
{
strcpy(str, “world”);
printf(str);
}
}
答:篡改动态内存区的内容,后果难以预料,非常危险。
因为free(str);
之后,str
成为野指针,
if(str != NULL)
语句不起作用。谨记malloc之后一定记得free,free之后将指针NULL一下,以免形成野指针。
以下摘自其他地方:
例5:
void GetMemory(char **p,int num)
{
/*p,指向指针的指针,*p,p指向的指针(即str),**p,最终的对象,str指向的单元*/
*p=(char *)malloc(num);
//申请空间首地址付给传入的被p指向的指针,即str
}
int main()
{
char *str=NULL;
GetMemory(&str,100); //传入指针变量本身的地址
strcpy(str,"hello");
free(str);
if(str!=NULL)
{
strcpy(str,"world");
}
printf("\n str is %s",str); 软件开发网 www.mscto.com
getchar();
}
问输出结果是什么?
答案:输出str is world。
free 只是释放的str指向的内存空间,它本身的值还是存在的.所以free之后,有一个好的习惯就是将str=NULL.此时str指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话,这段存储空间是可能被重新分配给其他变量的,尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常会打印出world来。这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完成的。当你malloc一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一些),然后在这块空间中记录一些管理信息(一般是在你申请的内存
前面一点),并将可用内存的地址返回。但是释放内存的时候,管理库通常都不会将内存还给操作系统,因此你是可以继续访问这块地址的。
分享到:
相关推荐
在C语言中,参数传递是函数调用时传递数据给函数的一种方式,主要分为值传递、地址传递和引用传递三种形式。以下是对这三个考题的分析以及相关知识点的详细解释。 1. **值传递(Value Passing)** - 在考题一中,`...
3. **内存管理**:传值无法访问超出函数作用域的变量,而传指针可以直接操作堆内存中的数据,这对于动态分配内存和管理复杂数据结构非常有用。 4. **函数设计**:根据函数的需求,开发者可以选择最适合的参数传递...
函数式编程在C语言中也占有一定地位,手册会讲解如何定义和调用函数,以及函数参数的传值与传址。还有预处理器的使用,如宏定义、条件编译等,这些都是C语言编程中不可或缺的部分。 错误处理和调试技巧也是《C语言...
理解指针的运算和解引用操作是进阶C语言的关键。 2. 动态内存分配:使用malloc和free函数动态分配和释放内存,掌握内存管理可以避免内存泄漏问题。 四、数组与字符串 1. 数组:一组相同类型的数据集合,可以通过...
C语言的输入/输出操作主要依赖于标准库中的`<stdio.h>`,包括printf和scanf函数。书中会详细介绍如何使用这些函数进行格式化输出和输入,以及文件操作。 七、错误处理与调试 理解和处理程序运行时的错误是编程过程...
Block是C语言的扩展,可以捕获并存储当前作用域内的变量,常用于回调和异步操作。通过将Block作为参数传递,可以实现在不同上下文之间传递数据。例如,`UIAlertAction`的handler属性就是一个Block,用于处理用户...
8. 其他高级主题:如文件操作、预处理器宏、位运算等,这些都是进阶C语言编程的必备知识。 这份参考答案文档对于自我检验、查漏补缺非常有帮助,它能让你更清晰地看到自己在理解或应用上的不足,并针对性地进行改正...
7. **结构体与联合体**:讲解如何创建和操作自定义数据结构,理解内存分配和结构体的传值与传址。 8. **预处理器**:解释宏定义、包含文件等预处理指令的作用。 9. **内存管理**:涵盖动态内存分配(malloc、...
在教程中,你将学习如何定义、调用函数,以及理解参数传递机制,包括传值和传址的区别。 C语言中的指针是其独特且强大的特性之一。指针允许我们直接操作内存,这对于实现高效的数据结构和算法至关重要。教程会详细...
此外,C语言还支持一些高级特性,如位运算、文件操作和预处理器宏,这些都能帮助程序员实现更底层的控制。例如,位运算可以用于直接操作二进制位,文件操作则允许程序读写磁盘上的数据。 在"教案"中,你可能会找到...
5.7 函数调用和传值调用 5.8 开发大型程序 5.9 使用断言 5.10 作用域规则 5.10.1 平行和嵌套代码块 5.10.2 以调试为目的使用代码块 5.11 存储类型 5.11.1 auto存储类型 5.11.2 extern存储类型 5.11.3 register存储...
- 定义与调用:了解如何定义和调用自定义函数,理解参数传递机制,包括传值和传址。 - 函数指针:理解函数指针的概念,以及如何使用它来实现回调函数和动态调度。 - 内联函数与预处理器宏:探讨内联函数以提高...
在C语言中,函数调用主要有三种方式:传值调用、传地址调用和引用调用。这三种调用方式决定了函数如何处理传递给它的参数。下面将详细讲解每种调用方式及其特点。 1. 传值调用(Value Passing) 在这种调用方式中...
学习如何声明、初始化和操作指针,理解指针与数组、函数的关系,以及动态内存分配(如malloc和free函数)是掌握C语言的关键。 结构体和联合体是C语言中的复合数据类型,它们可以将多个不同类型的变量组合成一个单一...
本教程涵盖了C语言的各个方面,包括基本语法、数据类型、控制结构、函数、数组、指针、结构体、文件操作等核心主题。 首先,C语言的基础知识是学习的关键。C语言是一种强大的、低级的编程语言,它的语法简洁而直接...
C语言是一种强大的、高效的编程语言,由Dennis Ritchie在20世纪70年代初期开发,用于编写UNIX操作系统。它的设计目标是提供一种既接近机器语言又具有高级语言特性的语言,以实现高效、灵活和可移植的代码。 在C语言...
5. **函数**:C语言中的函数是代码的复用单元,谭浩强的教材会讲解如何定义、调用函数,以及函数参数的传递方式(传值和传址)。 6. **数组与指针**:C语言中的数组和指针是其独特之处,教材会介绍如何声明、初始化...
以上就是C语言面试题中可能出现的知识点,包括基础语法、指针、结构体、文件操作、内存管理和函数等。对于华为等公司的笔试及面试,考生需要对这些知识点有扎实的掌握,并能够灵活运用到实际问题中。通过不断练习和...
4. 函数定义与调用:理解函数的作用,如何定义函数,以及参数传递的方式(传值与传址)。 5. 主函数与程序入口:了解main()函数的重要性,程序的执行起点以及返回值的含义。 三、数组与指针 6. 数组:学习一维、二...