使用 sizeof 来获取数组的大小在某些情况下是可以的,但在涉及到函数参数时可能会有一些问题。 使用 sizeof 获取数组大小
当数组在当前作用域内声明时,可以使用 sizeof 来获取数组的大小。例如:
#include <cstdio>
int main() {
char buffer[10];
printf("Size of buffer: %zu\n", sizeof(buffer)); // 输出:10
return 0;
}
在这个例子中,sizeof(buffer) 返回的是数组的总大小(以字节为单位)。对于 buffer[10],返回值为 10。
sizeof 在函数参数中的限制
当数组作为参数传递给函数时,sizeof 可能无法按预期工作。原因是数组在函数参数中退化为指针,这时 sizeof 返回的是指针的大小,而不是数组的大小。
#include <cstdio>
void printSize(char buffer[]) {
printf("Size of buffer in function: %zu\n", sizeof(buffer)); // 输出:指针的大小(通常为 8 或 4)
}
int main() {
char buffer[10];
printf("Size of buffer in main: %zu\n", sizeof(buffer)); // 输出:10
printSize(buffer);
return 0;
}
在这个例子中,sizeof(buffer) 在 main 函数中返回 10,但在 printSize 函数中返回的是指针的大小(在64位系统上通常是8,在32位系统上通常是4)。
使用 _countof 宏
Microsoft 提供了 _countof 宏,用于在编译时获取数组的元素个数。这个宏的实现通常是这样的:
#define _countof(array) (sizeof(array) / sizeof(array[0]))
_countof 宏可以正确地在编译时计算数组的大小:
#include <cstdio>
void printSize(char buffer[], size_t size) {
printf("Size of buffer in function: %zu\n", size); // 输出传递的实际大小
}
int main() {
char buffer[10];
printf("Size of buffer in main: %zu\n", sizeof(buffer)); // 输出:10
printSize(buffer, _countof(buffer));
return 0;
}
在这个例子中,_countof(buffer) 返回数组的大小,结果是 10。
其实如果不想使用该方法,可以借鉴该方法,自己在函数外定义一个变量如
len=(sizeof(array) / sizeof(array[0])
,然后通过传参的方式传入函数内部。
为什么选择 scanf_s 需要数组大小
scanf_s 需要数组大小作为额外参数来进行边界检查,确保不会发生缓冲区溢出。这是提高安全性的一个重要措施:
#include <cstdio>
int main() {
char buffer[10];
// 使用 scanf_s 读取字符串,并提供数组大小
printf("Enter a string: ");
scanf_s("%9s", buffer, (unsigned)_countof(buffer)); // 提供数组大小,防止溢出
printf("You entered: %s\n", buffer);
return 0;
}
在这里,_countof(buffer) 提供了数组的大小,确保 scanf_s 不会写入超过 buffer 容量的数据,从而防止缓冲区溢出
总结
• 在当前作用域内,使用 sizeof 可以正确地获取数组的大小。
• 当数组作为函数参数传递时,sizeof 会退化为指针大小,不再表示数组的实际大小。
• 使用 _countof 宏可以在编译时获取数组的元素个数,适用于许多需要数组大小的场景。
• scanf_s 等安全函数需要提供数组大小来防止缓冲区溢出。