(C语言)sizeof与strlen的区别,以及有关习题练习
一·sizeof与strlen的区别
在C语言中,sizeof
和strlen
是两个常用的工具,但它们的功能和使用场景有所不同。以下是基于我搜索到的资料对这两个概念的详细解析:
1. 定义与作用
-
sizeof:
sizeof
是一个操作符,用于计算变量或类型所占的内存字节数。- 它可以应用于任何类型的数据,包括基本数据类型、数组、结构体等。
sizeof
在编译时计算其值,因此可以用于定义数组维数等。- 返回值类型为
size_t
,通常在头文件stddef.h
中定义。
-
strlen:
strlen
是一个函数,用于计算以空字符\0
结尾的字符串中的字符个数。- 它不包括字符串末尾的
\0
字符。 strlen
在运行时计算其值,因此需要包含string.h
头文件。- 参数必须是字符型指针(
char*
),且必须是以\0
结尾的字符串。
2. 参数类型
-
sizeof:
- 适用于所有数据类型:基本类型(
int
、char
等)、数组、结构体、指针等。 - 例如:
sizeof(int)
、sizeof(a)
,其中a
是一个变量。(ps:这个括号可以省略掉 如 a) -
#include <stdio.h> int main() { int a = 22; printf("%zd\n", sizeof a); printf("%zd\n", sizeof (a)); printf("%zd\n", sizeof(int )); //printf("%zd\n", sizeof int); return 0; }
- 适用于所有数据类型:基本类型(
-
-
strlen:
-
-
仅适用于以
参数必须是字符型指针(\0
结尾的字符串(字符数组或字符指针)。char*
),且必须是以\0
结尾的字符串。(用于获取字符串的实际长度(直到遇到\0
为止,且不包含\0
)。) - 例如:
strlen("Hello, world!")
。
-
3. 对字符串的处理
-
sizeof
计算字符串的总内存大小(包括末尾的\0
)。
例如:char str[] = "hello"; printf("%zu\n", sizeof(str)); // 输出 6(5个字符 + 1个 '\0')
-
strlen
计算字符串的实际字符数(不包括\0
)。
例如:
char str[] = "hello";
printf("%zu\n", strlen(str)); // 输出 5
总结
sizeof
是一个操作符,用于计算变量或类型所占的内存字节数,适用于任何类型的数据。strlen
是一个函数,用于计算以空字符\0
结尾的字符串中的字符个数,不包括\0
字符。sizeof
在编译时计算其值,而strlen
在运行时计算其值。sizeof
的参数可以是类型名或变量名,而strlen
的参数必须是字符型指针,并且必须是以\0
结尾的字符串。
二·数组名的理解
1. 数组名的本质
-
数组名是数组首元素的地址(即
&array[0]
),但在某些情况下会表现出不同的行为。 -
数组名本身不是指针变量,而是一个符号常量,代表数组的起始地址。
2. 数组名的两种关键行为
(1) 作为首元素地址
-
在大多数表达式中,数组名会被隐式转换为指向数组首元素的指针(类型为
element_type*
)。int arr[5] = {1, 2, 3, 4, 5}; int *p = arr; // arr 退化为 &arr[0]
(2) 作为整个数组的标识符
在以下两种情况下,数组名不会被退化为指针,而是表示整个数组:
sizeof(arr)
:计算的是整个数组占用的字节数。int arr[5]; printf("%zu\n", sizeof(arr)); // 输出 20(假设 int 为 4 字节)
&arr
:取数组的地址,类型为int (*)[5]
(指向整个数组的指针)。int arr[5]; int (*ptr_to_array)[5] = &arr; // 类型是 int(*)[5]
总结
-
数组名是首元素地址,但在
sizeof
和&
操作中代表整个数组。 -
数组名不是指针变量,而是一个固定的符号常量。
三·习题练习
int main()
{
int a[] = { 1,2,3,4 };
printf("%zd\n", sizeof(a)); //sizeof(数组名), 4*4 = 16
printf("%zd\n", sizeof(a + 0)); //a就是首元素的地址,a+0还是首元素的地址,计算的是地址的大小: 4/ 8
printf("%zd\n", sizeof(*a)); //a就是首元素的地址,*a就是首元素.计算的是首元素的大小:4个字节
printf("%zd\n", sizeof(a + 1)); //a就是首元素的地址,a+1是第二个元素的地址,计算的是地址的大小: 4 / 8
printf("%zd\n", sizeof(a[1])); //计算的是第二个元素的大小,4
printf("%zd\n", sizeof(&a));//&a - 取出的是数组的地址. 是地址都是4或8个字节
//&a + 1 跳过多少个字节: 16
//*&a 这里的解引用访问到16个字节
//int (*)[4]
printf("%zd\n", sizeof(*&a)); //16
//解释1*&a, * 和 &抵消了,等于sizeof(a)
// 解释2 先&a取到a的地址 再*解用用 [1],[2],[3],[4]
printf("%zd\n", sizeof(a)); //16
printf("%zd\n", sizeof(&a + 1)); //&a+1是跳过整个数组,指向4的后面,其实也是地址,是地址就是4 / 8个字节
printf("%zd\n", sizeof(&a[0])); //&a[0]就是首元素,4 8 个字节
printf("%zd\n", sizeof(&a[0] + 1)); //&a[0] + 1是第二个元素的地址. 8
return 0;
}
注意 现在的情况是在64 的环境下运行 如果在86的环境下 地址字节为8
难点解释:
1·
printf("%zd\n", sizeof(*&a)); //16
// 解释1 *&a, * 和 &抵消了,等于sizeof(a)
// 解释2 先&a取到a的地址 再*解运用 计算a的数组 [1],[2],[3],[4]
2·
printf("%zd\n", sizeof(&a + 1));
//&a+1是跳过整个数组,指向4的后面,其实也是地址,是地址就是4 / 8个字节
从零开始,步步为营
不要害怕C语言的复杂性,每个人都是从零开始的。只要你坚持学习,每天进步一点点,终会看到自己的成长。
每日都会分享习题练习,加油练起来吧!!!
下篇分享一些可以练习习题的网站
关注一手呗