char * 与 char[] 区别
来源:互联网 发布:僵尸 知乎 编辑:程序博客网 时间:2024/06/05 02:34
char *a 与char a[] 的区别
char *a = "hello" 中的a是指向第一个字符‘a'的一个指针
char a[20] = "hello" 中数组名a也是执行数组第一个字符‘h’的指针
但二者并不相同:
看实例:把两个字符串相加:
结果:
对比:
结果:
把字符串加到指针所指的字串上去,出现段错误,本质原因:*d="0123456789"存放在常量区,是无法修的。而数组是存放在栈中,是可以修改的。两者区别如下:
一. ”读“ ”写“ 能力
- char *a = "abcd"; 此时"abcd"存放在常量区。指针a只是静态的,只能“读”字串,而不具备对字串“写"的本事。比如:a[0]='m'不正确
- 而char a[20] = "abcd"; 此时 "abcd"存放在栈,定义了数组a,并且开了大小为20个字符空间,此时的数组名a是指向第一个字符'a'指针,它是动态的,可以对整个字符串进行"读写”操作。比如a[0] = 'm'正确
二. 赋值时刻
- char *a = "abcd"; 是在编译时就确定了(因为为常量)。
- 而char a[20] = "abcd"; 在运行时确定
三. 存取效率
- char *a = "abcd"; 存于栈上。在栈上的数组比指针所指向字符串快。因此慢
- 而char a[20] = "abcd"; 存于栈上。快
另外注意:
char a[] = "01234",虽然没有指明字符串的长度,但是此时系统已经开好了,就是大小为6-----'0' '1' '2' '3' '4' '5' '\0',(注意strlen(a)是不计‘\0’)
看一结构中出现的同样的问题:
#include<stdio.h>typedef struct node{ int size;}node;void Init(node *n){ n->size = 100;}int main(){ node *n; Init(n); return 0;}
这样红色部分在调用Init函数时会出现“Segment Default", 因为此时 指针n是静态的,只有“读”的本事,不可以改变。
改为:
int main(){ node n; Init(&n); //此时传送地址,为引用 return 0;}
或:
int main(){ node *n = (*node)malloc(sizeof(node)); //动态分配空间 Init(n); return 0;}
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
string str_s = "abc";
char *str_cp = "abc";
char str_ca[] = "abc";
1. str_cp是指针,指向一段数据有四个元素,分别是'a', 'b', 'c', '\0'。
2. str_ca是数组,它包含四个元素,分别是'a', 'b', 'c', '\0'。
这个说法不正确。数组str_ca也会有'\0'。但如果你写char str_ca[] = {'a', 'b', 'c'}则不会有'\0'。
3.
这个说法不正确。数组和指针是不同的,数组不能看作常指针。证据就是:
char* const s = "abcdef";
char a[] = "abcdef";
则sizeof(s)一般为2或者4,而sizeof(a)为7。
指针只保存了所指向的地址,数组既包括首地址的信息,还包括长度的信息。不过数组在作为参数传递时,可以转化为指针的形式(数组首地址作为指针所指地址,数组长度信息被丢弃)。
4.
从对象的观点看。str_s就是一个对象,其中包含了字符串数据,如此而已。至于对象内部是如何操作,以保证正确的包含这个字符串数据,这完全取决于string类的作者。这种现象体现了面向对象编程思想中的一个重要观点——封装。作为类的使用者,我们只要知道它应该怎么用即可,不需要知道它是如何工作的。也就是说不需要知道它的本质。
当然我们也不能一无所知。为了更好的使用这个类,它的基本特性要了然于心。比如,我们要知道string中的字符是连续存储的,而不是通过链表来进行存储的。等等。
5.
不是的。C++本身的输入输出就直接支持string。比如:
string s;
cin >> s;
cout << s;
虽然string是鼓励的,但这并不意味着char*就是应该被抛弃的。很多时候还是会用到char*。例如你从zip包中解压出一个文件,因为很多zip压缩解压的程序都用C语言写,因此文件解压得到的数据在内存中很可能就是以char*的形式存在的。
6.
这个问题比较细,下面一点一点的分析。
(1) 返回一个char*,赋值给char*。可以。
(2) 返回一个char*,赋值给string。可以。运行时实际的情况是,根据char*的值构造一个临时的string对象,把这个临时的string对象赋值给你的string变量,最后销毁临时的string对象。
(3) 返回一个char*,赋值给char[]。不可以。char[]是数组,数组是不允许赋值的。只有数组的元素才能赋值。
(4) 返回一个string变量,赋值给char*。不可以。因为string不能转化为char*。你可以通过string类的c_str方法取得它的指针,但是要注意,如果string对象本身被销毁了,则指针所指的数据也跟着无效。例如:
string func() {
return string("abc");
}
int main() {
char* s = func().c_str();
cout << s; // 错误!!
}
因为函数func()返回后,它的返回值是临时的。通过c_str取得它的指针赋值给s后,临时值被销毁,因此s指向的是一个无效的位置。
(5) 返回一个string变量,赋值给string。可以。
(6) 返回一个string变量,赋值给char[]。不可以。char[]是数组,数组是不允许赋值的。只有数组的元素才能赋值。
(7) 如果返回数组的名字,其实是返回数组的首地址,也就是一个指针。所以这其实跟返回char*是非常类似的。唯一需要注意的问题是,如果数组是局部变量,并且不是static的,则函数返回时数组会被销毁,所以返回的指针所指向的位置也是无效的。例如:
char* func() {
char a[] = {"abc"};
return a;
}
int main() {
char* s = func();
cout << s; // 错误!!
}
7.
这个涉及到数据类型的问题。cout会根据数据的类型和数据的值来确定最终的输出。对于char类型,cout只输出一个字符,对于char*类型,cout输出多个字符,直到遇到'\0'才结束。
因为str_cp是char*类型,所以str_cp[1]是char类型。所以cout << str_cp[1]实际上是输出char类型,因此只输出一个字符。
但str_cp + 1是char*类型,所以cout << (str_cp+1)实际上是输出char*类型,因此输出多个字符,遇到'\0'才结束。
如果觉得(str_cp+1)不够直观,可以写为&str_cp[1]。(虽然后一种写法看起来执行了两步操作,但实际上两种写法编译后得到的代码是一样的,不会有效率问题)
char *str_cp = "abc";
char str_ca[] = "abc";
1. str_cp是指针,指向一段数据有四个元素,分别是'a', 'b', 'c', '\0'。
2. str_ca是数组,它包含四个元素,分别是'a', 'b', 'c', '\0'。
引用:我知道*str_cp的"abc"多了一个'/0'
这个说法不正确。数组str_ca也会有'\0'。但如果你写char str_ca[] = {'a', 'b', 'c'}则不会有'\0'。
3.
引用:str_ca相当于一个char * const str_cp
这个说法不正确。数组和指针是不同的,数组不能看作常指针。证据就是:
char* const s = "abcdef";
char a[] = "abcdef";
则sizeof(s)一般为2或者4,而sizeof(a)为7。
指针只保存了所指向的地址,数组既包括首地址的信息,还包括长度的信息。不过数组在作为参数传递时,可以转化为指针的形式(数组首地址作为指针所指地址,数组长度信息被丢弃)。
4.
引用:string str_s 本质上是什么呢?
从对象的观点看。str_s就是一个对象,其中包含了字符串数据,如此而已。至于对象内部是如何操作,以保证正确的包含这个字符串数据,这完全取决于string类的作者。这种现象体现了面向对象编程思想中的一个重要观点——封装。作为类的使用者,我们只要知道它应该怎么用即可,不需要知道它是如何工作的。也就是说不需要知道它的本质。
当然我们也不能一无所知。为了更好的使用这个类,它的基本特性要了然于心。比如,我们要知道string中的字符是连续存储的,而不是通过链表来进行存储的。等等。
5.
引用:一般做开发都得转换成 char*的吗?
不是的。C++本身的输入输出就直接支持string。比如:
string s;
cin >> s;
cout << s;
虽然string是鼓励的,但这并不意味着char*就是应该被抛弃的。很多时候还是会用到char*。例如你从zip包中解压出一个文件,因为很多zip压缩解压的程序都用C语言写,因此文件解压得到的数据在内存中很可能就是以char*的形式存在的。
6.
引用:我可以在一个函数里返回一个 数组名称/string变量/char *,然后给一个 char * /string/char[] 这样赋值行吗?
这个问题比较细,下面一点一点的分析。
(1) 返回一个char*,赋值给char*。可以。
(2) 返回一个char*,赋值给string。可以。运行时实际的情况是,根据char*的值构造一个临时的string对象,把这个临时的string对象赋值给你的string变量,最后销毁临时的string对象。
(3) 返回一个char*,赋值给char[]。不可以。char[]是数组,数组是不允许赋值的。只有数组的元素才能赋值。
(4) 返回一个string变量,赋值给char*。不可以。因为string不能转化为char*。你可以通过string类的c_str方法取得它的指针,但是要注意,如果string对象本身被销毁了,则指针所指的数据也跟着无效。例如:
string func() {
return string("abc");
}
int main() {
char* s = func().c_str();
cout << s; // 错误!!
}
因为函数func()返回后,它的返回值是临时的。通过c_str取得它的指针赋值给s后,临时值被销毁,因此s指向的是一个无效的位置。
(5) 返回一个string变量,赋值给string。可以。
(6) 返回一个string变量,赋值给char[]。不可以。char[]是数组,数组是不允许赋值的。只有数组的元素才能赋值。
(7) 如果返回数组的名字,其实是返回数组的首地址,也就是一个指针。所以这其实跟返回char*是非常类似的。唯一需要注意的问题是,如果数组是局部变量,并且不是static的,则函数返回时数组会被销毁,所以返回的指针所指向的位置也是无效的。例如:
char* func() {
char a[] = {"abc"};
return a;
}
int main() {
char* s = func();
cout << s; // 错误!!
}
7.
引用:我如果cout < <str_cp[1] 此时指向'b'如果以'\0'为结束标志的话,应该输出的是bc 啊
这个涉及到数据类型的问题。cout会根据数据的类型和数据的值来确定最终的输出。对于char类型,cout只输出一个字符,对于char*类型,cout输出多个字符,直到遇到'\0'才结束。
因为str_cp是char*类型,所以str_cp[1]是char类型。所以cout << str_cp[1]实际上是输出char类型,因此只输出一个字符。
但str_cp + 1是char*类型,所以cout << (str_cp+1)实际上是输出char*类型,因此输出多个字符,遇到'\0'才结束。
如果觉得(str_cp+1)不够直观,可以写为&str_cp[1]。(虽然后一种写法看起来执行了两步操作,但实际上两种写法编译后得到的代码是一样的,不会有效率问题)
- char[] 与 char *区别
- char * 与 char[] 区别
- char []与char*区别
- char[] 与 char* 的区别
- char[] 与 char* 的区别
- char * 与 char[]的区别
- char *与char []的区别
- char *与 &char的区别
- char*与char[]的区别
- unsigned char * 与 char *区别
- char[]与char*的区别
- char * 与char[]的区别
- char *与char[]的区别
- char[] 与char*的区别
- char[] 与char*的区别
- char * 与char []的区别
- char与unsigned char 区别
- *(char**) 与 (char*) 的区别
- 自动打渠道包的shell命令
- Google App Engine 学习和实践
- 给网页设计师和前端开发者看的前端性能优化
- iOS多线程编程之NSThread的使用
- iOS多线程编程之NSOperation和NSOperationQueue的使用
- char * 与 char[] 区别
- 编译内核模块的Makefile
- C++编译器
- iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用
- 如何向App Store提交应用
- STING:统计信息网格(STatistical INformation Grid)
- 《数据通信与网络》笔记--无线局域网
- 竹筏还是灯塔——数据洪流中的科学方法
- MySQL 同机异步复制