使用指针跨越INTEGER数组中的所有元素

有没有办法使用指针跨越整数数组中的所有元素(类似于使用指针跨越字符串元素)。我知道整数数组不是NULL终止所以当我尝试使用指针溢出数组时溢出。所以我添加NULL作为数组的最后一个元素,它工作得很好。

int array[7]={1,12,41,45,58,68,NULL}; int *i; for(i=array;*i;i++) printf("%d ",*i); 

但是,如果数组中的一个元素为0,那将表现为NULL。有没有其他方法可以实现指针跨越整数数组中的所有元素?

您可以使用指针迭代C样式字符串的原因是256个不同的字符值,其中一个特别保留为“这是字符串的结尾”。 因此,C风格的字符串不能在其中的任何位置存储空字符。

当您尝试对整数数组使用类似的技巧时,您会注意到同样的问题。 如果你想能够在某个时刻停止,你将不得不选择一些整数并保留它意味着“这不是一个整数;它实际上是整数序列的结束。” 所以不,除非你愿意选择一些通常不会出现在字符串中的值,否则没有通用的方法来获取整数数组并用特殊值标定结尾。

C ++选择了与C不同的方法来描述序列。 C ++样式范围(如在vectorstringlist )存储两个迭代器, begin()end() ,而不是使用某种null终止符存储元素,它们指示第一个元素和第一个元素元素结束。 您可以通过编写来迭代这些范围

 for (iterator itr = begin; itr != end; ++itr) /* ... visit *itr here ... */ 

这种方法比定义范围的C字符串方法灵活得多,因为它不依赖于范围内任何值的特定属性。 如果你想迭代一系列整数值,我建议选择使用这样的东西。 它更明确地表示范围的界限,并且不会遇到某些值无法存储在范围内的奇怪问题。

通常,除非您选择不属于有效数据范围的标记值 ,否则不会。 例如,有效范围可能是正数,因此您可以使用负数(如-1作为指示数组末尾的标记值。 这是C风格的字符串如何工作; 使用NULL终止符是因为它超出了可以表示字符的有效整数范围。

但是,通常最好以某种方式将数组指针与另一个指示数组大小的变量配对,或者将另一个指针指向数组的一端。

在您的具体情况下,您可以执行以下操作:

 // Note that you don't have to specify the length of the array. int array[] = {1,12,41,45,58,68}; // Let the compiler count the number of elements for us. int arraySize = sizeof(array)/sizeof(int); // or int arraySize = sizeof(array)/sizeof(array[0]); int main() { int* i; for(i = array; i != array + arraySize; i++) printf("%d ",*i); } 

你也可以这样做:

 int arrayBegin[] = {1,12,41,45,58,68}; int* arrayEnd = arrayBegin + sizeof(arrayBegin)/sizeof(arrayBegin[0]); int main() { int* i; for(i = arrayBegin; i != arrayEnd; i++) printf("%d ",*i); } 

但是只给出一个指针,你不知道它指向的数组有多长。 实际上,您甚至无法判断指针是指向数组还是单个对象! (至少不便携。)

如果你有必须接受数组的函数,要么你的函数需要:

  • 指针指针指向的数组的大小,
  • 两个指针,一个指向数组的第一个元素,一个指向数组的一个接一个结尾。

我想提供一些额外的建议:永远不要在数组中使用某种类型的sentinel / termination值来确定它们的界限。 这使您的程序容易出错,并且通常是导致安全问题的原因。 应始终存储数组的长度以将所有操作限制为其边界并针对该值进行测试。

在C ++中,您拥有STL及其容器。

在C中,你将有效地结束使用像

 typedef struct t_int_array { size_t length; int data[1]; /* note the 1 (one) */ } int_array; 

以及一组这样的操作函数

 int_array * new_int_array(size_t length) { int_array * array; /* we're allocating the size of basic t_int_array (which already contains space for one int) and additional space for length-1 ints */ array = malloc( sizeof(t_int_array) + sizeof(int) * (length - 1) ); if(!array) return 0; array->length = length; return array; } int_array * concat_int_arrays(int_array const * const A, int_array const * const B); int_array * int_array_push_back(int_array const * const A, int const value); /* and so on */ 

此方法将使编译器以某种方式对齐t_int_array结构,使其最适合目标体系结构(也使用malloc分配),并且只需在数据数组元素的元素大小数量中分配更多空间将保持这种方式。

除了通常建议您应该使用STL之外 ,您还可以找到固定数组的长度,如下所示:

 int array[6]={1,12,41,45,58,68}; for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i) { } 

