Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何找到“sizeof”(指向数组的指针)?_C_Arrays_Pointers_Sizeof - Fatal编程技术网

C 如何找到“sizeof”(指向数组的指针)?

C 如何找到“sizeof”(指向数组的指针)?,c,arrays,pointers,sizeof,C,Arrays,Pointers,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位系统中是四个字节 不,你不能。编译器不知道指针指向什么。有一些技巧,比如用已知的带外值结束数组,然后计算大

首先,这里有一些代码:

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

另一个技巧是所提到的,那就是把尺寸藏在某个地方。例如,如果要动态分配数组,请分配一个大于所需整数的块,将大小隐藏在第一个整数中,并返回ptr+1作为指向数组的指针。需要大小时,减小指针并查看隐藏的值。只要记住从一开始就释放整个块,而不仅仅是数组。

答案是,不

#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;
}
C程序员所做的是将数组的大小存储在某个地方。它可以是一个结构的一部分,或者程序员可以比C++请求更多的内存,并且在数组开始之前存储一个长度值。不幸的是,C并没有像C++那样做这件事,因为基本上必须为每个存储的不同类型的数组建立它,如果你需要管理的数组类型繁多,那么这是麻烦的。
#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;
}
对于静态数组,例如示例中的数组,有一个公共宏用于获取大小,但不建议使用它,因为它不会检查参数是否确实是静态数组。该宏用于实际代码,例如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;
}
你可以在谷歌上搜索一些原因来警惕这样的宏。小心点


如果可能的话,C++的STDLIB,比如向量,它更安全,更容易使用。对于这个特定的例子,

< P>,是的,如果你使用Type Debug,请参阅下面的内容。当然,如果你这样做,你也可以使用SIZEOF_天,因为你知道指针指向什么

如果您有一个由malloc或类似程序返回的void*指针,那么,不,无法确定指针指向的数据结构,因此无法确定其大小

#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;
} 

有一个干净的解决方案,用C++模板,不使用sieof。以下getSize函数返回任何静态数组的大小:

#include <cstddef>

template<typename T, size_t SIZE>
size_t getSize(T (&)[SIZE]) {
    return SIZE;
}

正如所有正确答案所述,您无法仅从数组的衰减指针值获得此信息。如果衰减指针是函数接收到的参数,则必须以其他方式提供原始数组的大小,以便函数知道该大小

这里有一个不同于目前提供的建议,它将起作用:将指针传递到数组。这个建议与C++风格的建议类似,除了C不支持模板或引用:

#define ARRAY_SZ 10

void foo (int (*arr)[ARRAY_SZ]) {
    printf("%u\n", (unsigned)sizeof(*arr)/sizeof(**arr));
}
但是,对于您的问题来说,这个建议有点愚蠢,因为函数被定义为准确地知道传入的数组的大小,因此,根本不需要在数组上使用sizeof。不过,它的作用是提供某种类型的安全性。它将禁止您传入不需要的大小的数组

int x[20];
int y[10];
foo(&x); /* error */
foo(&y); /* ok */
如果函数应该能够对任意大小的数组进行操作,那么您必须将该大小作为附加信息提供给函数

 #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
数组\u size正在传递给size变量:

#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;
    }
}

我解决这个问题的方法是将数组的长度保存到结构数组中,作为关于数组的元信息

#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;
}
但您必须注意设置要存储的数组的正确长度,因为无法检查此长度,正如我们的朋友大量解释的那样。

不,您不能使用SizeOffptr来查找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;
}
天数[]的大小为20,这是元素数*其数据类型的大小。 而不管指针指向什么,指针的大小都是4。
因为指针通过存储地址指向其他元素

没有神奇的解决办法。C不是一种反思性语言。对象不会自动知道它们是什么

但你有很多选择:

显然,添加一个参数 将调用包装在宏中并自动添加参数 使用更复杂的对象。定义一个包含动态数组和数组大小的结构。然后,传递结构的地址。 在字符串中,末尾有一个“\0”字符,因此可以使用strlen等函数获取字符串的长度。问题 例如,对于整数数组,您不能使用任何值作为结束值,因此一种可能的解决方案是寻址数组并使用NULL指针作为结束值

包括 /*以下功能将产生警告: *数组函数参数“a”上的“sizeof”将 *返回“int*”的大小[-Wsizeof数组参数] */ void foo int a[] { printf%lu\n,大小为a; } /*因此,我们必须实施其他一些可能的措施 *其思想是使用空指针作为控制值 *字符串中使用“\0”的方式相同,但如下所示 *传递给函数的指针应指向指针 *因此,数组类型的实际实现将 *成为指向指针的指针 */ typedef char*type_t;/*第18行*/ 类型定义类型**数组; int主空隙 { 数组初始化int; /*使用四个值foo、bar、baz、foobar初始化数组 *如果想要使用整数而不是字符串,而不是在typedef中 *第18行的声明char*类型应更改为int *和用于打印数组值的格式 *在第45行和第51行,应将%s更改为%i */ 数组\ t数组=初始化4,foo,bar,baz,foobar; 整数大小数组; /*打印数组大小*/ printf大小%i:\n,大小数组; void aprint char*,数组\u t; /*打印数组值*/ aprint%s\n,数组;/*第45行*/ 键入getval数组,int; /*打印索引值*/ int i=2; type_t val=getval数组,i; printf%i:%s\n,i,val;/*第51行*/ 无效删除数组; /*腾出一些空间*/ 删除数组; 返回0; } /*程序的输出应为: *尺寸4: *福 *酒吧 *巴兹 *福巴 *2:baz */ 包括 包括 数组\u t初始化int n。。。 { /*这里我们存储数组值*/ type_t*v=type_t*malloc sizeof type_t*n; va_列表ap; va_启动ap,n; int j; 对于j=0;j您可以这样做:

int days[] = { /*length:*/5, /*values:*/ 1,2,3,4,5 };
int *ptr = days + 1;
printf("array length: %u\n", ptr[-1]);
return 0;

这就是我个人在代码中所做的。我喜欢让它尽可能简单,同时仍然能够得到我需要的值

typedef struct intArr {
    int size;
    int* arr; 
} intArr_t;

int main() {
    intArr_t arr;
    arr.size = 6;
    arr.arr = (int*)malloc(sizeof(int) * arr.size);

    for (size_t i = 0; i < arr.size; i++) {
        arr.arr[i] = i * 10;
    }

    return 0;
}

我总是使用带有sizeof的parens-当然它使它看起来像一个函数调用,但我认为它更清晰。为什么不呢?你有反对多余括号的意见吗?我觉得我自己读起来更容易一点。@Paul:嗯。。假设该调用的左侧是指向int的指针,我会将其写成int*ptr=malloc4*sizeof*ptr;这对我来说要清楚得多。减少要读取的参数,并将文本constsant放在前面,就像在数学中一样。@unwind-当您指的是整数数组时,不要分配指针数组!这里没有指向数组的指针。只是一个指向int的指针。这就是pascal字符串的实现方式,显然pascal字符串是excel运行如此之快的原因@亚当:很快。我在我的字符串实现列表中使用它。线性搜索的速度非常快,因为它是:加载大小、预取pos+大小、比较大小和搜索大小,如果等于strncmp,移动到下一个字符串,重复。它比二进制搜索快,最多可搜索500个字符串。数组大小是各地实用程序员常用的范例。是的,它是一种常见范例。尽管在动态数组中很容易忘记和使用它,但您仍然需要谨慎使用它。是的,这一点很好,但问题是关于指针的,而不是静态数组的。如果数组大小宏的参数是数组,即数组类型的表达式,则该数组大小宏始终有效。对于所谓的动态数组,永远不会得到数组类型的实际数组表达式。当然,您不能,因为数组类型在编译时包含它们的大小。您只需要得到一个指向第一个元素的指针。您的异议不会检查参数是否真的是静态数组,也不会检查参数是否真的有效,因为它们是不同的,一个是数组,另一个不是。有一个浮动的模板函数可以做同样的事情,但会阻止指针的使用。很抱歉这么晚才发布评论,但是如果编译器不知道指针指向的是什么,free怎么知道要清除多少内存?我知道这些信息是为免费使用等功能而存储在内部的。所以我的问题是为什么“编译器也可以这么做?”@viki.omega9,因为free会在运行时发现大小。编译器无法知道大小,因为您
根据运行时因素命令行参数、文件内容、月亮的相位等,可以使数组的大小不同。快速跟进,为什么没有一个函数可以像free那样返回大小呢,如果您可以保证只使用malloced内存调用该函数,并且库会像我见过的大多数情况那样,在返回指针之前使用int来跟踪malloced内存,那么您可以编写一个。但是如果指针指向一个静态数组或类似的东西,它就会失败。同样,也不能保证您的程序可以访问malloced内存的大小。@viki.omega9:另外需要记住的是,malloc/free系统记录的大小可能不是您要求的大小。您将malloc9个字节,得到16个字节。malloc3k字节,得到4K。或类似情况。+1,因为您无法仅从数组的衰减指针值获得此信息,并提供解决方法。我从未见过表示法T&[SIZE]。你能解释一下这是什么意思吗?在这个上下文中你也可以提到CONTXPR。如果使用C++,实际上你有一个数组类型的变量,那就很好了。这两个问题都不是:语言是C,OP想要从数组中得到数组大小的东西是一个简单的PoTin。这个代码会通过为每个不同大小/类型组合重新创建相同的代码而导致代码膨胀,或者是由编译器神奇地优化了?“WorkSeund:这是C++语法,用于没有变量名的数组类型的引用,只是一个大小和元素类型。@user2796283:此函数在编译时被完全优化;不需要魔法;它不是将任何内容组合到单个定义中,只是将其内联到编译时常量中。但在调试构建中,是的,您将有一组单独的函数返回不同的常量。链接器魔法可能会合并使用相同常量的链接器。调用方不将SIZE作为arg传递,它是一个模板参数,必须由函数定义知道。sizeofptr是指针的大小,sizeof*ptr是指针的大小,我们的代码中充满了注释,但是我认为如果您在代码之外添加一些关于这如何工作的一般性解释,会使一切变得更容易,作为普通文本。你能回答你的问题并去做吗?非常感谢。创建一个指向每个元素的指针数组,这样就可以线性搜索它的空值,这可能是直接存储一个单独的大小所能想到的最低效的替代方法。特别是如果你真的一直在使用这个额外的间接层,对象知道它们是什么。但如果指向子对象,则无法获取有关完整对象或较大子对象的信息。请选择“首选大小”来存储大小。
typedef struct intArr {
    int size;
    int* arr; 
} intArr_t;

int main() {
    intArr_t arr;
    arr.size = 6;
    arr.arr = (int*)malloc(sizeof(int) * arr.size);

    for (size_t i = 0; i < arr.size; i++) {
        arr.arr[i] = i * 10;
    }

    return 0;
}