一直在看指针的资料,今天实践了一次字符串指针的操作,做一个简单的总结。
代码如下,:
char * x = "abcd"; //声明一个字符类型的指针x 指向一个字符串
需要特别注意的地方为:
1、指针类型为char ,指针的类型决定了这个指针指向数据的类型;
2、指针变量 x 自身是有变量地址的,也就是说 x 变量作为一个变量,有自己的内存地址。
那么,这里的赋值语句可以理解为 指针变量x的内存地址上存储了一个字符类型的地址。
这个可以通过以下代码得出结果:
printf("%p \n",x);
printf("%p \n",&x);
程序运行后,应该是输出两个不同的地址,一个是x变量存储的值得地址,第二行是x变量自身的地址;
3、字符型指针虽然指向了一个字符串的地址,但是其存储的只是这个字符串的开始地址,也就是字符串 “abcd” 里面首字母 "a" 这个字符的内存地址,并不能直接通过指针修改整个字符串的数据,需要通过指针运算来读取和修改每一个字符串内的元素,我就是犯了这个毛病,感叹脚本语言太方便了,代码如下:
char * x = "abcd";
char * z = "1234";
*x = *z ; //不合法
*x = 3; //不合法
释疑:
双引号括起来的字符串是字符串字面量(string literal),是静态对象(存储在内存区域的文字常量区,是无法被修改的),因此从语义上来说,指针指向它之后字符串内容自然不可修改。虽然不可被更改,但它是左值(lvalue),用&取地址还是可行的(结果是地址常量)。在C中它的类型是char[],不是常量(在C++中类型是char const[],是常量)。修改字符串字面量的字符从而改变字符串字面量,结果是未定义(Undefined)的,行为不可预料,应该避免使用。
如果要修改的话,只有用指针指向可以修改的字符串,例如字符数组。
要实现所说的功能,可以这样:
char *p=malloc(sizeof("this is a program"));
strcpy(p,"this is a program");
代替第一行即可。
或者也可以用非ANSI C的库函数:
char *p=strdup("this is a program");
这样,p指向的内存单元是可修改的堆空间。
TIPS: malloc 的内存 开辟在堆区,所以是可以被修改的,字符数组的初始化,看似是字符串常量,实际在内存中,这个数组所指向的地址是这个字符串常量的拷贝,而不是在字符串常量的静态区域中,所以字符串数组可以修改自身存储的字符串内容而指向字符串常量的指针无法修改字符串内容。
参考资料: