解析char *p与char p[]

 见论坛上有人讨论这个问题,感觉也是涉及面比较广,而且很多人犯过这个错误,比如声明char *p = "hello world!";却妄图用p指针改变字符串内容,所以就这个问题,我总结了一下。转载注明作者Logic0以及出处。

主要解析的问题:

问题1:
#include "stdio.h"
char *get_string_1()
{
    char p[] = "hello world!";
    return p;
}
char *get_string_2()
{
    char *p = "hello world!";
    return p;
}
int main()
{
    char *p;
    p = get_string_1();
    printf("get_string_1:%s\n",p);
    p = get_string_2();
    printf("get_string_2:%s\n",p);
    return 0;
}
输出:
get_string_1:(乱码或者没有输出),linux下没有任何输出
get_string_2:hello world!
为什么会这样?

问题2:
char *p = "hello world!";这样写到底合不合法,实际应用中能不能这样写。

问题3:
char *p = "hello world!";与char p[]="hello world!";有什么细节和操作上的差异。

解析:
       char *p = "hello world!";与char p[] = "hello world!"; 两者都用来声明一个字符串,并将其初始化为hello world!,但是表示的意义确是大不相同。
       从其声明的对象来说:
       char p[] = "hello world!";用来声明一个数组p,数组大小为12字节。
       char *p = "hello world!";用来声明一个指针p,指向“hello world!”字符串起始位置。
       从存储位置来说:
       char p[] = "hello world!";p数组作为局部变量被存储在栈区;
       char *p = "hello world!"; 在这个声明中,"hello world!"被存储在静态数据区,而且是全局的,p仅仅就是个指针,指向这个区域。不信的话你可以试试下边的代码,看是不是同一个地址:
       char *p1 = "hello world!"; 
       char *p2 = "hello world!"; 
       printf("p1:%x\np2:%x\n",p1,p2);
       从函数执行后的扫尾工作来看:
       C函数执行完之后对栈区进行清除操作,对静态数据区和堆则没有,因此第一个问题也就不难解释了,get_string_1()函数执行完就释放了栈区内存,所以根本就不存在存有"hello world!"声明时的内存,也就不可能有所输出。

        那么,写成char *p = "hello world!";到底合不合法呢?能不能这样写呢?
        这是一个历史问题,在const关键字被引入C语言之前,这样写是合法的,而且存在了很长的一段时间,大量的代码在此期间运用了这种写法,新版C语言为了兼容,故允许这样写,但最好不要这样,因为这种写法终会被淘汰,说不定哪天你的代码用了新版的编译器,然后莫名的出了问题,要找这个BUG估计不是一件容易的事。现在最好写成:
        const char *p = "hello world!";
        或者
        char p[] = "hello world!";
        那他们在操作和细节上有什么区别呢?
        区别很多,由于本人才疏学浅,只总结出以下几点,忘有知者补充:
        1. char *p = "hello world!"; 可以用p++操作,sizeof(p) == 4;

        2.char p[]="hello world!"; sizeof(p) == 12;

http://www.cnblogs.com/Logic0/archive/2009/08/01/1850337.html


