字符数组名可以等价于字符指针吗?

lizh1009 2019-08-22 03:56:58

#include <stdio.h>
char *func1()
{
char a[] = "abc";
printf("a = %p\n", a);
return a;
}
char *func2()
{
char *a = "abc";
printf("a = %p\n", a);
return a;
}
int main()
{
printf("func1 return %p\n", func1());
printf("func2 return %p\n", func2());

return 0;
}


我记得字符数组的值就是一个指针,上面程序func1编译的时候就有警告,”返回本地变量的地址“。执行时func1返回值为nil。

两个函数中,a的值都是常量"abc"的地址啊,为什么func2编译的时候不会警告呢?

...全文
3263 44 打赏 收藏 转发到动态 举报
写回复
用AI写文章
44 条回复
切换为时间正序
请发表友善的回复…
发表回复
luj_1768 2020-12-09
  • 打赏
  • 举报
回复
对于指针和数组,一般情况下,满秩矩阵使用数组表达,定长一维数组使用数组表达,稀疏矩阵和变长一维数组使用指针表达。但是,因为内存分配的实际情况是:内存块一旦分配了就很难以调整其长度,内存块增长的解决方案很难同时支持多种策略。所以,除了稀疏矩阵大多选择使用指针表达(有时为了保证运行速度也有使用数组的时候)外,使用指针和使用数组是完全一样的(区别在于编程习惯)。当然,指针相对于数组要灵活得多,但也更难于掌握和管控。所以,一些公司选择了进一步加强指针,另一些则选择了放弃指针而使用引用来弥补编程中对于指针功能的需求。在编程中,使用数组声明,而不加声明地使用指针访问数据,是允许的;反之亦然。
前行one 2019-09-02
  • 打赏
  • 举报
回复
数组里面什么都不用填哪?
come119on 2019-08-27
  • 打赏
  • 举报
回复
你要明白编译器是怎么编译的,const char* a= “abc”;“abc”是存放在附加断中的,a指向这个地址, char a[] ="abc", a是存储在栈中的,a重新构造=“abc”,函数结束,栈释放,返回值就成野指针了
O0o丶Or n0t 2019-08-27
  • 打赏
  • 举报
回复
fun2()数组这样写没有名字,a的值是数组的地址。
DGcolo 2019-08-26
  • 打赏
  • 举报
回复
崩溃那行本来就不应该那么写吧,要改值func2() *a = 'X';
zznyeren 2019-08-26
  • 打赏
  • 举报
回复
谢谢UP主分享
xiaofeixia66 2019-08-26
  • 打赏
  • 举报
回复
样 a b是同一个地址
  • 打赏
  • 举报
回复
指针是真的难,写了这么多年的代码,现在看到指针还是有点晕。
7.83Hz 2019-08-25
  • 打赏
  • 举报
回复
正视一下,发现有些小兄弟底子比我还薄,和原问题无关! 1:字符数组名 a,不是字符指针!!数组和指针毫无关系。 2:强调,虽然可以用指针方式访问数组元素,也可以用数组下标符号访问字符指针指向的元素。但,无关系,我家绝对不等于你家,虽然互打电话,这只是访问方式而已。 3:双引号“ ”的作用,为数据开辟内存空间,存放,提取地址,赋予等号左值。 4:数组名a所存地址不可改,如a=&p,错的。 5:指针名a所存地址可改,如a=&p,可以,常用。
u94586813 2019-08-25
  • 打赏
  • 举报
回复
func1中a是局部变量,函数调用结束a会被释放的,不应该再使用此地址,所以会告警。
ouyang035 2019-08-25
  • 打赏
  • 举报
回复
看了各位的回答,学习了
双杯献酒 2019-08-24
  • 打赏
  • 举报
回复
就好比你买了一个汽车, 说明书上说最高时速200,
如果你到公路上去跑200. 就会收到罚单.
这并不是说这个汽车跑不到200, 而是其他条件限制了.

如果你到赛车场里面, 就可以直接按最高时速飙了,
但是实际上还是受你的驾驶水平限制.

