开发者社区> 问答> 正文

C中局部变量指针问题

先提问题,在类似如下的函数中:

char *GetMemory(void)
{
   char p[] = "hello world";
   printf("%p\n",p);
   return p;
}
问题1:

printf("%p\n",p); // 对p的有什么影响?请对比GetMemory0和GetMemory1
问题2:

p[1] = 'a';  //这个的先后顺序不同,为啥结果不一样?请对比GetMemory2和GetMemory3
已知见解:
char* p = "hello world";
是一个指向常量区地址的指针。
char p[] = "hello world";
是局部字符串数组,会把"hello world"拷贝到函数栈中.
printf("%p",p)会修改栈的中数据的释放原则?

代码示例:

char *GetMemory0(void)
{
    char p[] = "hello world";
    return p;
}
char *GetMemory1(void)
{
    char p[] = "hello world";
    printf("%p\n",p);
    return p;
}
char *GetMemory2(void)
{
    char p[] = "hello world";
    printf("%p\n",p);
    p[1] = 'a';
    return p;
}
char *GetMemory3(void)
{
    char p[] = "hello world";
    p[1] = 'a';
    printf("%p\n",p);
    return p;
}
char *GetMemory4(void)
{
    char *p = "hello world";
    return p;
}
char *GetMemory5(void)
{
    char *p = "hello world";
    printf("%p\n",p);
    return p;
}
int main()
{
    char *str = NULL;
    str = GetMemory0();
    printf(str);
    printf("\n---0---\n");
    str = GetMemory1();
    printf(str);
    printf("\n---1---\n");
    str = GetMemory2();
    printf(str);
    printf("\n---2---\n");
    str = GetMemory3();
    printf(str);
    printf("\n---3---\n");
    str = GetMemory4();
    printf(str);
    printf("\n---4---\n");   
    str = GetMemory5();
    printf(str);
    printf("\n---5---\n");
}
运行结果为:

0(M�
---0---
0x7fff184d2720
hello world
---1---
0x7fff184d2720
hello world
---2---
0x7fff184d2720
hallo world
---3---
hello world
---4---
0x400988
hello world
---5---
编译过程:

g++ --version
g++ (GCC) 4.8.2 20140206 (prerelease)

g++ -Wall -O -g -c test.cpp -o test.o
test.cpp: 在函数‘char* GetMemory0()’中:
test.cpp:4:10: 警告:返回了局部变量的‘p’的地址 [-Wreturn-local-addr]
     char p[] = "hello world";
          ^
test.cpp: 在函数‘char* GetMemory1()’中:
test.cpp:9:10: 警告:返回了局部变量的‘p’的地址 [-Wreturn-local-addr]
     char p[] = "hello world";
          ^
test.cpp: 在函数‘char* GetMemory2()’中:
test.cpp:15:10: 警告:返回了局部变量的‘p’的地址 [-Wreturn-local-addr]
     char p[] = "hello world";
          ^
test.cpp: 在函数‘char* GetMemory3()’中:
test.cpp:22:10: 警告:返回了局部变量的‘p’的地址 [-Wreturn-local-addr]
     char p[] = "hello world";
          ^
test.cpp: 在函数‘char* GetMemory4()’中:
test.cpp:29:15: 警告:不建议使用从字符串常量到‘char*’的转换 [-Wwrite-strings]
     char *p = "hello world";
               ^
test.cpp: 在函数‘char* GetMemory5()’中:
test.cpp:34:15: 警告:不建议使用从字符串常量到‘char*’的转换 [-Wwrite-strings]
     char *p = "hello world";
               ^
g++ -Wall -O -g test.o -o ./test -lpthread  -lstdc++
chmod a+x ./test

展开
收起
a123456678 2016-06-06 16:14:38 2137 0
1 条回答
写回答
取消 提交回答
  • 使用下面的printf,就正常了……
    
    int __printf (const char *format, ...)
    {
      va_list arg;
      int done;
    
      va_start (arg, format);
      done = vfprintf (stdout, format, arg);
      va_end (arg);
    
      return done;
    }
    现在的问题是我自己编译glibc就没问题,用pacman的就有问题,pacman的又不能调试,gdb又不支持汇编单步……
    
    我来大胆猜测一下应该是因为不定传参奇特的压栈方式导致的吧……总之你换上puts的结果在我看来才是比较符合逻辑的。。
    
    我有一个怀疑,可能是因为某个不知名的原因在第一次调用printf的时候,printf会去调用一个类似puts这样的函数,导致参数被破坏?但是为什么同样的glibc的代码,自己写一遍就没有问题了……
    
    对了,问题2和问题3我这里没办法复现
    
    全选复制放进笔记�����
    ---0---
    0x7fffffffe480
    hello world123456789073421
    ---1---
    0x7fffffffe490
    hallo world
    ---2---
    0x7fffffffe490
    hallo world
    ---3---
    hello world
    ---4---
    0x400a38
    hello world
    ---5---
    2019-07-17 19:28:53
    赞同 展开评论 打赏
问答分类:
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载