在 C++ 中将数组作为函数参数传递

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/444746/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:22:57  来源:igfitidea点击:

Passing an array as a function parameter in C++

c++arrayspointersparametersarguments

提问by Yuval Adam

In C++, arrays cannot be passed simply as parameters. Meaning if I create a function like so:

在 C++ 中,数组不能简单地作为参数传递。这意味着如果我创建一个像这样的函数:

void doSomething(char charArray[])
{
    // if I want the array size
    int size = sizeof(charArray);
    // NO GOOD, will always get 4 (as in 4 bytes in the pointer)
}

I have no way of knowing how big the array is, since I have only a pointer to the array.

我无法知道数组有多大,因为我只有一个指向数组的指针。

Which way do I have, without changing the method signature, to get the size of the array and iterate over it's data?

在不更改方法签名的情况下,我有哪种方法来获取数组的大小并迭代它的数据?



EDIT:just an addition regarding the solution. If the char array, specifically, was initialized like so:

编辑:只是关于解决方案的补充。如果 char 数组,具体来说,是这样初始化的:

char charArray[] = "i am a string";

then the \0is already appended to the end of the array. In this case the answer (marked as accepted) works out of the box, so to speak.

那么\0已经附加到数组的末尾。在这种情况下,答案(标记为已接受)开箱即用,可以这么说。

回答by Josh Kelley

Use templates. This technically doesn't fit your criteria, because it changes the signature, but calling code does not need to be modified.

使用模板。这在技术上不符合您的标准,因为它更改了签名,但不需要修改调用代码。

void doSomething(char charArray[], size_t size)
{
   // do stuff here
}

template<size_t N>
inline void doSomething(char (&charArray)[N])
{
    doSomething(charArray, N);
}

This technique is used by Microsoft's Secure CRT functionsand by STLSoft's array_proxyclass template.

Microsoft 的Secure CRT 函数和 STLSoft 的array_proxy类模板使用了这种技术。

回答by Reunanen

Without changing the signature? Append a sentinel element. For char arrays specifically, it could be the null-terminating '\0'which is used for standard C strings.

不改签名?附加一个哨兵元素。特别是对于 char 数组,它可能'\0'是用于标准 C 字符串的空终止符。

