目录
在C语言中,sizeof和strlen是两个常用的关键字,用于获取数据的大小信息。尽管它们看起来相似,但它们的作用和用法有着本质的区别。在本博客中,我们将详细讨论sizeof和strlen的区别。
1. sizeof关键字
sizeof关键字用于获取类型或变量在内存中所占用的字节数。它是一个运算符,不是一个函数。它的语法为:
sizeof(type) // 获取类型的大小
sizeof(expression) // 获取表达式的结果类型的大小
以下是sizeof关键字的一些特点和使用注意事项:
- sizeof操作符返回一个`size_t`类型的值,代表给定对象的大小(以字节为单位)。
- 可以使用sizeof获取基本数据类型(如int、char)的大小,以及数组、结构体、联合体和指针的大小。
- sizeof是在编译时计算的,它并不对实际执行时的值进行评估。它根据类型或表达式的编译时类型来确定大小。
- 对于指针,sizeof返回指针本身的大小,而不是指针指向的内存空间的大小。
- 对于数组,sizeof返回整个数组所占的内存空间大小,而不是数组元素的个数。
- sizeof并不会求解指针所指向的内存的大小。例如,对于一个动态分配的数组或字符串,sizeof操作符不会告诉你它所占的实际空间。
下面是几个例子,演示了sizeof的使用:
#include <stdio.h>
int main() {
int num = 42;
printf("Size of int: %zu bytes\n", sizeof(int));
double arr[10];
printf("Size of arr: %zu bytes\n", sizeof(arr));
struct {
int x;
int y;
} point;
printf("Size of point: %zu bytes\n", sizeof(point));
int *ptr;
printf("Size of ptr: %zu bytes\n", sizeof(ptr));
return 0;
}
该程序将输出以下内容:
Size of int: 4 bytes
Size of arr: 80 bytes
Size of point: 8 bytes
Size of ptr: 8 bytes
解释:
- `sizeof(int)` 返回整型 `int` 在当前环境中所占用的字节数,通常为 4 个字节。
- `sizeof(arr)` 返回数组 `arr` 的总大小,即数组的长度乘以每个元素的大小。在本例中,数组 `arr` 的长度为 10,每个元素的类型为 `double`,在当前环境中,`double` 类型通常占用 8 个字节,所以 `sizeof(arr)` 返回 80 个字节。
- `sizeof(point)` 返回结构体 `point` 的总大小,即结构体内所有成员变量大小的总和。在本例中,结构体 `point` 内有两个整型成员变量,每个整型在当前环境中通常占用 4 个字节,所以 `sizeof(point)` 返回 8 个字节。
- `sizeof(ptr)` 返回指针 `ptr` 的大小,即指针本身所占用的字节数。在当前环境中,指针的大小通常为 8 个字节(64 位系统)。
在上述代码中,我们分别计算了int类型、数组arr、结构体point和指针ptr所占用的字节数。使用sizeof可以获得这些类型和变量的大小信息。
2. strlen函数
strlen函数用于计算字符串的长度,即字符串中字符的个数,不包括结尾的NULL字符。它定义在`<string.h>`头文件中,并有以下函数原型:
size_t strlen(const char *str)
以下是strlen函数的一些特点和使用注意事项:
- strlen函数接受一个指向字符串的指针(const char *str)作为参数,并返回一个`size_t`类型的值,代表字符串的长度。
- strlen通过逐个检查字符,直到遇到NULL字符('\0'),来确定字符串的长度。
- strlen仅适用于以NULL字符结尾的C字符串(字符数组),它无法直接计算非以NULL结尾的字符串的长度。
- 如果传递给strlen的指针是空指针(NULL),将导致未定义行为。因此,在使用strlen前应确保指针有效。
下面是一个示例,展示了strlen的使用:
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, world!";
size_t length = strlen(str);
printf("Length of str: %zu\n", length);
return 0;
}
该程序的控制台输出是:
Length of str: 13
这段代码的功能是计算字符串 "Hello, world!" 的长度并输出结果。使用 `strlen()` 函数计算字符串长度时,将结果存储在 `length` 变量中,并使用 `%zu` 格式说明符打印结果。`strlen()` 函数返回的类型是 `size_t`,它是无符号整数类型,适合用于表示内存大小和数组索引。
将上述代码编译并运行,将输出结果 "Length of str: 13",对应字符串 "Hello, world!" 的长度。需要注意的是,不包括末尾的空字符。
3. 返回值类型
- sizeof的返回类型是`size_t`,它是一种无符号整数类型。它的大小一般等于当前环境下可表示的最大对象的大小。
- strlen的返回类型也是`size_t`,表示字符串的长度。
由于sizeof和strlen的返回类型都是`size_t`,因此它们在此方面是相同的。
4. 作用对象
- sizeof可以用于任何数据类型,包括基本数据类型、结构体、联合体和指针等。
- strlen仅适用于以NULL字符结尾的C字符串(字符数组)。
这是使得sizeof和strlen在可操作对象上有重要区别的地方。sizeof关键字可以返回数据类型和变量的大小,而strlen函数仅适用于以NULL字符结尾的字符串。
5. 计算方式
- sizeof是在编译时计算的,它根据类型或表达式的编译时类型来确定大小,而不会对实际运行时的值进行评估。
- strlen是在运行时计算的,它通过逐个检查字符,直到遇到NULL字符来确定字符串的长度。
因为sizeof是在编译时计算的,所以它适用于确定数据类型在内存中的大小或用于静态分配的数组和结构体。相比之下,strlen是在运行时根据传递的指针所指向的字符串来计算长度,因此它适用于动态分配的字符串。
6. 适用范围
- sizeof适用于任何已知类型和变量,包括编译时已知和运行时已知的对象。
- strlen仅适用于以NULL字符结尾的C字符串,并且要求字符串的地址已知。
这意味着无论类型是否已知,sizeof都可以用于计算其大小。然而,要使用strlen,必须有以NULL字符结尾的字符串,并且要传递字符串的地址。
7. 使用场景
sizeof的使用场景:
- 计算数据类型的大小,如`sizeof(int)`、`sizeof(double)`。
- 计算数组的大小,如`sizeof(arr)`。
- 计算结构体或联合体的大小,如`sizeof(struct Point)`。
- 计算指针的大小,如`sizeof(int*)`。
strlen的使用场景:
- 获取以NULL字符结尾的C字符串的长度,如`strlen(str)`。
8. 示例
sizeof的示例:
#include <stdio.h>
struct Point {
int x;
int y;
};
int main() {
int num = 42;
printf("Size of int: %zu bytes\n", sizeof(int));
double arr[10];
printf("Size of arr: %zu bytes\n", sizeof(arr));
struct Point point;
printf("Size of point: %zu bytes\n", sizeof(point));
int *ptr;
printf("Size of ptr: %zu bytes\n", sizeof(ptr));
return 0;
}
上述代码中,我们使用sizeof分别计算了int类型、数组arr、结构体Point和指针ptr的大小,并将结果输出到控制台。
strlen的示例:
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello, world!";
size_t length = strlen(str);
printf("Length of str: %zu\n", length);
return 0;
}
在这个示例中,我们使用strlen函数计算了字符串"Hello, world!"的长度,并将结果输出到控制台。
9. 注意事项
在使用sizeof和strlen时,请注意以下事项:
- sizeof是一个运算符,而strlen是一个函数。因此,在使用sizeof时不需要使用括号,而在使用strlen时需要在函数名后使用括号。
- sizeof可以运用于任何数据类型和变量,而strlen仅适用于以NULL字符结尾的C字符串。
- sizeof在编译时计算,而strlen在运行时计算。这意味着sizeof可以提供类型和变量的大小信息,而strlen可以计算字符串的长度。
10. 综合应用
在实际开发中,我们常常会结合使用sizeof和strlen,以便正确处理内存分配和字符串操作。例如,当我们使用malloc分配内存来存储字符串时,可以使用strlen函数获取该字符串的长度,然后使用sizeof来为所需的内存分配提供正确的大小。这样可以确保我们分配了恰好能够容纳该字符串的足够空间。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char input[100];
printf("Enter a string: ");
fgets(input, 100, stdin);
// 获取输入字符串的长度
size_t length = strlen(input);
// 分配足够的内存存储字符串
char *dynamicString = (char *)malloc(sizeof(char) * length);
if (dynamicString != NULL) {
strcpy(dynamicString, input);
printf("Dynamic string: %s\n", dynamicString);
free(dynamicString);
}
return 0;
}
这段代码使用了C语言的标准库函数来获取用户输入的字符串,并动态地分配内存来存储这个输入的字符串。
首先,我们声明了一个大小为100的字符数组"input",用于存储用户输入的字符串。然后使用fgets函数从标准输入(stdin)获取用户输入的字符串,并将其存储在input数组中。
接下来,调用strlen函数获取input数组中存储的字符串的长度,并将结果存储在变量length中。
然后,我们使用malloc函数动态分配内存,以存储与输入字符串长度相等的字符数组。这样做是为了确保我们分配了足够的内存来存储输入字符串。如果分配内存成功(即dynamicString不为NULL),我们使用strcpy函数将输入字符串复制到动态分配的内存区域中。
最后,我们可以打印出复制到dynamicString中的字符串,并在程序结束前使用free函数释放动态分配的内存。
这段代码的目的是展示如何处理用户输入的字符串,并且动态地为其分配所需的内存空间。