我已经在hackerrank问题上写了这个函数。
int lonelyInteger (int a[], int n) {
int i, b[99] = {0};
for (i = 0; i < n; i ++) {
b[a[i]] ++;
}
for (i = 0; i < 100; i ++) {
if (b[i] == 1) {
return i;
}
}
}
但是我收到了这个编译错误。
solution.c: In function 'lonelyInteger':
solution.c:13:1: error: control reaches end of non-void function [-Werror=return-type]
}
^
我使用了逻辑,因此它必须在i = 0到i = 99之间返回。但是它的编译器给出了错误。所以我的问题是有必要在最后使用return语句(或者是一个好的做法)?
PS - 我在最后写了一个随机的return语句,它运行正常。
PPS - 如果您正在考虑b [i]是否永远不等于1,那么事实并非如此。根据问题,对于某些i = {0,1,2 ......,98},它必须等于1。
答案 0 :(得分:1)
编译器无法知道您的return语句将执行。 您可以添加包含某种错误代码的默认返回值,或者断言;如果你确定该函数应该在
之前返回答案 1 :(得分:1)
未在所有程序控制路径上定义显式return
。
您的编译器警告您:未从非void函数返回值的行为是 undefined 且编译器不够聪明(或者它不可能要知道程序控制将一直运行到函数的末尾。
代替冗余的return
,您可以使用assert
语句。一个好的编译器应该不显示警告。
答案 2 :(得分:1)
您声明b
有99个元素,这意味着它们的编号从0到 98 ,而不是99;你的第二个循环冒险跑掉该阵列的边缘。您需要声明b
包含100个元素或从0到99循环。
避免使用魔法数字;为数组大小和循环计数器使用符号常量:
#define RANGE_MAX 100
...
int b[RANGE_MAX] = {0};
您可以按如下方式重构循环;
for ( i = 0; i < RANGE_MAX && b[i] != 1; i++ )
; // empty loop body
return i;
这会将return
语句移到循环体之外,从而避免错误。
您应该添加一个检查,每个a[i]
的范围是0到99,如下所示:
for ( i = 0; i < n; i++ )
{
assert( a[i] >= 0 && a[i] < RANGE_MAX );
b[a[i]]++;
}
问题是,越界数组访问不能保证崩溃,或以任何其他可预测的方式运行;您的代码可能会彻底崩溃,可能会导致输出错误,可能会导致状态错误导致其在执行后期崩溃,或者可能会在没有问题的情况下运行完成。断言将允许您的代码在任何a[i]
超出范围的情况下以一致,明确定义的方式运行。