我也来小白一下.字符串&字符数组 问题。

时间:2023-01-07 11:40:37

char d [4]={'j','c','7','\0'} 是字符串…
char d [4]={'j','c','7','5'}  呢?书上说字符串末尾要“空值字符标记”,那我不写它会怎样?

char d [4]=“holi”这是字符串常量 
是否等价于char d [5]={‘h’,‘o’‘l’,‘i’,‘\0’}还是等价 char d [5]  =  "holic"

40 个解决方案

#1


一个字符数组,可以是一个字符串,也可以是多个。但一个字符串,一定是一个字符数组。
字符串是一个以'\0'结尾的字符数组。

char d[10] = {'a','b','c','\0','b','c','\0','c','c','\0'};
char d[10] = {'a','b','c','d','a','b','c','d','e','f'}; 这是一个字符串,由于没有明确的'\0'结尾,所以计算机不会计算字符串的具体长度。这是很不安全的。非常容易出现访问越界。

#2


动手试试就知道的

int main()
{
char c1[]="ab";
char c2[]={'a','b'};
char c3[]={'a','b','\0'};

cout <<sizeof(c1) <<'\t' <<c1 <<endl;
cout <<sizeof(c2) <<'\t' <<c2 <<endl;
cout <<sizeof(c3) <<'\t' <<c3 <<endl;

return 0;
}

#3


引用 1 楼 tearywang 的回复:
一个字符数组,可以是一个字符串,也可以是多个。但一个字符串,一定是一个字符数组。
字符串是一个以'\0'结尾的字符数组。

char d[10] = {'a','b','c','\0','b','c','\0','c','c','\0'};
char d[10] = {'a','b','c','d','a','b','c','d','e','f'}; 这是一个字符串,由于没有明确的'\0……


“char d[10] = {'a','b','c','d','a','b','c','d','e','f'}; ”---》你这个可是包含10个元素?但没有“空值字符标记”也算字符串吗?

#4


char d [4]=“holi”这个编译器会给你报错,两条都不等。char d [4]={'j','c','7','5'}这种写如果个数没超就没什么问题,如果大于或等于4就会出现越界,现在小程序你没感觉,大的运用程序会有很多隐患。

#5


引用 4 楼 echizenryom 的回复:
char d [4]=“holi”这个编译器会给你报错,两条都不等。
char d [4]={'j','c','7','5'}
这种写如果个数没超就没什么问题,如果大于或等于4就会出现越界,现在小程序你没感觉,大的运用程序会有很多隐患。

 char d [5]="holi"

是否等价于   char d [5]={‘h’,‘o’‘l’,‘i’,‘\0’}还是等价 
char d [4] ={‘h’,‘o’‘l’,‘i’}

#6


 会自动添加!当然是在没有越界的前提下!~~

#7


char d [5]="holi" 等价于char d [5]={‘h’,‘o’‘l’,‘i’,‘\0’}还是等价char d [4] ={‘h’,‘o’‘l’,‘i’}

#8


引用 7 楼 h_olic 的回复:
C/C++ code
char d [5]="holi" 等价于char d [5]={‘h’,‘o’‘l’,‘i’,‘\0’}还是等价char d [4] ={‘h’,‘o’‘l’,‘i’}

当然是前一个,从元素个数就可以看出来了。

#9


引用 8 楼 mingliang1212 的回复:
引用 7 楼 h_olic 的回复:
C/C++ code
char d [5]="holi" 等价于char d [5]={‘h’,‘o’‘l’,‘i’,‘\0’}还是等价char d [4] ={‘h’,‘o’‘l’,‘i’}

当然是前一个,从元素个数就可以看出来了。

小白又问-----。
char d [5]="holi"//这是常量字符串 强调的是常量……

#10


小白又问-----。
C/C++ code char d [5]="holi"//这是常量字符串 强调的是常量……

d可不是常量,别误会

#11


引用 10 楼 yuqangy 的回复:
小白又问-----。
C/C++ code char d [5]="holi"//这是常量字符串 强调的是常量……

d可不是常量,别误会
               我忍不住送了你一块砖头……书上说char d [5]="holi" 是常量字符串(从超语言意识来讲 应该还有“变量”字符串……)

#12


等价并不是说完全等同

