字符指针和字符数组的区别,

zyx_cambridge 发布于 2013/03/26 18:45
阅读 377
收藏 1

@stxy0509 你好,想跟你请教个问题:

 

char *p1 = "hello";

char p2[] = "hello";

区别是什么? p1,p2 存储在什么地方?

 

谢谢了

加载中
0
stxy0509
stxy0509

1 ---------------------------------------------------------------

p1所指向的字符串"hello",是编译器自动分配空间的,存放在全局数据空间,一般是不可以修改的,只可访问其内容;

如你在定义char *p1 = "hello";后使用*p1 = 'x'是不可以的;

p2代表了一个数组,分配了6个字节(包括结尾的0),数组中的内容你可以修改,但数组的元素个数是固定的(编译器根据你赋值的元素个数确定的)。实际上p2 = 

{

    'h','e','l','l','o','\0'

};

如果你在定义数组时确定了数组元素个数,比如char p2[7] = "hello",那么数组的元素个数以你定义的为准,赋值个数多于元素个数,编译器会警告你,赋值个数少于元素个数,没有明确赋值的将为0.

p2存储在什么地方,取决于你把p2定义在什么位置,如果定义在函数外面,那么它就是一个全局变量,存储在全局数据区;

如果定义在函数里面,那么它就是一个局部变量,存储在堆栈里面,函数返回以后,该变量不再有意义,该变量占用区域也会被别的函数调用使用;

2 ---------------------------------------------------------------------------------

p1是一个指针,指向字符,以后你可以根据需要改变它的值,使其指向其他的位置;

比如你可以让p1 = p2; p1 = p2 + 1;

还可以进行指针算术运算:++p1;--p1; p1+=2 ;p1 -= 3;等等,但运算时需确保其指向有效数据;

p2是一个数组名,目前你可以把一个数组名当成一个常量指针(即不可以改变它的值,比如p2++,p2--).

可以通过p2修改数组中元素的值,比如:

p[0] = 'm';p[3] = 'n';

此时p2指向的数组值为:"melno"

3-------------------------------------------------------------------------------

可能你对全局数据区和堆栈不理解,我稍微解释下。

程序被操作系统调入之后,会占用一定的内存。这个内存又被明确分为几个部分,以明确区分各部分作用,大致分为:

a 代码区:可执行代码就在这部分;(函数定义)

b 数据区:也就是全局数据区,全局变量和静态变量都在这个部分。

这个可能又分为只读区和读写区

c 堆栈区:这个部分是操作系统专门开辟出来供函数调用,参数传递,存储函数内部的自动变量用的。某个函数退出以后,这些区域又要被其他函数使用了。

d 自由区:也就是所谓的堆。归操作系统管理,你可以通过malloc()函数向系统申请使用一定量的这部分内存。使用完以后通过free()还给操作系统;

其实都是内存一部分,只是用途不一样罢了。

0
党玉涛
党玉涛

如果用一句话概括的话,那就是数组p2是个常量,指针p1是个变量。

先说他们共同的使用方法吧

1,都可以使用数组符号:putchar(p1[2]);putchar(p2[2]);

2,都可以使用指针加法:putchar(*(p1+2));putchar(*(p2+2));

区别:

只有指针可以使用自增运算符:

putchar(*(p1++));     ok

putchar(*(p2++));      error

第二个问题,存到什么地方,这个不懂

0
ling0
ling0

p1, p2 都在栈上,p2 是栈上的一个内存块儿,p1 是栈上的一个指针,指向一个静态存储区块。

参见 C 语言中的指针和数组的区别。

0
zyx_cambridge
zyx_cambridge

引用来自“stxy0509”的答案

1 ---------------------------------------------------------------

p1所指向的字符串"hello",是编译器自动分配空间的,存放在全局数据空间,一般是不可以修改的,只可访问其内容;

如你在定义char *p1 = "hello";后使用*p1 = 'x'是不可以的;

p2代表了一个数组,分配了6个字节(包括结尾的0),数组中的内容你可以修改,但数组的元素个数是固定的(编译器根据你赋值的元素个数确定的)。实际上p2 = 

{

    'h','e','l','l','o','\0'

};

如果你在定义数组时确定了数组元素个数,比如char p2[7] = "hello",那么数组的元素个数以你定义的为准,赋值个数多于元素个数,编译器会警告你,赋值个数少于元素个数,没有明确赋值的将为0.

p2存储在什么地方,取决于你把p2定义在什么位置,如果定义在函数外面,那么它就是一个全局变量,存储在全局数据区;

如果定义在函数里面,那么它就是一个局部变量,存储在堆栈里面,函数返回以后,该变量不再有意义,该变量占用区域也会被别的函数调用使用;

2 ---------------------------------------------------------------------------------

p1是一个指针,指向字符,以后你可以根据需要改变它的值,使其指向其他的位置;

比如你可以让p1 = p2; p1 = p2 + 1;

还可以进行指针算术运算:++p1;--p1; p1+=2 ;p1 -= 3;等等,但运算时需确保其指向有效数据;

p2是一个数组名,目前你可以把一个数组名当成一个常量指针(即不可以改变它的值,比如p2++,p2--).

可以通过p2修改数组中元素的值,比如:

p[0] = 'm';p[3] = 'n';

此时p2指向的数组值为:"melno"

3-------------------------------------------------------------------------------

可能你对全局数据区和堆栈不理解,我稍微解释下。

程序被操作系统调入之后,会占用一定的内存。这个内存又被明确分为几个部分,以明确区分各部分作用,大致分为:

a 代码区:可执行代码就在这部分;(函数定义)

b 数据区:也就是全局数据区,全局变量和静态变量都在这个部分。

这个可能又分为只读区和读写区

c 堆栈区:这个部分是操作系统专门开辟出来供函数调用,参数传递,存储函数内部的自动变量用的。某个函数退出以后,这些区域又要被其他函数使用了。

d 自由区:也就是所谓的堆。归操作系统管理,你可以通过malloc()函数向系统申请使用一定量的这部分内存。使用完以后通过free()还给操作系统;

其实都是内存一部分,只是用途不一样罢了。

数组应该是可以进行自加操作吧,c和指针中应该有提及。

还有一个:c和指针中有一个边界对齐的问题:

 

struct A

{

int a;

char b;

};占多大内存?为什么?

如果换成

struct A

{

char b;

 

int a;

};  结果怎样?

 

0
stxy0509
stxy0509

简单说一下:

两个都占8字节.(32位平台下,int是4字节的情况下),64位机器我没有试过。

因为在32位情况下,CPU内部寄存器都是32位的,一次传输4字节相对来说效率最高。所以编译器默认会把一些没有4字节对齐的变量,填充一定字节强制对齐。

当然编译器也提供一些做法或选项,让你可以不用填充这些字节,具体做法记不起来了,因为很少用。

但是有时候编译器会8字节对齐,可能的情况是结构体内部有一个double变量。

具体对齐和填充规则,我只能说我总结不出来。



0
zyx_cambridge
zyx_cambridge

今天有个高手说了一下,是编译器优化的结果,你觉得是不

返回顶部
顶部