在C中返回值-1作为size_t返回值的后果是什么?

Jos*_*lls 5 c size-t

我正在读一本教科书,其中一个例子就是这样做的.下面,我以缩写形式复制了这个例子:

#include <stdio.h>
#define SIZE 100

size_t linearSearch(const int array[], int searchVal, size_t size);

int main(void)
{
    int myArray[SIZE];
    int mySearchVal;
    size_t returnValue;

    // populate array with data & prompt user for the search value

    // call linear search function
    returnValue = linearSearch(myArray, mySearchVal, SIZE);

    if (returnValue != -1)
        puts("Value Found");
    else
        puts("Value Not Found");
}

size_t linearSearch(const int array[], int key, size_t size)
{
    for (size_t i = 0; i < size; i++) {
        if (key == array[i])
            return i;
    }
    return -1;
}
Run Code Online (Sandbox Code Playgroud)

这有什么潜在的问题吗?我知道size_t被定义为无符号整数类型,所以如果我返回-1作为size_t返回值,似乎这可能会在某些时候遇到麻烦.

Jon*_*ler 2

您的编译器可能会决定抱怨比较有符号与无符号 \xe2\x80\x94 GCC 或 Clang 如果激发* \xe2\x80\x94 但否则“它有效”。在补码机器上(现在大多数机器),确实(size_t)-1与 \xe2\x80\x94 相同SIZE_MAX,正如评论中的扩展所讨论的,它对于补码或符号大小是相同的机,因为 C99 和 C11 标准的 \xc2\xa76.3.1.3 中的措辞)。

\n\n

使用(size_t)-1来指示“未找到”意味着您无法区分最大可能数组中的最后一个条目和“未找到”,但这很少是实际问题。

\n\n
\n

那么,这只是我最终可能遇到问题的一种边缘情况?

\n
\n\n

不过,该数组必须是 的数组char,足够大才能引起麻烦 \xe2\x80\x94,虽然 32 位计算机可以拥有 4 GiB 内存,但拥有所有这些内存是相当难以置信的内存致力于字符数组(对于 64 位机器来说,这不太可能成为问题;大多数机器不会运行到 16 艾字节内存)。所以这不是一个实际的边缘情况。

\n\n

在 POSIX 中,有一种ssize_t类型,即与 的大小相同的有符号类型size_t。您可以考虑使用它来代替size_t. (size_t)-1然而,根据我的经验,它会引起同样的焦虑。另外,在 32 位计算机上,您可以将 3 GiB 内存块视为 的数组char,但作为ssize_t返回类型,您无法使用超过 2 GiB \xe2\x80\x94 的内存,否则您\需要使用SSIZE_MIN(如果它存在;我不确定它是否存在)而不是作为-1信号值。

\n\n
\n\n

* \nGCC 或 Clang 必须受到相当大的刺激。仅仅使用-Wall是不够的;它需要-Wextra(或特定-Wsign-compare选项)来触发警告。因为我经常编译-Wextra,因此我意识到了这个问题;并不是每个人都那么警惕。

\n\n

比较有符号和无符号数量是由标准完全定义的,但可能会导致违反直觉的结果(因为小负数在转换为无符号值时显得非常大),这就是为什么编译器在要求这样做时会抱怨的原因。

\n

  • 据我了解,C 标准实际上保证将负数转换为无符号的行为类似于二进制补码,无论这是否是机器有符号整数的本机格式。我认为在所有情况下你都应该得到`SIZE_MAX` (2认同)
  • 对于分配,根据 §6.3.1.3,在所有情况下您都会得到“SIZE_MAX” (2认同)
  • @JonathanLeffler:§6.3.1.3“否则,如果新类型是无符号的,则通过比新类型可以表示的最大值重复加或减一来转换该值,直到该值在新类型的范围内类型。” (2认同)