char d[5]="holi"; 这样写的话,常量区有个字符串,它的地址你直接得不到,而&d[0]指向的还有个字符串(这个不是常量 ),是从常量区拷贝来的

char d[5]={'h','o','l','i','\0'}; 这样写的话,常量区里根本没有字符串,但&d[0]指向的字符串同上

#13


引用 2 楼 yisikaipu 的回复:
动手试试就知道的

C/C++ code
int main()
{
    char c1[]="ab";
    char c2[]={'a','b'};
    char c3[]={'a','b','\0'};

    cout <<sizeof(c1) <<'\t' <<c1 <<endl;
    cout <<sizeof(c2) <<'\t' <<c2 <<en……

c2 是神马???为什么是abab 啊!!

#14


还有c2 为什么size是2?

#15


引用 3 楼 h_olic 的回复:
引用 1 楼 tearywang 的回复:

一个字符数组,可以是一个字符串,也可以是多个。但一个字符串,一定是一个字符数组。
字符串是一个以'\0'结尾的字符数组。

char d[10] = {'a','b','c','\0','b','c','\0','c','c','\0'};
char d[10] = {'a','b','c','d','a','b','c','d','e',……


是的,操作系统的内存是连续的,这个串的C函数,是无法知道正确的串长度的,一个字符串,如"abcdefghij",其中的任何字符或子串拿出来,都可以成串,C/C++中的字符串是以'\0'结束的,所以C/C++函数去找串的时候,它只识别'\0',找到这个字符,就认为是串的结束符,所以第二个没有明确'\0'的串,是一个不安全串,因为系统并不知道正确的结束位置在哪里,它会一直找下去,直到找到'\0',然后它把开始位置,到最后'\0'前一个字符,作为串的一个整体来识别。

#16


引用 13 楼 h_olic 的回复:
c2 是神马???为什么是abab 啊!!


结果不一定是abab,因编译器和平台等等因素而异

前两个字符是数组元素,后面的都是因为末尾没有'\0'而造成的

sizeof(c2)等于2很正常,这种情况编译器不会自动添加'\0',因为你既然这么一个元素一个元素地写,它就认为你就是只要这两个元素

你写成"ab",编译器才认为你要的是两个字符末尾加一个终止符的字符串,也就是三个字符的字符串

总结,char c[]={'a','b'}; 一个元素一个元素地写,编译器不会自动加'\0',运行时内存里也不存在一个字符串字面常量
char c[]="ab"; 这样写,编译器自动加'\0',运行时内存里有一个字符串字面常量,但是你直接得不到它的地址,你也不需要,这个字面常量的作用仅仅是让自身被拷贝到&c[0]起始的地址处
还有一种写法,char *c="ab"; 这样写,编译器当然也自动加'\0',运行时内存里有一个字符串字面常量,而且它的地址就存在c里。因为这才是真正的常量,默认情况下是不允许修改的,所以你如果要修改,比如c[0]='x';就会出错。而前面两种写法你用c[0]='x';修改的并不是字符串字面常量,而是它的拷贝。

另外char c[]="ab\0\0\0"; 这样写,编译器仍然会自动再加一个'\0',于是sizeof(c)等于6,即两个字符加三个终止符再加一个终止符。内存里也确实有6个字符。但是strlen(c)只等于2,因为它是挨个去数,遇到第一个终止符就认为该字符串结束了。

#17


出错呗,我想肯定是“烫烫”

#18


我自己总结一下吧…… 
如有不对请大神( @yisikaipu   @tearywang )改正……

 C++中的字符串和c的字符串不一样 ,C的字符串总是作为字符数组处理。
C++有两种处理方式,一种是使用string类库一种是使用从c哪里继承来的方法。 
从c那里继承来的方法需要“空字符标志”才能被称为字符串。所以有楼上那句“字符串一定是字符数粗 而字符数组不一定是字符串”

char c[]={'a','b'};//不会自动补“空字符标志”所以只能被称为字符数组 当然你作为字符串输出就出错了

char c[]="ab";//这个回自动补一个“空字符标志”所以是字符串
 另外它“运行时内存里有一个字符串字面常量,但是你直接得不到它的地址,你也不需要,这个字面常量的作用仅仅是让自身被拷贝到&c[0]起始的地址处”

#19


 @yisikaipu @tearywang  麻烦你们看一下上面的

#20


引用 2 楼 yisikaipu 的回复:
动手试试就知道的

C/C++ code
int main()
{
    char c1[]="ab";
    char c2[]={'a','b'};
    char c3[]={'a','b','\0'};

    cout <<sizeof(c1) <<'\t' <<c1 <<endl;
    cout <<sizeof(c2) <<'\t' <<c2 <<endl;
  ……




刚好这里c1和c3内容一样,内存布局对称的……于是不管栈从哪个方向长,应该都是ab\0abab\0。cout输出C风格字符串用basic_ostream重载的operator<<,间接用到了char_traits的length,这个函数的语义是把输入的参数当作C风格字符串的首元素的指针求字符串的长。于是这里就把abab\0当成一个字符串输出了。
对于期望字符指针当作字符串的参数要保证之后存在空字符。这里只是因为内存布局的关系运气好,运气不好就访问违例程序挂掉了。


这样说对吗??

#21


引用 20 楼 h_olic 的回复:
刚好这里c1和c3内容一样,内存布局对称的……于是不管栈从哪个方向长,应该都是ab\0abab\0。cout输出C风格字符串用basic_ostream重载的operator<<,间接用到了char_traits的length,这个函数的语义是把输入的参数当作C风格字符串的首元素的指针求字符串的长。于是这里就把abab\0当成一个字符串输出了。
对于期望字符指针当作字符串的参数要保证之后存在空字符。这里只是因为内存布局的关系运气好,运气不好就访问违例程序挂掉了。



就是这个意思了,但因编译器与平台等等因素不同,无法保证c1/c2/c3的元素一定是紧挨着接连存放的

#22


引用 11 楼 h_olic 的回复:
引用 10 楼 yuqangy 的回复:

小白又问-----。
C/C++ code char d [5]="holi"//这是常量字符串 强调的是常量……

d可不是常量,别误会
               我忍不住送了你一块砖头……书上说char d [5]="holi" 是常量字符串(从超语言意识来讲 应该还有“变量”字符串……)

也给我个砖头把。虽然书上那样说。不过我也认为它是变量。

#23


引用 10 楼 yuqangy 的回复:
小白又问-----。
C/C++ code char d [5]="holi"//这是常量字符串 强调的是常量……

d可不是常量,别误会

我决心捡回我的砖头…… yuqangy 别生气了哈  嘿嘿 我说 @jiergio 我人品好吧……

#24


18 楼  没错吧……

#25


对电脑而言没有乱码,只有二进制字节;对人脑才有乱码。

为什么要有数据结构这个东东?
因为要将现实世界或者抽象理论中的各种数据保存在计算机外存(光盘、硬盘、U盘……)或内存(ROM、RAM、SRAM……)里面的一维二进制字节数组中。
然后让CPU这个只会执行预先保存好的加减乘除移位条件转移……等机器指令的家伙按照人的意志去处理这些数据。

#26


VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

#27


引用 18 楼 h_olic 的回复:
 C++中的字符串和c的字符串不一样 ,C的字符串总是作为字符数组处理。
C++有两种处理方式,一种是使用string类库一种是使用从c哪里继承来的方法。 
从c那里继承来的方法需要“空字符标志”才能被称为字符串。所以有楼上那句“字符串一定是字符数粗 而字符数组不一定是字符串”


其实都没什么本质的不一样

一般来说,string内部也是用带终止符的字符数组来处理,只不过封装了

#28


引用 18 楼 h_olic 的回复:
我自己总结一下吧…… 
如有不对请大神( @yisikaipu @tearywang )改正……

 C++中的字符串和c的字符串不一样 ,C的字符串总是作为字符数组处理。
C++有两种处理方式,一种是使用string类库一种是使用从c哪里继承来的方法。 
从c那里继承来的方法需要“空字符标志”才能被称为字符串。所以有楼上那句“字符串一定是字符数粗 而字符数组不一定是字符串”


……


这样说吧,char是有历史原因的,最早的时候,字符和字节并没有非常严格的划分,而且当时的内存非常的宝贵,那些需要表示的字符用0到255编码足已(一个字节),因此,就把这组编码称为字符,也就是最早的ANSI标准,后来随时计算机应用在世界的普及,各国有各国的文字,因此才出了很多编码方式,总的分为两类,定长编码,也就是通常说的UNICODE编码(UNICODE字符集),另一类是不定长编码,也就是各地的ANSI编码(多字节字符集)。

这里,还是强调一句话,char表示是数据可以是字节,亦可以是字符,不应该看到char就认为是字符,它很有可能是字节,其在内存中的存在形式,永远是字节。一个字符数组,可以一个或多个字符串,一个字符串一定是一个字符数组。C/C++都一样。完整且正确的字符串应该是以'\0'结束的字符数组。

双引号括起来的表示的是一个完整的字符串,其长度是可见字符数加1。

string是C++标准中的一个类,它是一个管理字符数组的壳。它存的目标,是由于字符串中的一些操作,如串"abc"+串"bcd"(+是连接的意思),需要内存的重新分配(串是一个连续的字符数组),其帮助你管理这个字符数组所使用的内存,和封装一些常用的操作。存内部数据存在,依然是一个连续的字符数组。

char a[]={'a','b','c','\0'};
char* a = new char[4]; a[0]='a';a[1]='b'; a[2]='c';a[3]='\0'; 这时的a也是一个字符数组,亦是一个字符串。
string a("abc");

#29



int main()
{
    using namespace std;
    const int ArSize = 20;
    char name[ArSize];
    char dessert[ArSize];

    cout << "Enter your name:\n";
    cin >> name;  //那个'\0'是字符串的标志对吧?用引号声明系统自动添加了空字符标志,这里呢?  这个 为什么称之为字符串而不是字符数组?
    cout << "Enter your favorite dessert:\n";
    cin >> dessert; //
    cout << "I have some delicious " << dessert;
    cout << " for you, " << name << ".\n";
    return 0; 
}










求问 注释中的问题……

#30


TearyWang  yisikaipu 
通灵~召唤中

#31


引用 29 楼 h_olic 的回复:
C/C++ code

int main()
{
    using namespace std;
    const int ArSize = 20;
    char name[ArSize];
    char dessert[ArSize];

    cout << "Enter your name:\n";
    cin >> name;  //那个'\0'是字符串的标志对吧?用……

这里无法从键盘读入“空字符标志”
 cin 使用空格 制表符 换行符来定字符串的界……



小白又有问 为什么cin 知道作字符串处理? 

#32


引用 31 楼 h_olic 的回复:
为什么cin 知道作字符串处理?


c++标准就这么定的。它总得有一种默认行为

不喜欢你可以重载之,让它不要自动添加终止符即可

#33


我也来小白一下.字符串&字符数组 问题。

#34


问题好多呀》》》

#35




小白又有问 为什么cin 知道作字符串处理? 

cin是一个对象,
他所属的类重载了operator>>(char*);
当你
cin>>arr;//当arr的类型是 (char*)时,就会调用那一个重载。
这个重载是专门用来输入字符串的。
当然他也重载了很多类型,例如int,float,double, string and so on

#36


这帖子暂时不结帐……等我把这张剩下的看掉~  还望各位多多指教…… 唉 以前在学校学过c#粗浅的很 想用心学点什么 发现各种疑问无人可问……唉

#37


该回复于2011-11-21 09:18:38被版主删除

#38


引用 34 楼 mingliang1212 的回复:
问题好多呀》》》


我也来小白一下.字符串&字符数组 问题。 

#39


cin是标准C++中的一个类型,它是一个stream,>>运算符已经被重载,运算符接收一个参数,它接收的参数是一个stream,也就是流,接收的是一个字节流,表示的是一个字符串,在接收到这个流后,内部将其存储为字符数组。外面由壳string来表示。

// 以下可以表明流数据的类型及继承关系:
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 istream cin; // 摘自iostream

typedef basic_istream<char, char_traits<char> > istream; // 摘自iosfwd

template<class _Elem, class _Traits>
class basic_istream : virtual public basic_ios<_Elem, _Traits> // 摘自istream

// 以下可以表明,string是一个管理容器
typedef basic_string<char, char_traits<char>, allocator<char> > string; // 摘自xstring

template<class _Elem, class _Traits, class _Ax>
class basic_string : public _String_val<_Elem, _Ax> // 摘自xstring

template<class _Ty, class _Alloc>
class _String_val : public _String_base // 摘自xstring

class _CRTIMP2_PURE _String_base : public _Container_base_secure // 摘自xstring

class _CRTIMP2_PURE _Container_base_secure // 摘自xutility

#40


字符串 这章节我看完了 暂时没有新的疑问……下面是 共用体 枚举 指针 所以捏 呃……我会有新的问题 还望各位指教~ 我也来小白一下.字符串&字符数组 问题。

#1


一个字符数组,可以是一个字符串,也可以是多个。但一个字符串,一定是一个字符数组。
字符串是一个以'\0'结尾的字符数组。

char d[10] = {'a','b','c','\0','b','c','\0','c','c','\0'};
char d[10] = {'a','b','c','d','a','b','c','d','e','f'}; 这是一个字符串,由于没有明确的'\0'结尾,所以计算机不会计算字符串的具体长度。这是很不安全的。非常容易出现访问越界。

#2


动手试试就知道的

int main()
{
char c1[]="ab";
char c2[]={'a','b'};
char c3[]={'a','b','\0'};

cout <<sizeof(c1) <<'\t' <<c1 <<endl;
cout <<sizeof(c2) <<'\t' <<c2 <<endl;
cout <<sizeof(c3) <<'\t' <<c3 <<endl;

return 0;
}

#3


引用 1 楼 tearywang 的回复:
一个字符数组,可以是一个字符串,也可以是多个。但一个字符串,一定是一个字符数组。
字符串是一个以'\0'结尾的字符数组。

char d[10] = {'a','b','c','\0','b','c','\0','c','c','\0'};
char d[10] = {'a','b','c','d','a','b','c','d','e','f'}; 这是一个字符串,由于没有明确的'\0……


“char d[10] = {'a','b','c','d','a','b','c','d','e','f'}; ”---》你这个可是包含10个元素?但没有“空值字符标记”也算字符串吗?

#4


char d [4]=“holi”这个编译器会给你报错,两条都不等。char d [4]={'j','c','7','5'}这种写如果个数没超就没什么问题,如果大于或等于4就会出现越界,现在小程序你没感觉,大的运用程序会有很多隐患。

#5


引用 4 楼 echizenryom 的回复:
char d [4]=“holi”这个编译器会给你报错,两条都不等。
char d [4]={'j','c','7','5'}
这种写如果个数没超就没什么问题,如果大于或等于4就会出现越界,现在小程序你没感觉,大的运用程序会有很多隐患。

 char d [5]="holi"

是否等价于   char d [5]={‘h’,‘o’‘l’,‘i’,‘\0’}还是等价 
char d [4] ={‘h’,‘o’‘l’,‘i’}

#6


 会自动添加!当然是在没有越界的前提下!~~

#7


char d [5]="holi" 等价于char d [5]={‘h’,‘o’‘l’,‘i’,‘\0’}还是等价char d [4] ={‘h’,‘o’‘l’,‘i’}

#8


引用 7 楼 h_olic 的回复:
C/C++ code
char d [5]="holi" 等价于char d [5]={‘h’,‘o’‘l’,‘i’,‘\0’}还是等价char d [4] ={‘h’,‘o’‘l’,‘i’}

当然是前一个,从元素个数就可以看出来了。

#9


引用 8 楼 mingliang1212 的回复:
引用 7 楼 h_olic 的回复:
C/C++ code
char d [5]="holi" 等价于char d [5]={‘h’,‘o’‘l’,‘i’,‘\0’}还是等价char d [4] ={‘h’,‘o’‘l’,‘i’}

当然是前一个,从元素个数就可以看出来了。

小白又问-----。
char d [5]="holi"//这是常量字符串 强调的是常量……

#10


小白又问-----。
C/C++ code char d [5]="holi"//这是常量字符串 强调的是常量……

d可不是常量,别误会

#11


引用 10 楼 yuqangy 的回复:
小白又问-----。
C/C++ code char d [5]="holi"//这是常量字符串 强调的是常量……

d可不是常量,别误会
               我忍不住送了你一块砖头……书上说char d [5]="holi" 是常量字符串(从超语言意识来讲 应该还有“变量”字符串……)

#12


等价并不是说完全等同

char d[5]="holi"; 这样写的话,常量区有个字符串,它的地址你直接得不到,而&d[0]指向的还有个字符串(这个不是常量 ),是从常量区拷贝来的

char d[5]={'h','o','l','i','\0'}; 这样写的话,常量区里根本没有字符串,但&d[0]指向的字符串同上

#13


引用 2 楼 yisikaipu 的回复:
动手试试就知道的

C/C++ code
int main()
{
    char c1[]="ab";
    char c2[]={'a','b'};
    char c3[]={'a','b','\0'};

    cout <<sizeof(c1) <<'\t' <<c1 <<endl;
    cout <<sizeof(c2) <<'\t' <<c2 <<en……

c2 是神马???为什么是abab 啊!!

#14


还有c2 为什么size是2?

#15


引用 3 楼 h_olic 的回复:
引用 1 楼 tearywang 的回复:

一个字符数组,可以是一个字符串,也可以是多个。但一个字符串,一定是一个字符数组。
字符串是一个以'\0'结尾的字符数组。

char d[10] = {'a','b','c','\0','b','c','\0','c','c','\0'};
char d[10] = {'a','b','c','d','a','b','c','d','e',……


是的,操作系统的内存是连续的,这个串的C函数,是无法知道正确的串长度的,一个字符串,如"abcdefghij",其中的任何字符或子串拿出来,都可以成串,C/C++中的字符串是以'\0'结束的,所以C/C++函数去找串的时候,它只识别'\0',找到这个字符,就认为是串的结束符,所以第二个没有明确'\0'的串,是一个不安全串,因为系统并不知道正确的结束位置在哪里,它会一直找下去,直到找到'\0',然后它把开始位置,到最后'\0'前一个字符,作为串的一个整体来识别。

#16


引用 13 楼 h_olic 的回复:
c2 是神马???为什么是abab 啊!!


结果不一定是abab,因编译器和平台等等因素而异

前两个字符是数组元素,后面的都是因为末尾没有'\0'而造成的

sizeof(c2)等于2很正常,这种情况编译器不会自动添加'\0',因为你既然这么一个元素一个元素地写,它就认为你就是只要这两个元素

你写成"ab",编译器才认为你要的是两个字符末尾加一个终止符的字符串,也就是三个字符的字符串

总结,char c[]={'a','b'}; 一个元素一个元素地写,编译器不会自动加'\0',运行时内存里也不存在一个字符串字面常量
char c[]="ab"; 这样写,编译器自动加'\0',运行时内存里有一个字符串字面常量,但是你直接得不到它的地址,你也不需要,这个字面常量的作用仅仅是让自身被拷贝到&c[0]起始的地址处
还有一种写法,char *c="ab"; 这样写,编译器当然也自动加'\0',运行时内存里有一个字符串字面常量,而且它的地址就存在c里。因为这才是真正的常量,默认情况下是不允许修改的,所以你如果要修改,比如c[0]='x';就会出错。而前面两种写法你用c[0]='x';修改的并不是字符串字面常量,而是它的拷贝。

另外char c[]="ab\0\0\0"; 这样写,编译器仍然会自动再加一个'\0',于是sizeof(c)等于6,即两个字符加三个终止符再加一个终止符。内存里也确实有6个字符。但是strlen(c)只等于2,因为它是挨个去数,遇到第一个终止符就认为该字符串结束了。

#17


出错呗,我想肯定是“烫烫”

#18


我自己总结一下吧…… 
如有不对请大神( @yisikaipu   @tearywang )改正……

 C++中的字符串和c的字符串不一样 ,C的字符串总是作为字符数组处理。
C++有两种处理方式,一种是使用string类库一种是使用从c哪里继承来的方法。 
从c那里继承来的方法需要“空字符标志”才能被称为字符串。所以有楼上那句“字符串一定是字符数粗 而字符数组不一定是字符串”

char c[]={'a','b'};//不会自动补“空字符标志”所以只能被称为字符数组 当然你作为字符串输出就出错了

char c[]="ab";//这个回自动补一个“空字符标志”所以是字符串
 另外它“运行时内存里有一个字符串字面常量,但是你直接得不到它的地址,你也不需要,这个字面常量的作用仅仅是让自身被拷贝到&c[0]起始的地址处”

#19


 @yisikaipu @tearywang  麻烦你们看一下上面的

#20


引用 2 楼 yisikaipu 的回复:
动手试试就知道的

C/C++ code
int main()
{
    char c1[]="ab";
    char c2[]={'a','b'};
    char c3[]={'a','b','\0'};

    cout <<sizeof(c1) <<'\t' <<c1 <<endl;
    cout <<sizeof(c2) <<'\t' <<c2 <<endl;
  ……




刚好这里c1和c3内容一样,内存布局对称的……于是不管栈从哪个方向长,应该都是ab\0abab\0。cout输出C风格字符串用basic_ostream重载的operator<<,间接用到了char_traits的length,这个函数的语义是把输入的参数当作C风格字符串的首元素的指针求字符串的长。于是这里就把abab\0当成一个字符串输出了。
对于期望字符指针当作字符串的参数要保证之后存在空字符。这里只是因为内存布局的关系运气好,运气不好就访问违例程序挂掉了。


这样说对吗??

#21


引用 20 楼 h_olic 的回复:
刚好这里c1和c3内容一样,内存布局对称的……于是不管栈从哪个方向长,应该都是ab\0abab\0。cout输出C风格字符串用basic_ostream重载的operator<<,间接用到了char_traits的length,这个函数的语义是把输入的参数当作C风格字符串的首元素的指针求字符串的长。于是这里就把abab\0当成一个字符串输出了。
对于期望字符指针当作字符串的参数要保证之后存在空字符。这里只是因为内存布局的关系运气好,运气不好就访问违例程序挂掉了。



就是这个意思了,但因编译器与平台等等因素不同,无法保证c1/c2/c3的元素一定是紧挨着接连存放的

#22


引用 11 楼 h_olic 的回复:
引用 10 楼 yuqangy 的回复:

小白又问-----。
C/C++ code char d [5]="holi"//这是常量字符串 强调的是常量……

d可不是常量,别误会
               我忍不住送了你一块砖头……书上说char d [5]="holi" 是常量字符串(从超语言意识来讲 应该还有“变量”字符串……)

也给我个砖头把。虽然书上那样说。不过我也认为它是变量。

#23


引用 10 楼 yuqangy 的回复:
小白又问-----。
C/C++ code char d [5]="holi"//这是常量字符串 强调的是常量……

d可不是常量,别误会

我决心捡回我的砖头…… yuqangy 别生气了哈  嘿嘿 我说 @jiergio 我人品好吧……

#24


18 楼  没错吧……

#25


对电脑而言没有乱码,只有二进制字节;对人脑才有乱码。

为什么要有数据结构这个东东?
因为要将现实世界或者抽象理论中的各种数据保存在计算机外存(光盘、硬盘、U盘……)或内存(ROM、RAM、SRAM……)里面的一维二进制字节数组中。
然后让CPU这个只会执行预先保存好的加减乘除移位条件转移……等机器指令的家伙按照人的意志去处理这些数据。

#26


VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)

#27


引用 18 楼 h_olic 的回复:
 C++中的字符串和c的字符串不一样 ,C的字符串总是作为字符数组处理。
C++有两种处理方式,一种是使用string类库一种是使用从c哪里继承来的方法。 
从c那里继承来的方法需要“空字符标志”才能被称为字符串。所以有楼上那句“字符串一定是字符数粗 而字符数组不一定是字符串”


其实都没什么本质的不一样

一般来说,string内部也是用带终止符的字符数组来处理,只不过封装了

#28


引用 18 楼 h_olic 的回复:
我自己总结一下吧…… 
如有不对请大神( @yisikaipu @tearywang )改正……

 C++中的字符串和c的字符串不一样 ,C的字符串总是作为字符数组处理。
C++有两种处理方式,一种是使用string类库一种是使用从c哪里继承来的方法。 
从c那里继承来的方法需要“空字符标志”才能被称为字符串。所以有楼上那句“字符串一定是字符数粗 而字符数组不一定是字符串”


……


这样说吧,char是有历史原因的,最早的时候,字符和字节并没有非常严格的划分,而且当时的内存非常的宝贵,那些需要表示的字符用0到255编码足已(一个字节),因此,就把这组编码称为字符,也就是最早的ANSI标准,后来随时计算机应用在世界的普及,各国有各国的文字,因此才出了很多编码方式,总的分为两类,定长编码,也就是通常说的UNICODE编码(UNICODE字符集),另一类是不定长编码,也就是各地的ANSI编码(多字节字符集)。

这里,还是强调一句话,char表示是数据可以是字节,亦可以是字符,不应该看到char就认为是字符,它很有可能是字节,其在内存中的存在形式,永远是字节。一个字符数组,可以一个或多个字符串,一个字符串一定是一个字符数组。C/C++都一样。完整且正确的字符串应该是以'\0'结束的字符数组。

双引号括起来的表示的是一个完整的字符串,其长度是可见字符数加1。

string是C++标准中的一个类,它是一个管理字符数组的壳。它存的目标,是由于字符串中的一些操作,如串"abc"+串"bcd"(+是连接的意思),需要内存的重新分配(串是一个连续的字符数组),其帮助你管理这个字符数组所使用的内存,和封装一些常用的操作。存内部数据存在,依然是一个连续的字符数组。

char a[]={'a','b','c','\0'};
char* a = new char[4]; a[0]='a';a[1]='b'; a[2]='c';a[3]='\0'; 这时的a也是一个字符数组,亦是一个字符串。
string a("abc");

#29



int main()
{
    using namespace std;
    const int ArSize = 20;
    char name[ArSize];
    char dessert[ArSize];

    cout << "Enter your name:\n";
    cin >> name;  //那个'\0'是字符串的标志对吧?用引号声明系统自动添加了空字符标志,这里呢?  这个 为什么称之为字符串而不是字符数组?
    cout << "Enter your favorite dessert:\n";
    cin >> dessert; //
    cout << "I have some delicious " << dessert;
    cout << " for you, " << name << ".\n";
    return 0; 
}










求问 注释中的问题……

#30


TearyWang  yisikaipu 
通灵~召唤中

#31


引用 29 楼 h_olic 的回复:
C/C++ code

int main()
{
    using namespace std;
    const int ArSize = 20;
    char name[ArSize];
    char dessert[ArSize];

    cout << "Enter your name:\n";
    cin >> name;  //那个'\0'是字符串的标志对吧?用……

这里无法从键盘读入“空字符标志”
 cin 使用空格 制表符 换行符来定字符串的界……



小白又有问 为什么cin 知道作字符串处理? 

#32


引用 31 楼 h_olic 的回复:
为什么cin 知道作字符串处理?


c++标准就这么定的。它总得有一种默认行为

不喜欢你可以重载之,让它不要自动添加终止符即可

#33


我也来小白一下.字符串&字符数组 问题。

#34


问题好多呀》》》

#35




小白又有问 为什么cin 知道作字符串处理? 

cin是一个对象,
他所属的类重载了operator>>(char*);
当你
cin>>arr;//当arr的类型是 (char*)时,就会调用那一个重载。
这个重载是专门用来输入字符串的。
当然他也重载了很多类型,例如int,float,double, string and so on

#36


这帖子暂时不结帐……等我把这张剩下的看掉~  还望各位多多指教…… 唉 以前在学校学过c#粗浅的很 想用心学点什么 发现各种疑问无人可问……唉

#37


该回复于2011-11-21 09:18:38被版主删除

#38


引用 34 楼 mingliang1212 的回复:
问题好多呀》》》


我也来小白一下.字符串&字符数组 问题。 

#39


cin是标准C++中的一个类型,它是一个stream,>>运算符已经被重载,运算符接收一个参数,它接收的参数是一个stream,也就是流,接收的是一个字节流,表示的是一个字符串,在接收到这个流后,内部将其存储为字符数组。外面由壳string来表示。

// 以下可以表明流数据的类型及继承关系:
__PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 istream cin; // 摘自iostream

typedef basic_istream<char, char_traits<char> > istream; // 摘自iosfwd

template<class _Elem, class _Traits>
class basic_istream : virtual public basic_ios<_Elem, _Traits> // 摘自istream

// 以下可以表明,string是一个管理容器
typedef basic_string<char, char_traits<char>, allocator<char> > string; // 摘自xstring

template<class _Elem, class _Traits, class _Ax>
class basic_string : public _String_val<_Elem, _Ax> // 摘自xstring

template<class _Ty, class _Alloc>
class _String_val : public _String_base // 摘自xstring

class _CRTIMP2_PURE _String_base : public _Container_base_secure // 摘自xstring

class _CRTIMP2_PURE _Container_base_secure // 摘自xutility

#40


字符串 这章节我看完了 暂时没有新的疑问……下面是 共用体 枚举 指针 所以捏 呃……我会有新的问题 还望各位指教~ 我也来小白一下.字符串&字符数组 问题。