7

C语言陷阱与技巧第11节,sizeof(数组名)并不等于数组长度,怎样用它计算数组长度呢?

 3 years ago
source link: https://blog.popkx.com/c-language-traps-and-techniques-section-11-sizeof-array-name-is-not-equal-to-the-length-of-the-array-how-to-use-it-to-calculate/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

C语言陷阱与技巧第11节,sizeof(数组名)并不等于数组长度,怎样用它计算数组长度呢?

发表于 2019-04-28 08:04:33   |   已被 访问: 322 次   |   分类于:   C语言   |   暂无评论

在C语言程序开发中,sizeof() 是一个常用,也是一个非常有用的关键字,程序员常常使用它来获取变量占用内存的字节数。

称 sizeof() 为“关键字”,是因为虽然 sizeof() 使用起来很像一个函数,但是它与函数还是有很大区别的,这一点本专栏之前的章节讨论过。

7df5da4809835689c3a85db00da77342.png

小技巧:避免“硬解码”造成的代码维护困难

例如下面这样的例子,请看相关C语言代码如下:

float x;
size_t size = sizeof(x);

size 就等于 x 在内存中占用的字节数。在固定的机器平台,变量 x 是 float 类型,占用的内存字节数是固定的,例如 float 类型在 pc 上常占用 4 字节内存空间。之所以不直接使用 4,而是使用 sizeof(x) 是为了方便以后的维护。可以想象,若以后发现 x 需要使用更长的数据类型 double 才能满足需求,只需将 float x; 修改为 double x; 就可以了,size 会自己适应修改。

其实不仅C语言,在其他语言的程序开发中,都有这样一个原则:尽可能的避免硬解码出现,尽可能的避免重复功能出现,这样才有利于后期的维护——万一需要修改代码,只需要修改一处。

sizeof() 获取数组长度的“陷阱”

很多时候,利用 sizeof() 还可以获取数组的长度,例如下面这两行C语言代码:

char str[128];
size_t len = sizeof(arr);

len 此时等于 128,也即数组 str 的长度。但是如果数组不是 char 型的,而是其他类型的,len 还等于数组长度吗?编写如下C语言程序:

#include <stdio.h>
int main()
{
    int arr[10];
    size_t len = sizeof(arr);
    printf("%ld\n", len;
    return 0;
}

编译并执行这段C语言代码,得到如下结果:

# gcc t.c
# ./a.out 
40

显然,len 并不等于 arr 的长度 10,而是等于 40。很多C语言初学者看到这里会感到迷惑,怎么回事?sizeof(数组名)不是等于数组长度的吗?

sizeof() 关键字从来就不是计算长度的关键字,而是获取变量占内存空间字节数的关键字,这一点要谨记。str 是一个长度为 128 的 char 型数组,它占用内存字节数恰好等于 128,是因为 str 的每一个元素都是 char 型的,而 char 型占用一个字节的内存空间,因此此时 str 占用内存字节数和它的长度恰好是相等的。

再来看数组 arr,它的长度等于 10,但是它的每个元素都是 int 型的,而在我的机器上 int 型变量占用 4 字节内存空间,所以 arr 一共占用 40 字节内存空间,因此 sizeof(arr) 等于 40,而不是 10。

获取数组长度的小技巧

现在知道 sizeof() 有时无法直接获取数组长度的原因了,我们完全可以如下定义一个方法,用于计算数组长度,相关C语言代码如下,请看:

#define    arr_len(x)      ( sizeof(x)/sizeof(*x) )

sizeof(数组名)计算的是整个数组占用的内存字节数,而 sizeof(* x) 等价于 sizeof(x[0]),也即数组第一个元素占用的内存字节数。因为数组中各个元素的类型是相同的,所以 sizeof(* x) 也可以认为是每一个数组元素占用的内存字节数。上述宏定义就相当于:

数组长度 = 数组所有元素占用内存字节数 / 每个元素占用内存字节数

这么看来, arr_len 就不难理解了。编写如下C语言程序测试一下 arr_len:

#include <stdio.h>
int main()
{
    char carr[10];
    int iarr[10];
    char *parr[10];

    printf("%ld %ld %ld\n", arr_len(carr), arr_len(iarr), arr_len(parr));

    return 0;
}

编译并执行上面这段C语言程序,得到如下输出:

# gcc t.c
# ./a.out 
10 10 10

显然,arr_len 计算其他类型数组的长度也不在话下。

阅读更多:   C语言


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK