简述
char *str = "abcd"
先在静态区为”hello”常量分配5Byte,接着在栈里为指针str分配4Byte(32位机器)并指向”abcd”字串的首地址,因此此时str是指向第一个字符‘a’的一个指针。
char str[ ] = "abcd"
在栈里分配连续的5Byte,内容为’a’,’b’,’c’,’d’,’\0’,并把首地址标记为str,此时str是数组名,同时也是指向数组第一个字符‘a’的指针常量。
可见二者并不相同:
示例程序
/*************************************************************************
> File Name: 3.c
> Author: GatieMe
> Mail: gatieme@163.com
> Created Time: 2015年09月24日 星期四 19时22分53秒
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *pstr = "abcd";
// 指针pstr的地址(在栈中)跟pstr所指向的字符串(静态常量区)的地址不同
printf("指针pstr地址%p, 字符常量\"abcd\"的地址%p\n\n", &pstr, pstr);
printf("pstr是指向字符常量%s首字符的指针\n\n", pstr);
// -Wsequence-point
// 由于Linux下C语言参数入栈时从右往左依次入栈, 因此++pstr = "bcd", 然后pstr = "bcd"
// 关于下面这条语句的执行情况,不同的系统可能执行情况不同...
printf("pstr可以修改其指向%s和%s\n\n", pstr, ++pstr);
// 总结 char *pstr = "abcd";
// pstr -=> char *
// *pstr -=> char
// &pstr -=> char **
printf("%s %c %p\n\n", (char *)pstr, (char)*pstr, (char **)&pstr);
char cstr[ ] = "abcd";
// cstr作为数组名, 它的地址与字符串的首地址相同
// cstr是指向字符串\"abcd\"数组的数组名, 它的地址就是
// 而且我们很明显发现,cstr的地址与pstr指针的地址临近,同在栈区
printf("指针常量cstr的地址%p, 字符串%s == %s的地址%p\n\n", &cstr, cstr, cstr, cstr);
// cstr本身是一个常量,不能修改其指向
// cstr++; // error: lvalue required as increment operand
// 总结 char cstr[] = "abcd";
// cstr -=> char *
// *cstr -=> char
// &cstr -=> char (*)[5] 一个指向字符数组的指针
printf("%s %c %p %s\n", (char * const)cstr, (char)*cstr, (char (*)[5])&cstr, (&cstr)[1]);
return EXIT_SUCCESS;
}
总结
读/写 能力
char *str = “abcd”; 此时”abcd”存放在常量区。通过指针只可以访问字符串常量,而不可以改变它,但是指针可以修改其指向的字符串
而char str[20] = “abcd”; 此时 “abcd”存放在栈。可以通过指针去访问和修改数组内容。
赋值以及初始化时刻
char *str = “abcd”; 是在编译时就确定了(因为为常量)。
而char str[20] = “abcd”; 在运行时确定
存取效率
char *str = “abcd”; 存于静态存储区。在栈上的数组比指针所指向字符串快。因此慢
而char str[20] = “abcd”; 存于栈上。快
变量类型
对于char *pstr = "abcd"
char *pstr = "abcd";
pstr -=> char *
*pstr -=> char
&pstr -=> char **
对于char cstr[] = "abcd"
char cstr[] = "abcd";
cstr -=> char *
*cstr -=> char
&cstr -=> char (*)[5] 一个指向字符数组的指针