char * 和char[]的区别

如下代码块
char pngPath[10]; 在下面的sprintf函数中报错了
但是char *pngPath可以正常运行,就查了一下二者的区别

    for (int i = 0; i < 10; i++) {
//        char pngPath[10]; //报错
        char *pngPath = (char *)malloc(sizeof(char) * 10);//正常运行
        //拼接字符串 int sprintf(char *str, const char *format, ...) 发送格式化输出到 str 所指向的字符串
        sprintf(pngPath, "pic/d%d.png", i);
        name = env->NewStringUTF(pngPath);
        digitTexId[i] = env->CallStaticIntMethod(cl, id, obj, name);
    }

以下是从网络上找来的异同点

相同点

1. 首先 这两种类型都可以对应一个字符串,比如:

char * a="string1"; 
char b[]="string2"; 
printf("a=%s, b=%s", a, b); 

其中a是一个指向char变量的指针,b则是一个char数组(字符数组),

2. 其次 ,很多时候二者可以混用,像函数传参数的时候,实参可以是char*,形参可以是 char[],比如:

void fun1(char b[])
{
    printf("%s", b);
}
int main()
{
    char *a = "HellowWorld";
    fun1(a);
}

反过来,实参可以是char[],形参可以是 char *也是可以的。
存在即合理,char *和char[]肯定是有本质的不同。

不同点

1. char*是变量,值可以改变, char[]是常量,值不能改变。

比如:

char * a="string1"; 
char b[]="string2"; 
a=b; //OK 
a="string3"; //OK 
b=a; //报错!左边操作数只读 
b="string3" //报错!左边操作数只读

解释: a是一个char型指针变量,其值(指向)可以改变;
b是一个char型数组的名字,也是该数组首元素的地址,是常量,其值不可以改变 。

2. char[]对应的内存区域总是可写,char*指向的区域有时可写,有时只读

比如:

char * a="string1"; 
char b[]="string2"; 
gets(a); //试图将读入的字符串保存到a指向的区域,运行崩溃! 
gets(b) //OK 

解释: a指向的是一个字符串常量,即指向的内存区域只读;
b始终指向他所代表的数组在内存中的位置,始终可写!
注意,若改成这样gets(a)就合法了:

char * a="string1"; 
char b[]="string2"; 
a=b; //a,b指向同一个区域,注意这里改变了a的指向 
gets(a) //OK 
printf("%s",b) //会出现gets(a)时输入的结果 

解释:a的值变成了是字符数组首地址,即&b[0],该地址指向的区域是char *或者说 char[8],习惯上称该类型为字符数组,其实也可以称之为"字符串变量",区域可读可写。

注意:char *本身是一个字符指针变量,但是它既可以指向字符串常量,又可以指向字符串变量,指向的类型决定了对应的字符串能不能改变。

3. char * 和char[]的初始化操作有着根本区别:

测试代码:

char *a="Hello World"; 
char b[]="Hello World"; 
printf("%s, %d\n","Hello World", "Hello World"); 
printf("%s, %d %d\n", a, a, &a); 
printf("%s, %d %d\n", b, b, &b); 

结果

image

结果可见:尽管都对应了相同的字符串,但"Hellow World"的地址 和 a对应的地址相同,与b指向的地址有较大差异;&a 、&b都是在同一内存区域,且&b==b
根据c内存区域划分知识,我们知道,局部变量都创建在栈区,而常量都创建在文字常量区,显然,a、b都是栈区的变量,但是a指向了常量(字符串常量),b则指向了变量(字符数组),指向了自己(&b==b==&b[0])。

说明以下问题:

char * a="string1";是实现了3个操作:

  1. 声明一个char*变量(也就是声明了一个指向char的指针变量)。
  2. 在内存中的文字常量区中开辟了一个空间存储字符串常量"string1"。
  3. 返回这个区域的地址,作为值,赋给这个字符指针变量a

最终的结果:指针变量a指向了这一个字符串常量"string1"(注意,如果这时候我们再执行:char * c="string1";则,c==a,实际上,只会执行上述步骤的1和3,因为这个常量已经在内存中创建)

char b[]="string2";则是实现了2个操作:

  1. 声明一个char 的数组,
  2. 为该数组"赋值",即将"string2"的每一个字符分别赋值给数组的每一个元素,存储在栈上。

最终的结果:"数组的值"(注意不是b的值)等于"string2",而不是b指向一个字符串常量

PS:
实际上, char * a="string1"; 的写法是不规范的!
因为a指向了即字符常量,一旦strcpy(a,"string2")就糟糕了,试图向只读的内存区域写入,程序会崩溃的!尽管VS下的编译器不会警告,但如果你使用了语法严谨的Linux下的C编译器GCC,或者在windows下使用MinGW编译器就会得到警告。

所以,我们还是应当按照"类型相同赋值"的原则来写代码: const char * a="string1";
保证意外赋值语句不会通过编译。

小结

对于
const char * a="string1"
char b[]="string2";

  1. a是const char 类型, b是char const类型
    ( 或者理解为 (const char)xx 和 char (const xx) )

  2. a是一个指针变量,a的值(指向)是可以改变的,但a只能指向(字符串)常量,指向的区域的内容不可改变;

  3. b是一个指针常量,b的值(指向)不能变;但b指向的目标(数组b在内存中的区域)的内容是可变的

  4. 作为函数的声明的参数的时候,char []是被当做char *来处理的!两种形参声明写法完全等效!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269