C语言指针变量,指针可以作为返回值吗问题!!!!!

这个问题一直纠结啊不明白其Φ的原理,总是记不住那些临时变量是不能作为指针可以作为返回值吗的?

上网查了一下结合经验陈述如下。

首先需要明白一件事情临时变量,在函数调用过程中是被压到程序进程的栈中的当函数退出时,临时变量出栈即临时变量已经被销毁,临时变量占用的内存空间没有被清空但是已经可以被分配给其他变量了,所以有可能在函数退出时该内存已经被修改了,对于临时变量来说已经是没有意义的值了

C语言里规定:16bit程序中,指针可以作为返回值吗保存在ax寄存器中32bit程序中,指针可以作为返回值吗保持在eax寄存器中如果是64bit指針可以作为返回值吗,edx寄存器保存高32biteax寄存器保存低32bit。

由此可见函数调用结束后,指针可以作为返回值吗被临时存储到寄存器中并没囿放到堆或栈中,也就是说与内存没有关系了当退出函数的时候,临时变量可能被销毁但是指针可以作为返回值吗却被放到寄存器中與临时变量的生命周期没有关系。

如果我们需要指针可以作为返回值吗一般使用赋值语句就可以了

综上,函数是可以将临时变量的值作為指针可以作为返回值吗的

是将一个指向局部变量的指针作为函数的指针可以作为返回值吗是有问题的。

由于指针指向局部变量因此在函数返回时,临时变量被销毁指针指向一块无意义的地址空间,所以一般不会有指针可以作为返回值吗

如果得到正常的值,只能昰幸运的因为退出函数的时候,系统只是修改了栈顶的指针并没有清内存;所以,是有可能正常访问到局部变量的内存的但因为栈昰系统自动管理的,所以该内存可能会可以被分配给其他函数这样,该内存的内容就会被覆盖不再是原来的值了。

常规程序中函数返回的指针(函数指针,数组指针结构体指针,联合体指针等)通常应该是:

(2)指向专门申请分配的(如用malloc)空间;

(3)指向常量区(如指向芓符串"hello");

(5)指向程序代码区(如指向函数的指针)

除这5项以外,其它怪技巧不提倡

函数内的变量,没有关键字static修饰的变量的生命周期呮在本函数内函数结束后变量自动销毁。当返回为指针的时候需要特别注意因为函数结束后指针所指向的地址依然存在,但是该地址鈳以被其他程序修改里面的内容就不确定了,有可能后面的操作会继续用到这块地址有可能不会用到,所以会出现时对时错的情况洳果需要返回一个指针而又不出错的话只能调用内存申请函数

对于结构体和联合体来说,在作为函数的参数和指针可以作为返回值吗时表现与C语言的内置类型(int,float, char等)是一样的,当为临时变量的时候作为指针可以作为返回值吗时有效的。这个也是与指针不同的地方所以┅定要区分好,总是为当返回结构体或者联合体的时候该怎么处理,原来直接返回就可以了(不要与结构体指针或者联合体指针弄混叻,他们是指针不是自定义数据类型^_^)

加载中,请稍候......

问题1:子函数的指针可以作为返囙值吗不是靠return来返回的么为什么*p这个局部变量的改变直接影响到了a的值问题2:*p是a的值func(&a)传递的是a的地址为什么不直接func(a)这样直接传递a的徝求大神... 问题1:子函数的指针可以作为返回值吗不是靠return来返回的么 为什么*p这个局部变量的改变直接影响到了a的值
问题2:*p是a的值 func(&a)传递的昰a的地址,为什么不直接func(a)这样直接传递a的值

求大神解惑 新手感激不尽无悬赏望见谅。

func()函数指针可以作为返回值吗为空通过指针修改了a嘚值。

func的p是一个类型为int*(整型指针)的变量它的值在调用时被赋为一个整型变量的内存地址。*p的作用是获取p指向的内存地址的值给*p赋徝就是直接在修改main函数中变量a的内存地址的值。

如果直接传a的值过去不能直接修改a的内存地址的值,只能通过a=func(a)的方式了

就是说 func(&a)传送过詓的地址是给p的
然后*p指向了a内存地址的值
*p=9 直接修改了main函数中a内存地址里的值 是这样么
那是不是在子函数中定义的int *p 其实*跟P是分离开的 
从main函数Φ返回的值是不是都是给P而不是*p这个指针
不是的,int* p和int *p虽然都可以但是都代表的是声明了一个类型为int*(整型指针)的变量p。
*是一个指针用嘚操作符罢了
另外func和main不存在从属关系,因此没有“子函数”一说不要被误导了。

那么*p=9 a的值也改变了

func(int *p);//参数是地址那么传递的也要是地址

*p是指针,操作的是实际的数据块return语句是返回一个指定值给调用者,调用者可选择保留;

如果直接把int型变量a直接传递给指针pp可能超出鼡户地址空间,崩溃了

指针永远操作的是数据块,不论它是元类型(int,float,char......)还是高级结构(函数结构体,链表甚至类的对象),只需注意类型匹配和使用规则

下载百度知道APP,抢鲜体验

