我的一位同事最近说上述声明不是类型安全的,我应该使用其他东西,因为你需要尽可能多的类型安全结构来减少可能的错误数量。
虽然我同意类型安全,但我有点困惑,因为这是有问题的代码类型(只修改了数据[]的内容和长度)
unsigned char data[] = {1,2,3,4,5};
int data_len = sizeof(data) / sizeof(data[0]);
哪种部件不安全?
毋庸置疑,除了评论之外,同事不会进一步解释。
PS:这用于将初始化数据复制到构造函数的类中,此处不存在C ++ 11编译器,因此我们不能使用std :: array或其他花式数组初始化。技术。
答案 0 :(得分:5)
也许你的同事意味着使用带有指针的表达式会产生意想不到的结果。初学者经常犯这个错误。例如
void f( unsigned char data[] )
{
int data_len = sizeof(data) / sizeof(data[0]);
//...
}
//...
unsigned char data[] = {1,2,3,4,5};
f( data );
因此,在一般情况下,使用模板函数而不是表达式会更安全。例如
template <class T, size_t N>
inline size_t size( const T ( & )[N] )
{
return N;
}
考虑到C ++ 11中有模板结构std::extent
,可用于获取维度的大小。
例如
int a[2][4][6];
std::cout << std::extent<decltype( a )>::value << std::endl;
std::cout << std::extent<decltype( a ), 1>::value << std::endl;
std::cout << std::extent<decltype( a ), 2>::value << std::endl;
答案 1 :(得分:2)
一个可能的问题是,如果在堆上使用new创建数据,则不会获得长度,而是与您所在系统上的指针长度相关的某些值。
char* data = new char[5];
//sizeof(data) is dependent on system
答案 2 :(得分:1)
sizeof data / sizeof *data
非常好并且类型安全。但你必须能够保证:
如果您未使用模板提供阵列,则可以获得诊断信息:
template <typename T, size_t n> inline size_t elements_of(const T&[n])
{
return n;
}
答案 3 :(得分:-1)
#include<stdio.h>
void fun(int arr[])
{
/* sizeof cannot be used here to get number of elements in array*/
int arr_size = sizeof(arr)/sizeof(arr[0]); /* incorrect use of sizeof*/
}
int main()
{
int arr[4] = {0, 0 ,0, 0};
fun(arr);
return 0;
}
在C中,数组参数衰减为指针。因此表达式sizeof(arr)/sizeof(arr[0])
变为sizeof(int*)/sizeof(int)
,导致IA32机器为1。
因此,在这种情况下,不应使用sizeof
来获取元素数量。必须将数组大小(或长度)的单独参数传递给fun()
。因此,用于打印数字的更正程序是:
#include<stdio.h>
void fun(int arr[], size_t arr_size)
{
int i;
for (i = 0; i < arr_size; i++)
{
arr[i] = i;
}
}
int main()
{
int i;
int arr[4] = {0, 0 ,0, 0};
fun(arr, sizeof arr / sizeof arr[0]);
for(i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
printf(" %d ", arr[i]);
getchar();
return 0;
}