笨办法学C 练习8:大小和数组

练习8:大小和数组

原文:Exercise 8: Sizes And Arrays

译者:飞龙

在上一个练习中你做了一些算术运算,不过带有'\0'(空)字符。这对于其它语言来说非常奇怪,因为它们把“字符串”和“字节数组”看做不同的东西。但是C中的字符串就是字节数组,并且只有不同的打印函数才知道它们的不同。

在我真正解释其重要性之前,我先要介绍一些概念:sizeof和数组。下面是我们将要讨论的一段代码:

#include <stdio.h>

int main(int argc, char *argv[])
{
    int areas[] = {10, 12, 13, 14, 20};
    char name[] = "Zed";
    char full_name[] = {
        'Z', 'e', 'd',
         ' ', 'A', '.', ' ',
         'S', 'h', 'a', 'w', '\0'
    };

    // WARNING: On some systems you may have to change the
    // %ld in this code to a %u since it will use unsigned ints
    printf("The size of an int: %ld\n", sizeof(int));
    printf("The size of areas (int[]): %ld\n",
            sizeof(areas));
    printf("The number of ints in areas: %ld\n",
            sizeof(areas) / sizeof(int));
    printf("The first area is %d, the 2nd %d.\n",
            areas[0], areas[1]);

    printf("The size of a char: %ld\n", sizeof(char));
    printf("The size of name (char[]): %ld\n",
            sizeof(name));
    printf("The number of chars: %ld\n",
            sizeof(name) / sizeof(char));

    printf("The size of full_name (char[]): %ld\n",
            sizeof(full_name));
    printf("The number of chars: %ld\n",
            sizeof(full_name) / sizeof(char));

    printf("name=\"%s\" and full_name=\"%s\"\n",
            name, full_name);

    return 0;
}

这段代码中我们创建了一些不同数据类型的数组。由于数组是C语言工作机制的核心,有大量的方法可以用来创建数组。我们暂且使用type name[] = {initializer};语法,之后我们会深入研究。这个语法的意思是,“我想要那个类型的数组并且初始化为{..}”。C语言看到它时,会做这些事情:

  • 查看它的类型,以第一个数组为例,它是int
  • 查看[],看到了没有提供长度。
  • 查看初始化表达式{10, 12, 13, 14, 20},并且了解你想在数组中存放这5个整数。
  • 在电脑中开辟出一块空间,可以依次存放这5个整数。
  • 将数组命名为areas,也就是你想要的名字,并且在当前位置给元素赋值。

areas的例子中,我们创建了一个含有5个整数的数组来存放那些数字。当它看到char name[] = "Zed";时,它会执行相同的步骤。我们先假设它创建了一个含有3个字符的数组,并且把字符赋值给name。我们创建的最后一个数组是full_name,但是我们用了一个比较麻烦的语法,每次用一个字符将其拼写出来。对C来说,namefull_name的方法都可以创建字符数组。

在文件的剩余部分,我们使用了sizeof关键字来问C语言这些东西占多少个字节。C语言无非是内存块的大小和地址以及在上面执行的操作。它向你提供了sizeof便于你理解它们,所以你在使用一个东西之前可以先询问它占多少空间。

这是比较麻烦的地方,所以我们先运行它,之后再解释。

你会看到什么

$ make ex8
cc -Wall -g    ex8.c   -o ex8
$ ./ex8
The size of an int: 4
The size of areas (int[]): 20
The number of ints in areas: 5
The first area is 10, the 2nd 12.
The size of a char: 1
The size of name (char[]): 4
The number of chars: 4
The size of full_name (char[]): 12
The number of chars: 12
name="Zed" and full_name="Zed A. Shaw"
$

现在你可以看到这些不同printf调用的输出,并且瞥见C语言是如何工作的。你的输出实际上可能会跟我的完全不同,因为你电脑上的整数大小可能会不一样。下面我会过一遍我的输出:

译者注:16位机器上的int是16位的,不过现在16位机很少见了吧。

5

我的电脑认为int的大小是4个字节。你的电脑上根据位数不同可能会使用不同的大小。

6

areas中含有5个整数,所以我的电脑自然就需要20个字节来储存它。

7

如果我们把areas的大小与int的大小相除,我们就会得到元素数量为5。这也符合我们在初始化语句中所写的东西。

8

接着我们访问了数组,读出areas[0]areas[1],这也意味着C语言的数组下标是0开头的,像Python和Ruby一样。

9~11

我们对name数组执行同样的操作,但是注意到数组的大小有些奇怪,它占4个字节,但是我们用了三个字符来打出"Zed"。那么第四个字符是哪儿来的呢?

12~13

我们对full_name数组执行了相同的操作,但它是正常的。

13

最后我们打印出namefull_name,根据printf证明它们实际上就是“字符串”。

确保你理解了上面这些东西,并且知道这些输出对应哪些创建的变量。后面我们会在它的基础上探索更多关于数组和存储空间的事情。

如何使它崩溃

使这个程序崩溃非常容易,只需要尝试下面这些事情:

  • full_name最后的'\0'去掉,并重新运行它,在valgrind下再运行一遍。现在将full_name的定义从main函数中移到它的上面,尝试在Valgrind下运行它来看看是否能得到一些新的错误。有些情况下,你会足够幸运,不会得到任何错误。
  • areas[0]改为areas[10]并打印,来看看Valgrind会输出什么。
  • 尝试上述操作的不同变式,也对namefull_name执行一遍。

附加题

  • 尝试使用areas[0] = 100;以及相似的操作对areas的元素赋值。
  • 尝试对namefull_name的元素赋值。
  • 尝试将areas的一个元素赋值为name中的字符。
  • 上网搜索在不同的CPU上整数所占的不同大小。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容