黑马程序员技术交流社区

标题: 有个问题,大家看看 [打印本页]

作者: 完美世界    时间: 2014-6-26 19:14
标题: 有个问题,大家看看
先看代码:
#include <stdio.h>
int main()
{
    char c[]="ok";
    int a=-65;
    char c1[]={'n','o'};
    printf("%s\n",c);
    return 0;
}
(我用的苹果本)我的运行结果是:no????

我想问的是:4个问号我可以理解,但是在其后没有输出字符串ok,就说明4个问号后还有一个字符是'\0'。那是不是说明c1字符数组后有5个字节?我想的是在c1字符数组后的存储单元应该是变量a,有4个字节。变量a之后是c字符数组。

是不是我想的那个地方有出入?请大家帮忙看看~~


作者: 完美世界    时间: 2014-6-26 21:37
代码打错了一行。。输出语句应该是:printf("%s\n",c1);
作者: 诸葛佰通    时间: 2014-6-26 22:17
本帖最后由 诸葛佰通 于 2014-6-26 22:19 编辑

不知道你要的是不是这个结果?我的也是苹果本,完全拷贝你的代码,打印出来是有ok的。
如下图:




作者: 这个夏天的芬芳    时间: 2014-6-26 22:58
{:2_31:}{:2_31:}{:2_31:}{:2_31:}{:2_31:}{:2_31:}
作者: 骑着飞机去看海    时间: 2014-6-26 23:26
我的也是ok啊 我改成c1 就变成 no????^ok 这个了,怎么会是on ,楼主在试试??

作者: 董月峰    时间: 2014-6-27 07:25
c1是个字符数组,不是字符串,后面????是因为你没定义字符数组的长度。若在字符数组里面加个‘\0’应该就么有????号了,楼主也可以用strlen函数试试
作者: 完美世界    时间: 2014-6-27 08:10
董月峰 发表于 2014-6-27 07:25
c1是个字符数组,不是字符串,后面????是因为你没定义字符数组的长度。若在字符数组里面加个‘\0’应该 ...

那三个变量的定义顺序,以及输出方式是我故意安排的,我的疑问是:no后面不光有4个问号,最后还有一个'\0'否则就不会停下输出。然而c1字符数组没有'\0'那么会接着输出他后面内存地址中的数据也就是我定义的int型的a,而a是4个字节,一个字符是一个字节。会出现4个问号加一个'\0'让我很疑惑~~
作者: 完美世界    时间: 2014-6-27 08:12
诸葛佰通 发表于 2014-6-26 22:17
不知道你要的是不是这个结果?我的也是苹果本,完全拷贝你的代码,打印出来是有ok的。
如下图:

图看不到啊~~~最后输出的时c1,我开始写错了些成了c。看不到你得代码,不知道你是输出的哪个~~
作者: 完美世界    时间: 2014-6-27 08:14
骑着飞机去看海 发表于 2014-6-26 23:26
我的也是ok啊 我改成c1 就变成 no????^ok 这个了,怎么会是on ,楼主在试试??
...

我的结果是:no????
不是on呀~,你输出的这个结果和我最后要问的道理相同。就是no后面为什么有5个字符
作者: 零下_1°    时间: 2014-6-27 09:46
字符串常量不是%c吗?  printf("%c\n",c);  这么写应该没问题吧
作者: 1014917278    时间: 2014-6-27 09:47
内存是从大到小分配的,你在中间定义了一个整型变量,所以会出现????,我试了几次一定情况下它输出到整形变量a就结束了,后面的ok并没有输出所以4个问号
作者: 完美世界    时间: 2014-6-27 10:09
1014917278 发表于 2014-6-27 09:47
内存是从大到小分配的,你在中间定义了一个整型变量,所以会出现????,我试了几次一定情况下它输出到整 ...

嗯,我问的就是,ok没有输出是因为他前面有了'\0',而且还有4个问号,也就是5个字节。而我在中间定义的int a 只占据4个字节。~
作者: liulinjie    时间: 2014-6-27 15:25
完美世界 发表于 2014-6-27 10:09
嗯,我问的就是,ok没有输出是因为他前面有了'\0',而且还有4个问号,也就是5个字节。而我在中间定义的in ...

你可以打印 c1 &a 和 c 看看它们的地址.
在定义变量的时候, **它们不一定是连续存储的**, 很可能在 a 和 c 之间还有没有被赋值的内存空间, 那里可能有一个字节是 0000 0000.

我试了一下, 在我的Xcode里, a 的起始地址是 0x...28, c 的起始地址是 0x...2d, 因为 a 只占四个字节, 说明 0x...2c这个字节是空的, 而它碰巧是'\0'.
作者: liulinjie    时间: 2014-6-27 15:32
嗯... 我以前也挺好奇内存中是怎么回事的, 其实还可以定义一个 char* 类型的指针, 把 a 后面地址中的内存*逐个字节*的打印出来看一下,

char *p = (char *)&a;         // 从 a 的地址开始
for (int i = 0; i < 7; i++)    // 一共查看7个字节的内容
{
        // 因为p是char*, 所以每次p+1就过一个字节
        printf("%d\n", *(p+i));    // 读取每个字节的内容, 并打印出它对应的整数值
}

打印出来会发现, 前4个字节都是负数 (-65的二进制码占的四个字节), 第五个字节是0, 第六个才是111, 即'o', 第七个是107, 即'k'.

反正, 关键就是, 变量不总是连续存储的
c1和a是连续的, a和c是不连续的, 至于为什么有的连续有的不连续我就不知道了...


作者: 完美世界    时间: 2014-6-27 15:54
liulinjie 发表于 2014-6-27 15:32
嗯... 我以前也挺好奇内存中是怎么回事的, 其实还可以定义一个 char* 类型的指针, 把 a 后面地址中的内存* ...

谢谢,耐心解答。有代码还有注释~~
你说的我都看了,我在发帖之前也做了很多测试,看了MJ老师的视频,看到两个字符数组定义时地址连续了,就自己做了些测试。也在想是不是定义变量时地址不一定是连续的。你说的很有道理,还是得说谢了~
作者: 曹雨    时间: 2014-6-27 16:03
我只看到你说的“我用的苹果本”表示羡慕嫉妒恨
作者: a1130003724    时间: 2014-6-27 16:16
路过   沙发




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2