<think>好的,我现在需要回答用户关于C/C++中指针声明时空格位置对含义的问题,特别是char* p和char * p的区别。首先,我得确认自己对这个问题是否理解正确。用户提到的两种写法,char* p和char * p,它们的区别在哪里呢?我记得在C和C++中,指针的声明语法可能会有不同的写法,但具体是否有语义上的差异呢? 首先,我应该回顾一下C/C++的语法规则。在声明指针变量时,通常的语法是将星号(*)放在类型名旁边,或者靠近变量名。例如,char* p和char *p,或者char * p。根据我所学的知识,这里的空格位置其实并不影响编译器的解释,只是代码风格的问题。也就是说,无论是char* p还是char * p,编译器都会将它们视为声明一个指向char类型的指针变量p。 不过,可能用户会有疑问,比如当声明多个变量的时候,是否会有不同的效果。例如,char* p, q;这种情况下,p是指针,而q是char类型的变量。这时候,星号的位置是否会影响变量的类型呢?是的,如果写成char *p, q;,那么p是指针,q是char。而如果写成char* p, q;,同样,只有p是指针,q还是char。这说明,星号实际上是属于变量名的,而不是类型的一部分。因此,在声明多个变量时,需要为每个指针变量单独加上星号。 接下来,我需要确认这种理解是否正确。查阅相关资料,比如C++ Primer中的说明,指针声明的语法确实要求每个变量名前都要有星号。因此,char* p, q;这种写法容易让人误解,以为q也是指针,但实际上不是。所以,为了代码清晰,建议每个指针单独声明,或者将星号紧贴变量名,如char *p, *q;,这样更明确。 然后,用户的问题中还提到了用户提供的引用内容,比如引用[1]中的char *p=s2; p[0]='x';,这说明指针p被声明为char*类型,可以修改指向的内容。而引用[2]和[3]涉及到char*其他类型的转换,进一步说明指针的使用方式。但这些引用内容可能和指针声明时的空格问题关联不大,但用户可能希望了解不同写法是否影响指针的行为。比如,char* p和char *p是否会导致不同的行为,答案是不会,只是风格差异。 不过,我需要确保自己的回答正确无误,是否有例外情况。例如,在函数返回类型或参数列表中,星号的位置是否有影响?比如,函数声明如char* func()和char *func(),实际上是一样的,但前者可能让人误解返回类型是char指针,而后者更明确函数名是func。不过,编译器处理时,仍然会将它们视为返回char指针的函数。 此外,用户可能还会混淆指针类型和const关键字的结合使用。例如,const char* p和char const* p是否相同,而char* const p则不同。但这里的空格位置是否会影响这些声明呢?答案是否,因为const的位置决定了指向的内容还是指针本身是常量,而空格不影响解析。 总结来说,用户的问题核心在于指针声明中的空格位置是否改变语义,答案是否定的,只是代码风格的差异。但需要注意在声明多个变量时,星号需要紧贴变量名以避免误解。这需要我在回答中明确说明,并给出示例,帮助用户理解不同写法的影响。 最后,根据用户的要求,生成相关问题。比如,指针声明中的const位置的影响,或者多变量声明时的注意事项,这些都可能成为相关的问题。</think>在C/C++中,`char* p`和`char *p`的语法含义完全一致,空格位置仅影响代码可读性,不改变程序行为。以下从多个角度分析: ### 1. 语法解析规则 编译器将`char*`视为类型修饰符,变量名无关。两种写法均声明一个指向`char`类型的指针变量`p`: - `char* p`:强调`p`的类型是`char*` - `char *p`:强调`*p`的结果是`char`类型 例如: ```cpp char* p1; // p1是char*类型 char *p2; // p2同样是char*类型 ``` ### 2. 多变量声明的陷阱 声明多个变量时,`*`需紧贴变量名以避免歧义: ```cpp char* p, q; // p是char*类型,q是char类型(易误解) char *p, *q; // 明确p和q均为char*类型 ``` 此时`char* p, q`的写法容易导致`q`被误认为指针,而实际它是`char`类型[^1]。 ### 3. 代码风格建议 - **类型关联风格**:`char* p`更直观体现变量类型,常用于面向对象编程 - **符号关联风格**:`char *p`符合C语言传统,强调操作符`*`的作用 - **函数参数返回值**: ```cpp char* func1(); // 返回char*类型 char *func2(); // 同上,风格差异 void func3(char* p1, int* p2); // 参数类型明确 ``` ### 4. 特殊场景扩展 - **`const`结合**:空格位置不影响`const`的修饰对象 ```cpp const char* p; // 指向常量字符(内容不可改) char* const p; // 常量指针(地址不可改) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值