首页 新闻 会员 周边

C++对字符数组的输入

0
悬赏园豆:10 [已解决问题] 解决于 2017-11-05 10:29

本人是一个新手,刚刚自学完C++, 今天有感而发,突然想到想到一个问题,关于cin对于字符数组的输入,具体的代码描述是这样的:

(OS: CentOS 7, clang++)

 1 #include <iostream>
 2 using std::cin;
 3 using std::cout;
 4 using std::endl;
 5 
 6 int main(void)
 7 {
 8     char str[6] = "Hello";
 9 
10     cout << str << endl;
11     cout << &str[0] << endl;
12     cout << &str << endl;
13 
14     cin >> str;
15     cout << str << endl;16     cout << &str << endl;
17 
18     return 0;
19 }

运行结果:

1 Hello
2 Hello
3 0x7fffcb2c8786
4 World    //此为输入
5 World
6 World
7 0x7fffcb2c8786

我觉得这反映了一些深刻的问题:

1:代码的第10行和第11行,我本想输出数组的第一个元素的地址,但为什么输出了整个数组?

2:为什么12行和16行的结果一样,字符串常量"Hello"不是应该存储在常量区么?

3:如果第8行改为  char *str = "Hello";  或 char str[] = "Hello",

对于后者,

clang++ 10.cpp -o main

10.cpp:8:14: warning: conversion from string literal to 'char *' is deprecated [-Wc++11-compat-deprecated-writable-strings]
char *str = "Hello";
^
1 warning generated.

编译会发出警告,并且运行到第14行出现段错误,这两种表达式的内存分配方式有何异同。

4:对于C语言:

复制代码
 1 #include <stdio.h>
 2 
 3 int main(void)
 4 {
 5     char str[] = "Hello";
 6     
 7     printf("%s\n", str);
 8     printf("%s\n", &str[0]);
 9     printf("%p\n", str);
10 
11     return 0;
12 }
复制代码

为什么第7、8行的结果一样? %s有什么内涵?

clang编译报警:clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated

g++不报警告

菜鸟明的主页 菜鸟明 | 初学一级 | 园豆:186
提问于:2017-11-04 22:57
< >
分享
最佳答案
1

先解释一下问题3:

 1 int main(void)
 2 {
 3     char *str1="233345";//"233345"存储在文字常量区,str1为指向那个的首地址的指针,编译器认为str1指向内容不应当被修改,而str1类型不是const,所以爆warning
 4     const char* strtmp1="233345";//这样就不会爆warning
 5     //char str3[];//编译不通过
 6     char str[]="233345";//存储在栈上,根据用来初始化的字符串长度自动确定数组长度为7
 7     char str2[7]="233345";//存储在栈上
 8     str[1]='1';//可以
 9     str2[1]='1';//可以
10     //str1[1]='1';//段错误
11     return 0;
12 }

参考:http://blog.csdn.net/codingkid/article/details/6858395

http://blog.csdn.net/xyy410874116/article/details/6397549

对于第二个问题,从上面的参考资料可以得知,这样定义char str[6]=".....";得到的是一个字符数组,数组内内容被初始化为了".....",也就是str中的"....."是存储在栈上的而不是常量区。

对于第四个问题,我想C内部printf("%s")的实现应该类似于这样(只是示意,当然不是真的实现)

void my_out(const char *t)
{
    for(;*t!='\0';t++)
        putchar(*t);
}

这是由于C约定合法字符串最后有'\0'。因此:

int main()
{
    char str[] = "Hello";//str初始化用的"Hello"字符串最后会自动添加'\0'
    char wstr = 't';//wstr只是一个字符,自然不会有'\0'
    char wstr2[5]="Hell";
    wstr2[4]='o';//wstr2最后缺少'\0'
    printf("%s\n",str);
    //printf("%s\n",wstr);//段错误
    //printf("%s\n",wstr2);//段错误,也可能没有,反正运行不正常就是了
    return 0;
}

对于第一个,

参考一下https://www.zhihu.com/question/52252124

就是c++的cout如果接受到指向字符的指针,就会用跟C处理printf("%s")类似的方式去做。

因此:

char ch='1';
cout<<&ch;

就会出现奇怪的事情。

11行传的就是一个指向字符(str[0])的指针。

10行由于c/c++不支持直接以数组作为参数,str降阶成了&str[0]。(事实上cout字符数组的时候,这样的方式才是正常的吧...)

12行传去的是一个指向一个字符数组的指针。

收获园豆:10
hehe_54321 | 小虾三级 |园豆:750 | 2017-11-05 08:56

跪谢!Thank you very much!!!

菜鸟明 | 园豆:186 (初学一级) | 2017-11-05 10:25
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册