区别: 1, 字符数组由若干个元素组成, 每个元素中放一个字符, 而字符指针变量中存放的是地址(字符串第一个字符的地址).
2, 赋值方式. 对字符数组只能对各个元素赋值, 不能用以下方法对字符数组赋值: char str[20]; str="I love China"; 而对字符指针变量, 可以用如下方法赋值: char *a; a="I love China"; 注意, 赋值给 a 的不是字符, 而是字符串的第一个元素的地址.
3, 对字符指针变量赋初值: char *a="I love China"; 等价于 char*a; a="I love China"; 而对数组的初始化: char a[20]={"I love China"}; 不能等价于: char str[20];str[]="I love China";
4, 如果定义了一个字符数组, 在编译时为它们分配内存单元, 它有确定的地址. 而定义一个字符指针变量时, 给指针变量分配内存单元, 在其中可放一个字符指针变量的地址. 也就是说, 该指针变量可以指向一个字符型数据, 但若未对它赋予一个地址值, 则它未具体指向一个确定的字符数据. 例: char str[10]; sanf("%s",str); 合法. 但: char *a; scanf("%s",a); 有时也可执行, 但风险较大.
5, 指针变量的值是可以改变的, 例:
- #include <stdafx.h>
- #include<stdio.h>
- void main()
- {
- char *a="Hello word";
- a+=4;
- printf("%s\n",a);
- }
注: 指针变量的值 (即地址) 可以改变, 但指针指向的值无法改变.
6, 若定义了一个指针变量, 并使它指向一个字符串, 就可以用下标形式引用指针变量所指的字符串中的字符.
例:
- #include <stdafx.h>
- #include<stdio.h>
- void main()
- {
- char *a="Hello word";
- int i=0;
- for(;a[i]!='\0';i++)
- {printf("%c",a[i]);
- }
- }
7, 在内存中的储存位置不同.
例:
- #include <stdafx.h>
- #include<stdio.h>
- void main()
- {
- void copy_string(char*from,char*to);
- char*a="Hello word";
- char*b="I love China";
- printf("%s\n%s\n",a,b);
- copy_string(a,b);
- printf("%s\n%s\n",a,b);
- }
- void copy_string(char*from,char*to)
- {
- for(;*from!='\0';from++,to++;)
- {
- *to=*from;
- }
- *to='\0';
- }
会出错,
程序中的 "I love China" 字符串在常量区, 而使用指针存放字符串, b 中只是存放了字符串在常量区中的地址, 当调用 copy_string 函数的时候又引用了 b 这个参数, 即试图将字符串 "I am a teacher." 写入常量区. 而常量区的这段内存是不可写的, 所以在运行的时候出现了报错.
对这段代码的改进只许把 b 改为用数组来存放字符串(对 a 不必修改, 因为程序中没有执行对 a 写入的操作).
char *b = "You are a student.";
改为
char b[] = "You are a student.";
一般认为在 c 中分为这几个存储区:
1. 栈 -- 有编译器自动分配释放
2. 堆 -- 一般由程序员分配释放, 若程序员不释放, 程序结束时可能由 OS 回收
3. 全局区(静态区) -- 全局变量和静态变量的存储是放在一块的, 初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域. 程序结束释放.
4. 另外还有一个专门放常量的地方. 程序结束释放
在函数体中定义的变量通常是在栈上, 用 malloc, calloc, realloc 等分配内存的函数分配得到的就是在堆上. 在所有函数体外定义的是全局量, 加了 static 修饰符后不管在哪里都存放在全局区(静态区), 在所有函数体外定义的 static 变量表示在该文件中有效, 不能 extern 到别的文件用, 在函数体内定义的 static 表示只在该函数体内有效. 另外, 函数中的 "adgfdf" 这样的字符串存放在常量区.
比如:
- int a = 0; // 全局初始化区
- char *p1; // 全局未初始化区
- main() { int b; // 栈
- char s[] = "abc"; // 栈
- char *p2; // 栈
- char *p3 = "123456"; //123456\0 在常量区, p3 在栈上.
- static int c = 0; // 全局 (静态) 初始化区
- p1 = (char *)malloc(10);
- p2 = (char *)malloc(20); // 分配得来得 10 和 20 字节的区域就在堆区.
- strcpy(p1, "123456"); //123456\0 放在常量区, 编译器可能会将它与 p3 所指向的 "123456" 优化成一块. }
还有就是函数调用时会在栈上有一系列的保留现场及传递参数的操作.
栈的空间大小有限定, vc 的缺省是 2M. 栈不够用的情况一般是程序中分配了大量数组和递归函数层次太深. 有一点必须知道, 当一个函数调用完返回后它会释放该函数中所有的栈空间. 栈是由编译器自动管理的, 不用你操心.
堆是动态分配内存的, 并且你可以分配使用很大的内存. 但是用不好会产生内存泄漏. 并且频繁地 malloc 和 free 会产生内存碎片(有点类似磁盘碎片), 因为 c 分配动态内存时是寻找匹配的内存的. 而用栈则不会产生碎片.
在栈上存取数据比通过指针在堆上存取数据快些.
一般大家说的堆栈和栈是一样的, 就是栈(stack), 而说堆时才是堆 heap. 栈是先入后出的, 一般是由高地址向低地址生长.
来源: http://www.bubuko.com/infodetail-2950930.html