Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.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中的数组大小。无法理解输出_C_Arrays_Malloc - Fatal编程技术网

获取C中的数组大小。无法理解输出

获取C中的数组大小。无法理解输出,c,arrays,malloc,C,Arrays,Malloc,我很好奇为什么我的代码中会出现以下行为 #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int M=24; int arr[M]; int N=24; int* ptr=(int*) malloc(sizeof(int)*N); /*Allocate memory of size N */ printf("Size of yo

我很好奇为什么我的代码中会出现以下行为

#include <stdio.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{
    int M=24;
    int arr[M];
    int N=24;
    int* ptr=(int*) malloc(sizeof(int)*N); /*Allocate memory of size N  */

    printf("Size of your malloced array is %lu\n",sizeof(ptr)/sizeof(ptr[0])); /* Get the size of memory alloctaed. Should be the same as N?*/

    printf ("Size of your normal arrays is %lu\n",sizeof(arr)/sizeof(arr[0])); /* Ditto  */

    free(ptr);

    return 0;
}
我原以为这两个地方的输出都是
24
。那么,如果我不知何故“忘记”了malloced数组,如何获得它的大小呢

当然,指针
ptr
将包含一些关于malloced数组大小的信息,因为当我们调用
free(ptr)
时,它将只释放malloced数组而
sizeof()
与您预期的固定长度和可变长度数组一样工作,它对
malloc()的大小一无所知
'ed数组

应用于指针时,
sizeof()
只返回指针的大小

更一般地说,给定一个指向
malloc()
的块的指针,没有标准的方法来发现该块的大小

请参见C常见问题解答和问题

总之,如果您需要以可移植的方式知道堆分配数组的大小,您必须自己跟踪该大小。

在指针上使用
sizeof()
时,您可以得到指针的大小。不是分配的数组的大小。在您的例子中,指针可能是8个字节,
int
是4个字节,因此得到2个字节

简而言之,您无法获得已分配数组的大小。你需要自己跟踪它


编辑:请注意,某些编译器确实支持此功能作为扩展:


例如,MSVC支持
msize()

如果只有指向数组(第一个元素)的指针,则在运行时无法获取数组的大小。在C中根本没有允许您这样做的构造。你必须自己记录长度

如果您碰巧有一个数组而不是指针,那么您可以找到它的长度,但不能找到指向数组元素的指针


在您的代码中,
ptr
是一个指针,因此您无法找到它所指向的数组的长度。另一方面,
arr
是一个数组,因此您可以通过
sizeof(arr)/sizeof(arr[0])
查找其长度在32位机器上指针的大小为4字节,在64位机器上指针的大小为8字节。我猜你是在64位机器上工作的,因为int的大小是4,你得到的
sizeof(ptr)/sizeof(ptr[0])
是2。

正如所指出的,没有可移植的方法获得动态数组的大小,因为
malloc
可能会分配比请求更多的内存。此外,管理malloc请求取决于操作系统。例如*nix将调用
sbrk
,并将请求存储在某处。因此,当调用
sizeof(ptr)
时,它返回指针的大小,而不是数组的大小。另一方面,如果数组是固定的,那么它的大小是在编译时确定的,因此编译器可以用固定数组的大小替换
sizeof(arr)
,从而为您提供“正确”的大小。

关于
sizeof
需要记住的是它是一个编译时操作符1;它返回基于操作数类型的字节数

arr
的类型是
int[24]
,因此
sizeof arr
将计算为存储24
int
值所需的字节数。
ptr
的类型是
int*
,因此
sizeof ptr
将计算为存储单个
int*
值所需的字节数。由于这是在编译时发生的,所以
sizeof
无法知道ptr指向的内存块是什么,或者它有多大

通常,无法根据指针值本身确定指针指向的内存块有多大;这些信息必须单独跟踪

风格nit:编写
malloc
调用的首选方法是

int *ptr = malloc(sizeof *ptr * N);
在C语言中,您不需要将
malloc
的结果强制转换为目标指针类型2,如果忘记包含
stdlib.h
或在范围内没有
malloc
的原型,这样做可能会掩盖有用的诊断

其次,请注意,我将表达式
*ptr
作为操作数传递给
sizeof
,而不是
(int)
。如果您更改了
ptr
的类型,但忘记了在相应的
malloc
调用中更改类型,这将最大限度地减少错误。这是因为
sizeof
不尝试计算操作数(意味着它不尝试取消引用
ptr
);它只计算其类型


1当
sizeof
应用于可变长度数组时,会出现此规则的例外情况;由于数组的大小直到运行时才确定,因此将在运行时计算应用于VLA的
sizeof
运算符。


2注意,C++中不是这样的;需要一个强制转换,但是如果你正在编写C++,你应该使用<代码>新< /COD>和<代码>删除< />代码,而不是<代码> Malc 和<代码>免费< /代码>。而且,这只适用于C89;较旧版本的C具有
malloc
return
char*
而不是
void*
,因此对于这些版本,需要强制转换。除非您使用的是非常旧的实现(例如运行旧版本VMS的旧VAX mini),否则这不应该是一个问题 MalCal?你的标签有点含糊。无论如何,如果这是C,你必须自己记录大小,就像@Mysticial说的。但是,如果这是C++,通常你会使用一个<代码> STD::vector < /C>或类似的结构,并且不会麻烦,因为它会为你做。谢谢。我的意思是这是一个C问题。把它标记为C++错误。另请看,重复其他人说过的话:如果你认为“肯定是”你错了
int *ptr = malloc(sizeof *ptr * N);