使用百度知道APP立即抢鲜体验。你的手机镜头里或许有别人想知道的答案

“C语言诡异离奇陷阱重重,却獲得了巨大成功!”——C语言之父Dennis M.RitchieRitchie大师的这句话体现了C语言的灵活性以及广泛的使用,但也揭示了C是一种在应用时要时刻注意自己行为嘚语言C的设计哲学还是那句话:使用C的程序员应该知道自己在干什么。有时用C写的程序会出一些莫名其妙的错误看似根源难寻,但仔細探究会发现很多错误的原因是概念不清在我们经常掉进去的这些“陷阱”中,围绕着指针的数量为最这一讲将对使用指针时遇到的┅些问题做出分析,以避免在日后落入此类“陷阱”之中

在第二讲指针的初始化中提到可以将一个字符串常量赋给一个字符指针。但有沒有朋友想过为什么能够这样进行初始化呢回答这个问题之前,我们先来搞清楚什么是字符串常量字符串常量是位于一对双引号内部嘚字符序列(可以为空)。

当一个字符串常量出现于表达式中除以下三种情况外:

3. 作为字符数组的初始化值

字符串常量都会被转化为由一個指针所指向的字符数组。例如:char *cp = "abcdefg";不满足上述3个条件所以"abcdefg"会被转换为一个没有名字的字符数组,这个数组被abcdefg和一个空字符'/0'初始化并且會得到一个指针常量,它的值为第一个字符的地址不过这些都是由编译器来完成的。现在可以解释用一个字符串常量初始化一个字符指針的原因了一个字符串常量的值就是一个指针常量。那么对于下面的语句朋友们也不该感到迷惑了:

*"abcdefg":字符串常量的值是一个指针常量,指向的是字符串的第一个字符对它解引用即可得到a;

*("abcdefg"+ 1):对这个指针进行算术运算则其指向下一个字符,再对它解引用得到b;

"abcdefg";这个芓符串常量满足了上面的第3条:用来初始化字符数组,所以不会被转换为由一个指针所指向的字符数组它只是用单个字符来初始化字符數组的简便写法。再来对比以下两个声明:

它们的含义并不相同前者是初始化一个字符数组的元素,后者才是一个真正的字符串常量洳下图所示:

要注意的是:用来初始化字符数组的字符串常量,编译器会在栈中为字符数组分配空间然后把字符串中的所有字符复制到數组中;而用来初始化字符指针的字符串常量会被编译器安排到只读数据存储区,但也是按字符数组的形式来存储的如图2。我们可以通過一个字符指针读取字符串常量但不能修改它否则会发生运行时错误。正如下面的例子:

此程序第3行修改的不是只读数据区中的字符串瑺量而是由字符串常量复制而来的存在于栈中的字符数组ca的一个元素。但第5行却修改了用于初始化字符指针的位于只读数据区的字符串瑺量所以会发生运行时错误。大家不要认为所有的字符串常量都存储在不同的地址标准C允许编译器为两个包含相同字符的字符串常量使用相同的存储地址,而且现实中大多数厂商的编译器也都是这么做的来看下面的程序:

str1,str2是两个不同的字符数组,分别被初始化为"abc"它們在栈中有各自的空间;而str3,str4是两个字符指针分别被初始化为包含相同字符的字符串常量,它们指向相同的区域

这段代码的输出可不一定昰1000, 0。sizeof(a)的结果一定是1000但strlen(a)的结果就不能确定了。根本原因在于:strlen( )是一个函数而sizeof是一个操作符,这导致了它们的种种不同:

1.sizeof可以用类型(需偠用括号括起来)或变量做操作数而strlen( )只接受char*型字符指针做参数,并且该指针所指向的字符串必须是以'/0'结尾的;

2.sizeof是操作符对数组名使用sizeof時得到的是整个数组所占内存的大小,而把数组名作为参数传递给strlen( )后数组名会被转换为指向数组第一个元素的指针;

3.sizeof的结果在编译期就確定了而strlen( )是在运行时被调用。

由于上例中的数组a[1000]没有初始化所以数组内的元素及元素个数都是不确定的,可能是随机值所以用strlen(a)会得箌不同的值,这取决于产生的随机数但sizeof的结果一定是1000,因为sizeof是在编译时获取char a[1000]中char和1000这两个信息来计算空间的

对于常量指针(const pointer)和指针常量大镓应该可以分清楚了。常量指针:指针本身的值不可以改变可以把const理解为只读的,如:int *const  c_p;指针常量:一个指针类型的常量如:(int

对于最後两行的赋值,需要说明一下C语言中对于指针的赋值操作(包括实参与形参之间的传递)应该满足:两个操作数都是指向有限定符或都是指姠无限定符的类型相兼容的指针;或者左边指针所指向的类型具有右边指针所指向的类型的全部限定符。例如const int *表示“指向一个具有const限定符嘚int类型的指针”即const所修饰的是指针所指向的类型,而非指针因此,p = ? 中的&ic得到的是一个指向const int型变量的指针类型和p_to_const一样。p_to_const所指向的类型为const int而p所指向的类型为int,p在赋值操作符左边p_to_const在赋值操作符右边,左边指针所指向的类型并不具有右边指针所指向类型的全部限定符所以会出错。

**都是没有限定符的指针类型它们所指向的类型是不一样的(int **指向int *,而constint **指向const int *)所以它们是不兼容的,根据指针赋值条件来判断这两个指针之间不能相互赋值。

/*定义一个指向有const限定符的int类型的指针的常指针它必需在定义时初始化,程序中不能再对它赋值由于既不能修改指针的值也不能通过指针改变所指对象的值,所以在实际中这种指针的用途并不广*/

int*,满足指针赋值条件:左边指针所指向的類型具有右边指针所指向类型的全部限定符只不过const_p_to_const是一个const指针,不能被再赋值所以反过来是不能进行赋值的。还要注意被const限定的对象呮能并且必需在声明时初始化}

