C++ 使用整数指针操作时如何确定整数数组的结尾?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2736062/
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
How to determine the end of an integer array when manipulating with integer pointer?
提问by AKN
Here is the code:
这是代码:
int myInt[] ={ 1, 2, 3, 4, 5 };
int *myIntPtr = &myInt[0];
while( *myIntPtr != NULL )
{
cout<<*myIntPtr<<endl;
myIntPtr++;
}
Output: 12345....<junks>..........
For Character array: (Since we have a NULL character at the end, no problem while iterating)
对于字符数组:(因为我们在末尾有一个 NULL 字符,迭代时没有问题)
char myChar[] ={ 'A', 'B', 'C', 'D', 'E', 'int my_array[] = {1, 2, 3, 4, 5};
for(int& x : my_array)
{
cout<<x<<endl;
}
' };
char *myCharPtr = &myChar[0];
while( *myCharPtr != NULL )
{
cout<<*myCharPtr<<endl;
myCharPtr++;
}
Output: ABCDE
My question is since we say to add NULL character as end of the strings, we rule out such issues! If in case, it is rule to add 0 to the end of integer array, we could have avoided this problem. What say?
我的问题是,既然我们说在字符串的末尾添加 NULL 字符,我们排除了这样的问题!如果以防万一,规则是在整数数组的末尾添加 0,我们本可以避免这个问题。说啥?
回答by Vicente Botet Escriba
C-strings convention is that a char* finish by a '\0' char. For array or any other C++ container there are other idioms that can be applied. Next follows my preferences
C 字符串约定是 char* 以 '\0' 字符结束。对于数组或任何其他 C++ 容器,可以应用其他习惯用法。接下来按照我的喜好
The best way to iterate on sequences is to use the Range-based for-loop included on C++0x
迭代序列的最佳方法是使用 C++0x 中包含的基于范围的 for 循环
for(int* it = std::begin(array); it!=std::end(array); ++it)
{
cout<<*it<<endl;
}
If your compiler don't provide this yet, use iterators
如果您的编译器尚未提供此功能,请使用迭代器
for(int* it = &array[0]; it!=&array[sizeof(array)]; ++it)
{
cout<<*it<<endl;
}
And if you can not use neither std::begin/end
如果你不能使用 std::begin/end
int myInt[] ={ 1, 2, 3, 4, 5, -1 };
int *myIntPtr = &myInt[0];
while( *myIntPtr >= 0 )
{
cout<<*myIntPtr<<endl;
myIntPtr++;
}
P.S Boost.Foreach emulates the Range-based for-loop on C++98 compilers
PS Boost.Foreach 在 C++98 编译器上模拟基于范围的 for 循环
回答by Vicente Botet Escriba
In C++ the best solution is to use a std::vector, not an array. vectors carry their size around with them. The problem with using zero (or any other value) as a an end marker is that of course it can't appear elsewhere in the array. This is not so much of an issue for strings, as we rarely want to print the character with code zero, but it is an issue when using arrays of ints.
在 C++ 中,最好的解决方案是使用 std::vector,而不是数组。向量随身携带它们的大小。使用零(或任何其他值)作为结束标记的问题在于它当然不能出现在数组的其他地方。这对于字符串来说不是什么大问题,因为我们很少想用代码零打印字符,但在使用整数数组时这是一个问题。
回答by Gabriel ??erbák
What about using sizeof? http://www.cppreference.com/wiki/keywords/sizeof
使用 sizeof 怎么样?http://www.cppreference.com/wiki/keywords/sizeof
回答by Greg Hewgill
You can certainly decide on your own "sentinel" valueto store at the end of your array of integers. If your integers are always expected to be nonnegative, for example, you can use -1 as the sentinel value that marks the end of the array.
您当然可以决定将自己的“哨兵”值存储在整数数组的末尾。例如,如果您的整数总是非负的,您可以使用 -1 作为标记数组末尾的标记值。
"oneint myInt[]={1, 2, 3, 4, 5};
int myIntNumElements = sizeof(myInt) / sizeof(myInt[0]);
int *myIntEnd = myInt + myIntNumElelents;
for (int *myIntPtr = myInt; myInt != myIntEnd; myIntPtr++)
{
cout << *myIntPtr << endl;
}
twoint myInt[] ={ 100, 200, 300, 400, 500 };
int *myIntPtr = &myInt[0];
int *myIntPtr_end = myIntPtr + 5;
while(myIntPtr != myIntPtr_end)
{
cout<<*myIntPtr<<endl;
++myIntPtr;
}
threefor(i=0; i < sizeof(myInt); i++ )
{
cout<<*myIntPtr<<endl;
myIntPtr++;
}
" // there's an implicit '##代码##' appended in C/C++
回答by Péter T?r?k
The char value 0 has special meaning, standardized by convention and practice. The int value 0 does not, so this can't be a general rule. If it works in your specific case, you can go with it. However, in general it is better to just keep track of the length of integer arrays separately, since this works universally. Or use std::vector
or a similar container which handles that job for you.
char 值 0 具有特殊含义,由惯例和实践标准化。int 值 0 不是,所以这不是一般规则。如果它适用于您的特定情况,您可以使用它。但是,通常最好单独跟踪整数数组的长度,因为这普遍适用。或者使用std::vector
或类似的容器为您处理该工作。
回答by AnT
Firstly, we don't "add NULL character" at the end of the string. There's no such thing as "NULL character". We add zerocharacter, which is sometimes called "NUL character". But NULL
has absolutely nothing to do with it. NULL
is normally used in pointer context and not in character or integer context. Your comparisons like *myCharPtr != NULL
or *myIntPtr != NULL
will compile (due to the way NULL
is defined in C++), but make virtually no sense. If you are looking for a zero character in an array, you can check for it as *myCharPtr != '\0'
or as *myCharPtr != 0
or as simply *myCharPtr
, but never as *myCharPtr != NULL
.
首先,我们不会在字符串的末尾“添加 NULL 字符”。没有“空字符”这样的东西。我们添加零字符,有时称为“NUL 字符”。但NULL
与它完全无关。NULL
通常用于指针上下文而不是字符或整数上下文。您的比较喜欢*myCharPtr != NULL
或*myIntPtr != NULL
将编译(由于方式NULL
是在 C++ 中定义的),但实际上毫无意义。如果您要在数组中查找零字符,您可以按 as*myCharPtr != '\0'
或 as*myCharPtr != 0
或 as 简单地检查它*myCharPtr
,但绝不能像*myCharPtr != NULL
.
Secondly, the zero character is called zero character for a reason: it is equal to integer zero. Character type in C++ is just a plain integer type after all. The only reason we can use zero character as something special in string context is because it's meaning is reserved for that specific purpose. In general case in integer context reserving zero for that purpose is plainly impossible for obvious reasons: zero is as useful as any other integer value. Yet, if in your specific application integer zero can be used as a reserved value, feel free to use it that way. Or you can use any other integer value for that purpose. But in general case, referring to the question you ask in the title, there's no wayto determine the end of an array. It is your responsibility to know where the end is (by knowing the total number of elements or by marking the end with a reserved value of your choice or in some other way). There's no way to determine the end of an array even with strings, because all you can hope for is to find the end of the string, which is not necessarily the end of the array that stores that string.
其次,零字符被称为零字符是有原因的:它等于整数零。C++ 中的字符类型毕竟只是一个普通的整数类型。我们可以在字符串上下文中使用零字符作为特殊内容的唯一原因是因为它的含义是为特定目的保留的。通常情况下,在整数上下文中,出于显而易见的原因,为此目的保留零显然是不可能的:零与任何其他整数值一样有用。然而,如果在您的特定应用程序中整数零可以用作保留值,请随意使用它。或者您可以为此使用任何其他整数值。但在一般情况下,参考你在标题中提出的问题,没有办法确定数组的结尾。您有责任知道终点在哪里(通过了解元素的总数或用您选择的保留值或以其他方式标记终点)。即使使用字符串也无法确定数组的结尾,因为您所能希望的只是找到string 的结尾,这不一定是存储该字符串的数组的结尾。
If you explicitly added a zero to the end of your integer array, your first cycle would happily stop at it. For some reason you explicitly added \0
at the end of your character array (and the second cycle stops), but you didn't add a zero at the end of your integer array (and the first cycle doesn't stop). You are wondering why your first cycle didn't stop at zero? Becuse you didn't put that zero in there. It is that simple.
如果您明确地在整数数组的末尾添加了一个零,您的第一个循环会很高兴地停在它上面。出于某种原因,您\0
在字符数组的末尾明确添加(第二个循环停止),但您没有在整数数组的末尾添加零(第一个循环不会停止)。你想知道为什么你的第一个周期没有停在零?因为你没有把零放在那里。就是这么简单。
回答by Skizz
Both the ASCII and Unicode standard defines a character with value 0 as the NULL character, not an end-of-array/string marker. It is only C/C++ convention that strings are terminated with this character. Pascal uses a different notation. Also, the NULL character does not necessarily indicated the end of the array that contains the string. There are several Win32 API functions that use double null terminated strings (the open file dialog for one), like this:
ASCII 和 Unicode 标准都将值为 0 的字符定义为 NULL 字符,而不是数组结尾/字符串标记。字符串以该字符结尾只是 C/C++ 约定。Pascal 使用不同的符号。此外,NULL 字符不一定表示包含字符串的数组的结尾。有几个 Win32 API 函数使用双空终止字符串(打开文件对话框),如下所示:
##代码##This is valid C/C++ code, the NULL character does not mean the end of the array.
这是有效的 C/C++ 代码,NULL 字符并不意味着数组的结尾。
To adapt this idea of a NULL value to integer arrays means you have to sacrifice one of your integer values. If your data consists of a subset of the set of integers then this isn't a problem but if your data can consist of any integer value, then there is no way to detemine if a given integer is the end-of-array marker or a valid value. In this latter case, your need additional information about the number of elements in the array, either manually or automatically via a std::vector.
将 NULL 值的这种想法应用于整数数组意味着您必须牺牲一个整数值。如果您的数据由一组整数的子集组成,那么这不是问题,但如果您的数据可以由任何整数值组成,则无法确定给定的整数是否是数组结束标记或一个有效的值。在后一种情况下,您需要手动或通过 std::vector 自动获取有关数组中元素数量的附加信息。
回答by Edward Schaefer
The generic way of creating the end pointer for any array is as follows: First determine the number of elements in the array using sizeof(array)/sizeof(array[0])
. Note that sizeof appears twice because it returns the size of an item in bytes. So for a static array, this is the size of the array divided by the size of an element in the array. Then the end-pointer to an array is array+number_of_elements
. So this should work:
为任何数组创建结束指针的通用方法如下:首先使用 确定数组中元素的数量sizeof(array)/sizeof(array[0])
。请注意,sizeof 出现两次,因为它以字节为单位返回项目的大小。所以对于静态数组,这是数组的大小除以数组中元素的大小。那么数组的端点是array+number_of_elements
。所以这应该有效:
And now for some caveats:
现在有一些警告:
- The end pointer points to a location just after the end of the array! So
*myIntPtr
returns junk, not the value of the last element in the array. - This is only good for regular, static arrays!For containers, use the
begin
andend
member functions and iterators. This approach will work with any version of C++. However, if you are using C++-11 or later, it is advisable to use the
std::begin
andstd::end
functions in the for statement as follows:for (int *myIntPtr = std::begin(myInt); myIntPtr != std::end(myIntPtr); myIntPtr++)
This method is intended to be considered in addition to the other answers. Which one is best is a matter of context.
- 结束指针指向数组末尾之后的位置!所以
*myIntPtr
返回垃圾,而不是数组中最后一个元素的值。 - 这仅适用于常规的静态数组!对于容器,使用
begin
和end
成员函数和迭代器。 这种方法适用于任何版本的 C++。但是,如果您使用的是 C++-11 或更高版本,则建议在 for 语句中使用
std::begin
和std::end
函数,如下所示:for (int *myIntPtr = std::begin(myInt); myIntPtr != std::end(myIntPtr); myIntPtr++)
除了其他答案之外,还打算考虑此方法。哪个最好是上下文问题。
回答by Joris Timmermans
Use std::vector, like Neil says.
使用 std::vector,就像尼尔说的那样。
Or do it the iterator way:
或者用迭代器的方式来做:
##代码##回答by kostas
If you're suggesting your code where myIntPtr is manipulated has no idea of the chunk size it points to, you either have to decide for a magic value in your int array, or restructure your code so that sizeof(myInt)
is also available.
如果您建议操作 myIntPtr 的代码不知道它指向的块大小,您要么必须决定 int 数组中的魔术值,要么重构您的代码,以便它sizeof(myInt)
也可用。
Standard C library functions use the latter approach: whenever you need to pass a buffer area through a pointer, you have to pass them its size in the same call.
标准 C 库函数使用后一种方法:每当您需要通过指针传递缓冲区时,您必须在同一个调用中传递缓冲区的大小。