转载:http://blog.csdn.net/pzhsunxu/article/details/7798365
字符串指针与字符数组的区别
数组和指针都可以在它们的定义中用字符串常量进行初始化,尽管看上去一样,底层的实现机制却不相同。
定义指针时,编译器并不为指针所指向的对象分配空间,它只是分配指针本身的空间。
例如:下面的定义创建了一个字符串常量(为其分配了内存):
char *p=”abcdefg”; //”abcdefg”存储在静态常量区,p指向该”abcdefg”,即是p保存的是”abcdefg”在常量区的地址。
注意只有对字符串常量才是如此,不能指望为浮点数之类的常量分配空间,如:
Float *p=3.14;
由字符串常量初始化的数组是可以修改的。其中的单个字符在以后可以改变。
例如:
#include <stdio.h>
void fun(char *p)
{
printf("-----%p\n",p);
p[0]='s';
puts(p);
}
int main()
{
char a[]="123";
char *p="123";
char *q="123";
printf("a===%p\n",a); //a===0xbfdda00c %p表示输出a的地址
printf("p===%p\n",p); //p===0x8048839
printf("q===%p\n",q); //q===0x8048839
// fun("hello"); //-----0x8048855 // p[0]='s';错误 说明存储在静态常量区
// fun(a); //-----0xbfdda00c // 输出:s12 说明存储在栈中
fun(p); //-----0x8048839 // p[0]='s';错误 说明存储在静态常量区
return 0;
}
综上所述:
<1> 初始化的字符串数组存储在栈中,可以改变其值。
<2> 初始化的字符串常量指针存储在静态常量区,不能修改其值。
<3> 字符串作为实参传递存储在静态常量区。
<4> 程序段和代码段的起始地址0x08048000.
====================================================================================
数组要么在静态存储区被创建(如全局数组,指针数组),要么在栈上被创建(字符串数组)。指针可以随时指向任意类型的内存块。
(1) 修改内容上的差别
char a[] = "hello";
a[0] = 'X';
char *p- = "world"; //注意p指向常量字符串
p[0] = 'X'; //编译器不能发现该错误,运行时错误
(2) 用运算符sizeof可以计算出数组的容量(字节数)。sizeof(p),p为指针得到的是一个指针变量的字节数,而不是p所指的内存容量。C++/C语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。
char a[] = "hello world";
char *p = a;
printf("%d ",sizeof(a)); //12字节
printf("%d ",sizeof(p)); //4字节
计算数组和指针的内存容量
void func(char a[100]) {
printf("%d ",sizeof(a)); //4字节而不是100字节 说明函数的数组参数都是看做指针
}
sizeof 指针 数组
-------------------------------------------
char p[]; // 编译不过
char p[0]; // sizeof(p) = 0
char p[8]; // sizeof(p) = 8
char * p = malloc (10); // sizeof(p) = 4
用运算符sizeof可以计算出数组的容量(字节数),但是计算不出指针指向空间的容量,只能计算出指针变量的空间容量(4字节)
指针就是指针,成不了数组
----------------------------------------------
在C语言中,我们没有办法可以将一个数组作为函数参数直接传递。如果我们使用数组名作为参数,那么数组名会立即被转换为指向该数组第1个元素的指针。例如,下面的语句:
char hello[] = "hello";
声明了hello是一个字符数组。如果将该数组作为参数传递给一个函数,
printf ("%s\n", hello);
实际上与将该数组第1个元素的地址作为参数传递给函数的作用完全等效,即:
printf ("%s\n", &hello[0]);
因此,将数组作为函数参数毫无意义。所以,C语言中会自动地将作为参数的数组声明转换为相应的指针声明。也就是说,像这样的写法:
int strlen (char s[])
{
...
}
与下面的写法完全相同:
int strlen (char *s)
{
...
}