void doSomething(char charArray[])
{
    char* p = charArray;
    for (; *p != '
void doSomething(char* charArray)
{
    // Cast unnecessary but I prefer explicit type conversions.
    std::size_t length = static_cast<std::size_t>(static_cast<unsigned char>(charArray[0]));
    // … do something.
}
'; ++p) { // if '
void foo(char a[])
{
    // Do something...
}
' happens to be valid data for your app, // then you can (maybe) use some other value as // sentinel } int arraySize = p - charArray; // now we know the array size, so we can do some thing }

Of course, then your array itself cannot contain the sentinel element as content. For other kinds of (i.e., non-char) arrays, it could be any value which is not legal data. If no such value exists, then this method does not work.

当然,那么您的数组本身不能包含哨兵元素作为内容。对于其他类型(即非字符)数组,它可以是任何不是合法数据的值。如果不存在这样的值,则此方法不起作用。

Moreover, this requires co-operation on the caller side. You really have to make sure that the caller reserves an array of arraySize + 1elements, and alwayssets the sentinel element.

此外,这需要呼叫方的合作。您确实必须确保调用者保留一个arraySize + 1元素数组,并始终设置哨兵元素。

However, if you really cannot change the signature, your options are rather limited.

但是,如果您确实无法更改签名,那么您的选择就非常有限。

回答by Konrad Rudolph

It actually used to be a quite common solution to pass the length in the first element of the array. This kind of structure is often called BSTR(for “BASIC string”), even though this also denoted different (but similar) types.

在数组的第一个元素中传递长度实际上曾经是一个非常常见的解决方案。这种结构通常被称为BSTR(对于“BASIC 字符串”),尽管这也表示不同(但相似)的类型。

The advantage over the accepted solution is that determining the length using a sentinel is slow for large strings. The disadvantage is obviously that this is a rather low-level hack that respects neither types nor structure.

与公认的解决方案相比,优势在于使用哨兵确定大字符串的长度很慢。缺点很明显,这是一个相当低级的 hack,既不考虑类型也不考虑结构。

In the form given below it also only works for strings of length <= 255. However, this can easily be expanded by storing the length in more than one byte.

在下面给出的形式中,它也仅适用于长度 <= 255 的字符串。但是,这可以通过将长度存储在一个以上的字节中来轻松扩展。

void foo(char * a)
{
    // Do something
}

回答by John K?llén

In general when working with C or low-level C++, you might consider retraining your brain to never consider writing array parameters to a function, because the C compiler will always treat them as pointers anyway. In essence, by typing those square brackets you are fooling yourself in thinking that a real array is being passed, complete with size information. In reality, in C you can only pass pointers. The function

通常,在使用 C 或低级 C++ 时,您可能会考虑重新训练您的大脑,不要考虑将数组参数写入函数,因为无论如何 C 编译器总是将它们视为指针。从本质上讲,通过键入这些方括号,您会误以为正在传递一个真实的数组,并带有大小信息。实际上,在 C 中你只能传递指针。功能

void foo(char * a)
{
    int cplusplus_len = reinterpret_cast<std::size_t *>(a)[-1];
    int c_len = ((size_t *)a)[-1];
}

is, from the point of view of the C compiler, exactly equivalent to:

从 C 编译器的角度来看,完全等同于:

##代码##

and obviously that nekkid char pointer contains no length information.

很明显,nekkid 字符指针不包含长度信息。

If you're stuck in a corner and can't change the function signature, consider using a length prefix as suggested above. A non-portable but compatible hack is to specify the array length in an size_t field located beforethe array, something like this:

如果您被困在角落并且无法更改函数签名,请考虑使用上面建议的长度前缀。一个不可移植但兼容的 hack 是在位于数组之前的size_t 字段中指定数组长度,如下所示:

##代码##

Obviously your caller needs to create the arrays in the appropriate way before passing them to foo.

显然,您的调用者需要在将数组传递给 foo 之前以适当的方式创建数组。

Needless to say this is a horrible hack, but this trick can get out of trouble in a pinch.

不用说这是一个可怕的黑客,但是这个技巧可以在紧要关头摆脱困境。

回答by Jimmy

if it's nullterminated, strlen() would work.

如果它是空终止的, strlen() 会起作用。

回答by finnw

You can't determine the size from charArrayalone. That information is not automatically passed to the function.

你不能charArray单独确定大小。该信息不会自动传递给函数。

Of course if it's a null-terminated string you can use strlen(), but you have probably considered that already!

当然,如果它是一个以空字符结尾的字符串,您可以使用strlen(),但您可能已经考虑过了!

Consider passing a std::vector<char>& parameter, or a pair of pointers, or a pointer plus a size parameter.

考虑传递一个std::vector<char>& 参数,或者一对指针,或者一个指针加上一个 size 参数。

回答by falstro

This is actually more C than C++, in C++ you'd probably rather use a std::vector. However, in C there's no way to know the size of an array. The compile will allow you to do a sizeof if the array was declared in the current scope, and only if it was explicitly declared with a size (EDIT:and "with a size", I mean that it was either declared with an integer size or initialized at declaration, as opposed to being passed as a parameter, thanks for the downvote).

这实际上比 C++ 更 C,在 C++ 中,您可能更愿意使用 std::vector。但是,在 C 中无法知道数组的大小。如果数组在当前范围内声明,则编译将允许您执行 sizeof,并且仅当它显式声明为一个大小(编辑:和“一个大小”,我的意思是它要么用一个整数大小声明或在声明时初始化,而不是作为参数传递,感谢您的反对)。

The common solution in C is to pass a second parameter describing the number of elements in the array.

C 中的常见解决方案是传递描述数组中元素数量的第二个参数。

EDIT:
Sorry, missed the part about not wanting to change the method signature. Then there's no solution except as described by others as well, if there's some data that is not allowed within the array, it can be used as a terminator (0 in C-strings, -1 is also fairly common, but it depends on your actual data-type, assuming the char array is hypothetical)

编辑:
抱歉,错过了不想更改方法签名的部分。那么除了其他人的描述之外没有其他解决方案,如果数组中不允许有一些数据,则可以将其用作终止符(C字符串中的0,-1也很常见,但这取决于您的实际数据类型,假设 char 数组是假设的)

回答by AShelly

In order for a function to know the number of items in an array that has been passed to it, you must do one of two things:

为了让函数知道传递给它的数组中的项数,您必须执行以下两项操作之一:

  1. Pass in a size parameter
  2. Put the size information in the array somehow.
  1. 传入一个大小参数
  2. 以某种方式将大小信息放入数组中。

You can do the latter in a few ways:

您可以通过以下几种方式执行后者:

  • Terminate it with a NULL or some other sentinel that won't occur in normal data.
  • store the item count in the first entry if the array holds numbers
  • store a pointer to the last entry if the array contains pointers
  • 用 NULL 或其他一些不会出现在正常数据中的标记来终止它。
  • 如果数组包含数字,则将项目计数存储在第一个条目中
  • 如果数组包含指针,则存储指向最后一个条目的指针

回答by Percy Stainwall

try using strlen(charArray); using the cstring header file. this will produce the number of characters including spaces till it reaches the closing ".

尝试使用 strlen(charArray); 使用 cstring 头文件。这将产生包括空格在内的字符数,直到它达到结束“。

回答by t.g.

You are guarranteed to receive 4 in a 32-bit PC and that's the correct answer. because of the reason explained hereand here. The short answer is, you are actually testing the sizeof a pointer rather than an array, because "the array is implicitly converted, or decays, into a pointer. The pointer, alas, doesn't store the array's dimension; it doesn't even tell you that the variable in question is an array."

保证在 32 位 PC 中收到 4,这是正确答案。因为这里这里解释的原因。简短的回答是,您实际上是在测试指针而不是数组的大小,因为“数组被隐式转换或衰减为指针。唉,指针不存储数组的维度;它不甚至告诉你有问题的变量是一个数组。”

Now that you are using C++, boost::arrayis a better choice than raw arrays. Because it's an object, you won't loose the dimention info now.

现在您使用的是 C++,boost::array是比原始数组更好的选择。因为它是一个对象,所以您现在不会丢失尺寸信息。