如何find'sizeof'(一个指向数组的指针)?
首先,这是一些代码:
int main() { int days[] = {1,2,3,4,5}; int *ptr = days; printf("%u\n", sizeof(days)); printf("%u\n", sizeof(ptr)); return 0; }
有没有办法找出ptr
指向的数组的大小(而不是只给它的大小,这是一个32位系统上的四个字节)?
不,你不能。 编译器不知道指针指向什么。 有一些技巧,比如用已知的带外值结束数组,然后将数值计算到该值,但不是使用sizeof。
另外一个诀窍就是咱提到的那个,就是把它放在某个地方。 例如,如果您要dynamic分配数组,则分配一个比您需要的大的块,将大小存储在第一个int中,然后返回ptr + 1作为指向数组的指针。 当你需要的大小,减less指针,偷看藏起来的价值。 只要记住要从头开始释放整个块,而不仅仅是数组。
答案是不。”
C程序员所做的是将数组的大小存储在某处。 它可以是一个结构的一部分,或者程序员可以欺骗一点点和malloc()多于所请求的内存,以便在数组开始之前存储一个长度值。
对于dynamic数组( malloc或C ++ new ),您需要存储其他人所提到的数组大小,或者可能构build一个处理添加,删除,计数等的数组pipe理器结构。不幸的是,C不能做到这一点C ++,因为你基本上必须为你存储的每种不同的数组types构build它,如果你需要pipe理多种types的数组,那么这很麻烦。
对于静态数组(如您的示例中的静态数组),有一个用于获取大小的常用macros,但不build议这样做,因为它不检查参数是否真的是静态数组。 尽pipemacros可以在实际代码中使用,例如在Linux内核头文件中,但可能与下面的代码略有不同:
#if !defined(ARRAY_SIZE) #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) #endif int main() { int days[] = {1,2,3,4,5}; int *ptr = days; printf("%u\n", ARRAY_SIZE(days)); printf("%u\n", sizeof(ptr)); return 0; }
你可以谷歌的原因是像这样的macros的警惕。 小心。
如果可能的话,C ++的stdlib比如vector更安全,更易于使用。
C ++模板有一个干净的解决scheme,不使用sizeof() 。 下面的getSize()函数返回任何静态数组的大小:
#include <cstddef> template<typename T, size_t SIZE> size_t getSize(T (&)[SIZE]) { return SIZE; }
这是一个foo_t结构的例子:
#include <cstddef> template<typename T, size_t SIZE> size_t getSize(T (&)[SIZE]) { return SIZE; } struct foo_t { int ball; }; int main() { foo_t foos3[] = {{1},{2},{3}}; foo_t foos5[] = {{1},{2},{3},{4},{5}}; printf("%u\n", getSize(foos3)); printf("%u\n", getSize(foos5)); return 0; }
输出:
3 5
对于这个特定的例子,是的,如果你使用typedefs(见下面)。 当然,如果你这样做,你就可以使用SIZEOF_DAYS,因为你知道指针指向什么。
如果你有一个(void *)指针,像malloc()或类似的方法返回的那样,否则没有办法确定指针指向哪个数据结构,因此无法确定它的大小。
#include <stdio.h> #define NUM_DAYS 5 typedef int days_t[ NUM_DAYS ]; #define SIZEOF_DAYS ( sizeof( days_t ) ) int main() { days_t days; days_t *ptr = &days; printf( "SIZEOF_DAYS: %u\n", SIZEOF_DAYS ); printf( "sizeof(days): %u\n", sizeof(days) ); printf( "sizeof(*ptr): %u\n", sizeof(*ptr) ); printf( "sizeof(ptr): %u\n", sizeof(ptr) ); return 0; }
输出:
SIZEOF_DAYS: 20 sizeof(days): 20 sizeof(*ptr): 20 sizeof(ptr): 4
正如所有正确的答案已经说明,你不能单独从数组的腐烂的指针值得到这个信息。 如果衰减的指针是函数接收到的参数,那么必须以其他方式提供始发数组的大小,以使函数知道该大小。
这里有一个不同于迄今为止提供的build议,这将是有效的:传递一个指向数组的指针。 这个build议类似于C ++风格的build议,只是C不支持模板或引用:
#define ARRAY_SZ 10 void foo (int (*arr)[ARRAY_SZ]) { printf("%u\n", (unsigned)sizeof(*arr)/sizeof(**arr)); }
但是,这个build议对于你的问题来说是愚蠢的,因为函数被定义为精确地知道传入的数组的大小(因此几乎不需要在数组中使用sizeof)。 它所做的是提供某种types的安全。 它将禁止你传入一个不需要的大小的数组。
int x[20]; int y[10]; foo(&x); /* error */ foo(&y); /* ok */
如果该函数应该能够在任何大小的数组上运行,那么您将不得不将该大小作为附加信息提供给该函数。
没有魔术解决scheme。 C不是reflection语言。 对象不会自动知道它们是什么。
但是你有很多select:
- 显然,添加一个参数
- 将调用包装在一个macros中,并自动添加一个参数
- 使用更复杂的对象。 定义一个包含dynamic数组和数组大小的结构。 然后,传递结构的地址。
我对这个问题的解决scheme是将数组的长度作为关于数组的元信息保存到一个struct Array中。
#include <stdio.h> #include <stdlib.h> struct Array { int length; double *array; }; typedef struct Array Array; Array* NewArray(int length) { /* Allocate the memory for the struct Array */ Array *newArray = (Array*) malloc(sizeof(Array)); /* Insert only non-negative length's*/ newArray->length = (length > 0) ? length : 0; newArray->array = (double*) malloc(length*sizeof(double)); return newArray; } void SetArray(Array *structure,int length,double* array) { structure->length = length; structure->array = array; } void PrintArray(Array *structure) { if(structure->length > 0) { int i; printf("length: %d\n", structure->length); for (i = 0; i < structure->length; i++) printf("%g\n", structure->array[i]); } else printf("Empty Array. Length 0\n"); } int main() { int i; Array *negativeTest, *days = NewArray(5); double moreDays[] = {1,2,3,4,5,6,7,8,9,10}; for (i = 0; i < days->length; i++) days->array[i] = i+1; PrintArray(days); SetArray(days,10,moreDays); PrintArray(days); negativeTest = NewArray(-5); PrintArray(negativeTest); return 0; }
但是你必须关心设置你想存储的数组的长度,因为没有办法检查这个长度,就像我们的朋友大量地解释。
不,您不能使用sizeof(ptr)
来查找数组ptr
指向的大小。
虽然分配额外的内存(超过数组的大小)将会有帮助,如果你想存储在额外的空间的长度。
int main() { int days[] = {1,2,3,4,5}; int *ptr = days; printf("%u\n", sizeof(days)); printf("%u\n", sizeof(ptr)); return 0; }
days []的大小是20,它是数据types的元素*的大小。 而指针的大小是4,不pipe它指向什么。 因为指针指向其他元素通过存储它的地址。
找不到指针的sizeof值是不可能的,因为编译器不知道指针的位置有多长。 sizeof指针应该是2或4(取决于编译器)。
#define array_size 10 struct { int16 size; int16 array[array_size]; int16 property1[(array_size/16)+1] int16 property2[(array_size/16)+1] } array1 = {array_size, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; #undef array_size
array_size传递给sizevariables:
#define array_size 30 struct { int16 size; int16 array[array_size]; int16 property1[(array_size/16)+1] int16 property2[(array_size/16)+1] } array2 = {array_size}; #undef array_size
用法是:
void main() { int16 size = array1.size; for (int i=0; i!=size; i++) { array1.array[i] *= 2; } }
一些可能有助于解决问题的function,但是我必须提到,Zan Lynx和Paul Tomblin在他们所说的内容上是正确的。
#include <stdio.h> #include <stdlib.h> int main() { int truInt = 12345679; int intLength = snprintf( NULL, 0, "%d", truInt ); printf("size of truInt = %d: \n", intLength); int *ptr_truInt = &truInt; printf("size of ptr_truInt = %d: \n", (snprintf( NULL, 0, "%d", ptr_truInt[0] ) ) ); int daysInt[] = {1,2,3,4,5,6,7,8,9}; int *ptrIntDays = daysInt; printf("size of ptrDays = %d: \n\n", getIntPointerSize(ptrIntDays)); char *stringPointer1 = "123456789"; printf("size of stringPointer = %d: \n", getCharPointerSize(stringPointer)); char daysChar[] = {'1','2','3','4','5','6','7','8','9','\0'}; printf("size of daysChar = %u: \n", sizeof(daysChar)); char *ptrDaysChar = daysChar; printf("size of ptrDaysChar2 = %u: \n", getCharPointerSize(ptrDaysChar)); char daysChar2[] = "123456789"; char *ptrDaysChar2 = daysChar2; printf("size of ptrDaysChar2 = %u: \n", getCharPointerSize(ptrDaysChar2)); return 0; } int getIntPointerSize(unsigned pointer[]){ int i=-1; while(pointer[++i] != '\0'){} return i; } int getCharPointerSize(char *pointer){ int i=-1; while(pointer[++i] != '\0'){} return i; }
嗨在string中有一个'\0'
字符在结尾,所以人们可以得到像strlen
函数的string的大小整数数组例如是,你不能使用任何值作为结束值,所以一个可能的解决scheme是解决数组,并使用NULL
指针作为结束值
/* http://stackoverflow.com/questions/492384/how-to-find-the-sizeof-a-pointer-pointing-to-an-array */ #include <stdio.h> /* the following function will produce the warning: * 'sizeof' on array function parameter 'a' will * return size of 'int *' [-Wsizeof-array-argument] */ void foo( int a[] ) { printf( "%lu\n", sizeof a ); } /* so we have to implement something else one possible * idea is to use the NULL pointer as a control value * the same way '\0' is used in strings but this way * the pointer passed to a function should address pointers * so the actual implementation of an array type will * be a pointer to pointer */ typedef char * type_t; /* line 18 */ typedef type_t ** array_t; /* * -- -- * -**-**- * -$$$$$- * -999- * -^- * - */ int main( void ) { array_t initialize( int, ... ); /* initialize an array with four values "foo", "bar", "baz", "foobar" * if one wants to use integers rather than strings than in the typedef * declaration at line 18 the char * type should be changed with int * and in the format used for printing the array values * at line 45 and 51 "%s" should be changed with "%i" */ array_t array = initialize( 4, "foo", "bar", "baz", "foobar" ); int size( array_t ); /* print array size */ printf( "size %i:\n", size( array )); void aprint( char *, array_t ); /* print array values */ aprint( "%s\n", array ); /* line 45 */ type_t getval( array_t, int ); /* print an indexed value */ int i = 2; type_t val = getval( array, i ); printf( "%i: %s\n", i, val ); /* line 51 */ void delete( array_t ); /* free some space */ delete( array ); return 0; } /* the output of the program should be: * size 4: * foo * bar * baz * foobar * 2: baz */ #include <stdarg.h> #include <stdlib.h> array_t initialize( int n, ... ) { /* here we store the array values */ type_t *v = (type_t *) malloc( sizeof( type_t ) * n ); va_list ap; va_start( ap, n ); int j; for ( j = 0; j < n; j++ ) v[j] = va_arg( ap, type_t ); va_end( ap ); /* the actual array will hold the addresses of those * values plus a NULL pointer */ array_t a = (array_t) malloc( sizeof( type_t *) * ( n + 1 )); a[n] = NULL; for ( j = 0; j < n; j++ ) a[j] = v + j; return a; } int size( array_t a ) { int n = 0; while ( *a++ != NULL ) n++; return n; } void aprint( char *fmt, array_t a ) { while ( *a != NULL ) printf( fmt, **a++ ); } type_t getval( array_t a, int i ) { return *a[i]; } void delete( array_t a ) { free( *a ); free( a ); } /* край */
不,原因来自arrays退化为指针规则。 当你引用这个数组的时候,它被隐含地转换成一个指针。 但是这会抛出关于数组的信息:当你知道数组的内容和存储大小时,你只知道一个指针的地址和大小。 解决方法是使用元组指针+大小:退化数组并存储其容量。