如果使用模板化函数,则可以隐式导出长度,如下所示:

 template void func(int (&array)[len]) { for (int i = 0; i < len; ++i) { } } int array[6]={1,12,41,45,58,68}; func(array); 

如果0是正常整数数组中可能出现的值,则可以指定其他值:

 const int END_OF_ARRAY = 0x80000000; int array[8]={0,1,12,41,45,58,68,END_OF_ARRAY}; for (int i = 0; array[i] != END_OF_ARRAY; ++i) { } 

如果每个值都是可能的,或者其他任何方法都不起作用(例如,动态数组),那么您必须分别管理长度。 这是允许嵌入空字符工作的字符串(例如BSTR )的方式。

在您的示例中,您使用(或者更确切地说是滥用)NULL宏作为标记值 ; 这是C字符串中NUL( '\0' )字符的函数,但在C字符串的情况下,除了作为终端(或sentinel)值之外,NUL不是有效字符。

NULL宏旨在表示无效指针而不是整数值(尽管在C ++中隐式或显式地转换为int时,其值保证为零,而在C中,这几乎总是如此)。 在这种情况下,如果要使用零作为标记值,​​则应使用文字零而不是NULL。 问题当然是如果在这个应用程序中,零是有效数据值,则它不适合用作标记。

例如,以下可能适合:

 static const int SENTINEL_VALUE = -1 ; int array[7] = { 1, 12, 41, 45, 58, 68, SENTINEL_VALUE } ; int* i ; for( i = array; *i != SENTINEL_VALUE; i++ ) { printf( "%d ", *i ) ; } 

如果所有整数值都是有效的数据值,那么你根本就不能使用sentinel值,并且必须使用容器类(知道其长度)或迭代数组的已知长度(来自sizeof() )。

只是为了先前的答案迂腐和扩展:在处理C中的整数数组时,依赖于数组本身的哨兵值是极其罕见的。 没有(1)理智的程序员这样做。 为什么不? 因为根据定义,整数可以在预定义的负/正限制内保持任何值,或者(对于现在非常见的32位整数)0到0xffffff。 通过窃取其中一个可能的哨兵值来重新定义“整数”的概念并不是一件好事。

相反, 总是(1)必须(1)依赖于控制arrays中最新的整数计数。 假设我们要编写一个C函数,它返回一个int指针,指向第一个数组成员,其值大于函数的参数,或者,如果没有这样的成员,则返回NULL(所有代码都未经测试):

 int my_int_array[10]; // maximum of 10 integers in my_int_array[], which must be static int member_count = 0; // varies from 0 to 10, always holds number of ints in my_int_array[] int * first_greater_than ( int val ) { int i; int *p; for ( i = 0, p = my_int_array; i < member_count; ++i, ++p ) { if ( *p > val ) { return p; } } return NULL; } 

更好的是将i的值限制为永远不会超过 my_int_array []的最后一个可能成员,即它永远不会超过9,并且p永远不会指向my_int_array [10]及以后:

 int my_int_array[10]; // maximum of 10 integers in my_int_array[], which must be static int member_count = 0; // varies from 0 to 10, always holds number of ints in my_int_array[] int * first_greater_than ( int val ) { #define MAX_COUNT sizeof(my_int_array)/sizeof(int) int i; int* p; for ( i = 0, p = my_int_array; i < member_count && i < MAX_COUNT; ++i, ++p ) { if ( *p > val ) { return p; } } return NULL; } 

HTH和我道歉,如果这也是太基本的话。

–pete

  1. 不完全正确,但现在相信它

在ANSI C中,它比以前的解决方案更容易和更短:

 int array[]={1,12,41,45,58,68}, *i=array; size_t numelems = sizeof array/sizeof*array; while( numelems-- ) printf("%d ",*i++); 

另一种方法是管理int的指针数组:

 #include  #include  #define MAX_ELEMENTS 10 int main() { int * array[MAX_ELEMENTS]; int ** i; int k; // initialize MAX_ELEMENTS,1 matrix for (k=0;k 

这样,循环条件完全独立于整数值。 但是......为此,你必须使用2D数组(矩阵)而不是普通的1D数组。 希望有所帮助。