当前位置:首页 > 时尚美妆 > C/C++ 指针函数返回值的一些问题

C/C++ 指针函数返回值的一些问题

1。指针功能

指针也是C语言中的一种数据类型,所以函数的返回值肯定可以是指针类型。
返回指针的函数的一般形式为: 类型名称 * 函数名称(参数列表)

1.1 示例 1

#包括
#包括
使用命名空间 std;char *returnStr()
{char* p = "tigerjibo";return p;
}
int main()
{char* str;str = returnStr();//str[0] = 'T'; //会导致错误,只读数据段中的内容无法修改 printf("%s\n", str);system("pause");return 0;
}

我们来分析一下程序。

(1) char *p = "tigerjibo"。系统在堆栈上分配四个字节的空间来存储p的值。 “tigerjibo”是字符常量,存储在只读数据段中。指向后,系统将“tigerjibo的地址分配给p

(2) 该函数使用 return 返回值p 。该值指向只读数据段(该数据段中的数据是静态的,不会改变)。退出子函数后,系统破坏p的值。但是p的值已经通过return返回了。并且只读数据段中的内容不会被修改和回收(在静态区丢失)

(3) 在主程序中再次将地址赋给str。所以str指向“tigerjbo”。

(4) 这个程序虽然可以运行,但是还有一个缺点,就是字符串常量中的值不能在程序中修改。修改会导致段错误。


1.2 示例 2

#include
char *returnStr(){char p[]=”tigerjibo”;return p;
}
int main()
{char *str;str =returStr();printf(“%s\n”,str);
}
程序编译完成后,系统会提示如下警告:
函数返回局部变量的地址
(函数返回变量地址)
此错误分析:
1>“tigerjibo”是一个字符常量,存储在只读数据中段,无法修改。
2>char p[],是一个局部变量。调用该函数时,会在堆栈上开辟一个空间来存储数组p的内容。
3>char p[]=”tigerjibo”, 该语句将“tigerjibo”的值赋给值p,并将其存储在数组p的地址处。而不是将“tigerjibo”的地址分配给数组p。因此,“tigerjibo”此时在系统中有一份备份,一份在只读数据段(无法修改,内容不会被回收),一份存放在堆栈上(其内容可以修改,但函数退出后,其内容不会被回收)。栈中存储的内容也会被回收)。
4> 因此,return p时,返回的是数组的首地址,但是当函数退出时,栈上的内容也会被丢弃,局部变量的内存为也清零了,所以数组首地址的内容就是一个变量值。

1.3 示例 3

#include
char *returnStr()
{static char p[]="tigerjibo";return p;
}
int main()
{char *str;str =returnStr();str[0] = 'T';printf("%s\n", str);}
该程序运行正确。
分析如下:
1>“tigerjibo”是一个字符常量,存储在只读数据段中,不能修改。
2>static char p[],它是一个静态局部变量,在读写数据段中为p开辟一个空间来存储其值。
3>static char p[]=”tigerjibo”,该语句将”tigerjibo”的值赋给值p存储在数组p的地址处。而不是将“tigerjibo”的地址分配给数组p。因此,“tigerjibo”此时在系统中有一份备份,一份在只读数据段(不可修改,内容不会回收),一份存放在读写数据段(其内容可以修改,并且当函数退出后,因为保存在读写数据段中,所以内容不会被丢弃)。
4> 因此,return p时,返回的是数组的首地址,但是当函数退出时,虽然栈上的内容被清空了,但是p地址在数据区地址的内容不会被回收。

1.4 示例 4

#include
#include
#包括
无效获取内存(字符* p)
{p = (char *)malloc(100);
}
int main()
{char *str=NULL;getmemory(str);strcpy(str,"helloworld");printf("%s\n",str);}
编译后出错:
段错误

分析:主程序中str地址为空。在函数传递中,将str的地址传递给子函数中的指针p(复制了的副本),然后在子函数中, p在中给定,在上申请100字节空间,并将首地址分配给p。但在函数调用过程中,p值的变化不会影响中str的值到主函数。因此,str的地址仍然是空的。在 strcpy 中引用空指针将导致段错误。

1.1 到 1.4 摘自http://www.chinapulp.net/tigerjibo/article/details/7425571

1.5示例 5


//将字符串str中的小写字母转换为大写字母,并返回变化后的字符串
// 注意:这里的参数需要传递字符串变量,不能传递字符串常量
字符 * 上部(字符 *str)
{//先保留初始地址。因为str指向的位置稍后会发生变化。 char *dest = str; // 如果还不是空字符 (*str != '\0') {// 如果是小写字母 if (*str >= 'a' && *str <= 'z') { //更改为大写字母。小写字母和大写字母的ASCII值有固定差异 *str -= 'a' - 'A';}//遍历下一个字符 str++;}//返回字符串 return dest;
}我就不详细解释
里面的代码了,重点关注第2行的定义形式。
调用这个函数也很简单:

int main()
{// 定义字符串变量 char str[] = "lmj"; // 调用函数 char *dest = upper(str); printf("%s", 目标);返回0;
}
输出结果:LMJ

以上摘自:http://www.chinapulp.net/mjios/archive/2013/03/19/2967037.html

1.5 示例 5

char *returnStr1(const char* instr)
{char* temp = const_cast(instr);char *outstr = new char[strlen(temp) + 1];memcpy(outstr, temp, strlen(temp) + 1);outstr[0] = 'E' ;返回输出;
}int main()
{char *str;char in_main[100];cin.getline(in_main, 100);str = returnStr1(in_main);printf("%s\n", str);删除(str);str = NULL;system( “暂停”);
}



程序补全功能:对于输入字符串,第一个字符修改为E,如果指针函数中使用new,则在堆中分配内存空间,返回给主函数,不一致一般程序以标准化方式编写。另外,main函数中的str在声明时并没有初始化,这也是不符合规范的。
为了避免程序中内存泄漏,必须保证对new生成的每个指针都调用delete(同理,对malloc生成的指针调用free)。删除只能在子函数之外使用。如果程序员忘记释放内存,很容易造成内存泄漏! !
第 31 条:永远不要返回对函数内部使用 new 初始化的本地对象或指针的引用






2。函数指针



未完成




发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。