我有以下C代码:

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

#define ARRAYSIZE(a) (sizeof(a))/(sizeof(a[0]))
#define ARRAYSIZEWITHPTR(a) (&(a)[1] - a)

int main (void){

  int array[5] = {1,2,3,4,5};
  int* pArray = array;
  int* p = calloc(ARRAYSIZE(array), sizeof(int));
  
  assert(NULL != p);
  
  printf("size of array: %ld\n", ARRAYSIZE(array));
  printf("size of pArray: %ld\n", ARRAYSIZE(pArray));
  printf("size of p: %ld\n", ARRAYSIZE(p));
  printf("size of pArray: %ld\n", ARRAYSIZEWITHPTR(pArray));
  printf("size of p: %ld\n", ARRAYSIZEWITHPTR(p));

  free(p);

return 0;
}

当我编译这个程序时,我从GCC那里收到了以下警告消息:

test.c: In function ‘main’:
test.c:5:33: warning: division ‘sizeof (int *) / sizeof (int)’ does not compute the number of array elements [-Wsizeof-pointer-div]
    5 | #define ARRAYSIZE(a) (sizeof(a))/(sizeof(a[0]))
      |                                 ^
test.c:15:35: note: in expansion of macro ‘ARRAYSIZE’
   15 |   printf("size of pArray: %ld\n", ARRAYSIZE(pArray));
      |                                   ^~~~~~~~~
test.c:11:8: note: first ‘sizeof’ operand was declared here
   11 |   int* pArray = array;
      |        ^~~~~~
test.c:5:33: warning: division ‘sizeof (int *) / sizeof (int)’ does not compute the number of array elements [-Wsizeof-pointer-div]
    5 | #define ARRAYSIZE(a) (sizeof(a))/(sizeof(a[0]))
      |                                 ^
test.c:16:30: note: in expansion of macro ‘ARRAYSIZE’
   16 |   printf("size of p: %ld\n", ARRAYSIZE(p));
      |                              ^~~~~~~~~
test.c:12:8: note: first ‘sizeof’ operand was declared here
   12 |   int* p = calloc(ARRAYSIZE(array), sizeof(int));
      |        ^

以下是程序输出:

size of array: 5
size of pArray: 2
size of p: 2
size of pArray: 1
size of p: 1
 

从程序输出中可以明显看出,只有在以数组名称作为参数调用宏时,我才能获得正确的值.然而,数组名称不是指向数组的第一个元素的指针吗?如果是这样的话,使用数组名称调用宏(这样会产生正确的结果)与指向堆上的数组的指针(不会产生正确的结果)之间有什么本质的区别?

从源代码中可以看出,我try 了两种宏方法来获取在堆上创建的数组的大小,但都没有成功.

那么下一个问题是,在C编程中使用calloc()在堆上这样创建的数组的大小是不是可能的?

提亚

推荐答案

没有标准化的方法来找出从malloc/calloc/realloc返回的指针指向多少已分配内存.预计程序员将亲自跟踪这一点.

在您的示例中,因为ppArray具有类型int *,所以sizeof(p)sizeof(pArray)给您的大小是类型int *的大小,在您的系统上很可能是8.

然而,数组名称不是指向数组的第一个元素的指针吗?

不,数组名称是数组,然而在大多数上下文中,数组decays指向指向其第一个元素的指针.其中一种情况是,当数组是sizeof运算符的操作数时,因为array是数组类型,所以sizeof(array)给出了整个数组的大小.

C++相关问答推荐

为什么在传输 Big Data 时共享内存段的运行时间比管道更长?

从STdin读写超过4096个字节

Mise()在虚拟内存中做什么?

在函数中使用复合文字来初始化C语言中的变量

Sizeof(&Q;字符串&Q;)的正确输出是什么?

GCC不顾-fno-Builtin-SINCOS旗帜向SINCOS发出呼唤

GTK函数调用将完全不相关的char* 值搞乱

==284==错误:AddressSaniizer:堆栈缓冲区下溢

在C++中父进程和子进程中的TAILQ队列同步问题

搜索使用int代替time_t的用法

用C++构建和使用DLL的困惑

C中的回文数字

Valgrind正在使用一个Fexecve电话报告不可能发生的事情

如何摆脱-WIMPLICIT-Function-声明

有没有办法减少C语言中线程的堆大小?

为什么这个代码的最后一次迭代不能正常工作?

C中2个数字的加法 - 简单的人类方法

C 和 C++ 标准如何告诉您如何处理它们未涵盖的情况?

在 C23 之前如何对空指针使用nullptr?

strided memcpy(3) 在 libvpx 中如何工作