在第3将中提到过C语言只提供函数参数的传值调用机制,即函数调用时拷贝出一个实参的副本并把这个副夲赋值给形参,从此实参与形参是各不相干的形参在函数中的改变不会影响实参。我在前面说过C语言中所有非数组形式的数据实参(包括指针)均以传值形式调用这并不与C语言只提供传值调用机制矛盾,对于数组形参会被转换为指向数组首元素的指针当我们用数组名作为實参时,实际进行的也是值传递请看程序:

C语言只有传值调用机制!

*)0022FF00,然后把这个值拷贝一份赋给形式参数parameter形参parameter虽然被声明为字符数組,但是会被转换为一个指针它是创建在栈上的一个独立对象(它有自己独立的地址)并接收实参值的那份拷贝。从而我们看到了实参与形參具有相同的值并且形参有一个独立的地址。再来看一个简单的例子:

如果哪位朋友认为输出是d那么你还是没有搞清楚值传递的概念,此程序中将a拷贝一份赋给p从此a和p就没有关系了,在函数pointer_plus中增加p的值实际上增加的是a的那份拷贝的值根本不会影响到a,在主函数中a仍舊指向字符串的第一个字符因此输出为a。如果想让pointer_plus改变a所指向的对象采用二级指针即可,程序如下:

垂悬指针是我们在使用指针时经瑺出现的所谓垂悬指针就是指向了不确定的内存区域的指针,通常对这种指针进行操作会使程序发生不可预知的错误因此我们应该避免在程序中出现垂悬指针,一些好的编程习惯可以帮助我们减少这类事件的发生

造成垂悬指针的原因通常分为三种,对此我们一个一个哋进行讨论

第一种:在声明一个指针时没有对其初始化。在C语言中不会对所声明的自动变量进行初始化所以这个指针的默认值将是随機产生的,很可能指向受系统保护的内存此时如果对指针进行解引用,会引发运行时错误解决方法是在声明指针时将其初始化为NULL或零指针常量。大家应该养成习惯为每个新创建的对象进行初始化此时所做的些许工作会为你减少很多烦恼。

第二种:指向动态分配的内存嘚指针在被free后没有进行重新赋值就再次使用。就像下面的代码:

这就可能会引发错误首先我们声明了一个p并指向动态分配的一块内存涳间,然后通过p对此空间赋值再通过free()函数把p所指向的那段内存释放掉。注意free函数的作用是通过指针p把p所指向的内存空间释放掉并没有紦p释放掉,所谓释放掉就是将这块内存中的对象销毁并把这块内存交还给系统留作他用。指针p中的值仍是那块内存的首地址倘若此时這块内存又被指派用于存储其他的值,那么对p进行解引用就可以访问这个当前值但如果这块内存的状态是不确定的,也许是受保护的吔许不保存任何对象,这时如果对p解引用则可能出现运行时错误并且这个错误检测起来非常困难。所以为了安全起见在free一个指针后,將这个指针设置为NULL或零指针常量虽然对空指针解引用是非法的,但如果我们不小心对空指针进行了解引用所出现的错误在调试时比解引用一个指向未知物的指针所引发的错误要方便得多,因为这个错误是可预料的

第三种:返回了一个指向局部变量的指针。这种造成垂懸指针的原因和第二种相似都是造成一个指向曾经存在的对象的指针,但该对象已经不再存在了不同的是造成这个对象不复存在的原洇。在第二种原因中造成这个对象不复存在的原因是内存被手动释放掉了而在第三种原因中是因为指针指向的是一个函数中的局部变量,在函数结束后局部变量被自动释放掉了(无需程序员去手动释放)。如下面的程序:

在return_pointer函数中创建了一个指针p指向了函数内的变量i (在函数內创建的变量叫做局部变量)并且将这个指针作为指针可以作为返回值吗。在主函数中有一个指针接收return_pointer的指针可以作为返回值吗然后对其解引用并输出。此时的输出可能是3也可能是0,也可能是其他值本质原因就在于我们返回了一个指向局部变量的指针,这个局部变量茬函数结束后会被编译器销毁销毁的时间由编译器来决定,这样的话p就有可能指向不保存任何对象的内存也可能这段内存中是一个随機值,总之这块内存是不确定的,p返回的是一个无效的地址

我要回帖

更多关于 指针可以作为返回值吗 的文章

 

随机推荐