所有的"可以", 都是指在其他方面满足的情况下才可以.
super_admi 2019-08-24
  • 打赏
  • 举报
回复
语法上没有规定说不能返回局部变量地址,所以没有报错(但如果你把警告等级调高,就不一定只是警告了……)
实际应用当然会有问题,函数返回后,之前的局部变量会被回收,所以,如果你再想用它,天知道里面是什么东西……也许你运气好,之前的值还在呢……
这就好比法律并没有规定我不能开超跑,但问题是,我没有超跑。不过,也许我运气好,能继承某个富豪的千亿元遗产呢?

引用 32 楼 iicup 的回复:
既然只是警告, 就说明是可以的.
只不过这种用法有其他问题.
luj_1768 2019-08-24
  • 打赏
  • 举报
回复
两个用法严格地讲没有什么不同。警告是因为侵犯了服务器安全,使服务器有可能受到攻击和破坏。你甚至可以用第一个声名,然后用第二个使用数据;或者反过来。
双杯献酒 2019-08-24
  • 打赏
  • 举报
回复
既然只是警告, 就说明是可以的.
只不过这种用法有其他问题.

jSORoROWy 2019-08-23
  • 打赏
  • 举报
回复
引用 27 楼 jSORoROWy 的回复:
char* a = "abc"; char* b = "abc"; 这样 a b是同一个地址 char a[] = "abc"; char b[] = "abc"; 这样 a b是不同地址 所以前者返回了还能指回"abc",后者返回了就指向一个野指针了
上面说错了,应该是有概率a b指向同一个地址,因为这个abc是存在data段的 而a[]存的abc是在栈段的,调用结束就没了
jSORoROWy 2019-08-23
  • 打赏
  • 举报
回复
char* a = "abc"; char* b = "abc"; 这样 a b是同一个地址 char a[] = "abc"; char b[] = "abc"; 这样 a b是不同地址 所以前者返回了还能指回"abc",后者返回了就指向一个野指针了
jSORoROWy 2019-08-23
  • 打赏
  • 举报
回复
一个指向局部变量,return了就没了,再访问有概率崩,一个是指向常量,这个return了之后你还能再访问他
赵4老师 2019-08-23
  • 打赏
  • 举报
回复
理解讨论之前请先学会如何观察
//char (*(*x[3])())[5];//x是什么类型的变量?
//
//分析C语言声明,关键是搞清楚这个变量是个什么东西(函数、指针、数组),
//是函数那么剩下的就是他的参数和返回值,
//是指针那剩下部分是说明他指向什么,
//是数组剩下的部分就是说明数组的成员是什么类型。
//解析C语言声明规则:
//从左侧第一个标识符开始,按照优先级进行结合。*表示是..的指针,const表示只读的,volatile表示可变的,[]表示是数组,()表示是函数。
//
//x和[3]结合说明是一个大小为3的数组,该数组的每个元素为一类指针,该类指针指向一类函数,该类函数无参数,返回一类指针,该类指针指向一个大小为5的char型数组
#include <stdio.h>
#include <typeinfo.h>
char num[5];
char (*x00())[5] {
    return #
}
int main() {
    char (*(*x[3])())[5];//是个数组,大小为3
    char (*(*x0  )())[5];//数组的元素,是个函数指针
    char (*( x00 )())[5];//函数原型,参数为空,返回值为指针
    char (*  x000   )[5];//返回值

    x0 = x00;
    x[0] = x0;
    x[1] = x0;
    x[2] = x0;
    printf("typeid(x).name() is %s\n",typeid(x).name());
    return 0;
}
//typeid(x).name() is char (* (__cdecl**)(void))[5]
不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!
qq_36926873 2019-08-23
  • 打赏
  • 举报
回复
原理上并不是完全等价的,因为数字名师首地址而指针是指向首地址,一个是地址一个是链接从原理上这两个就不是一个东西,但是在学习时当成对等的也无妨,因为指针指向的就是首地址所以也大体可以代表首地址。
加载更多回复(25)

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