我有以下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++相关问答推荐

理解没有返回语句的递归C函数的行为

为什么getchar()挂起了,尽管poll()返回了一个好的值?""

为什么复合文字(C99)的返回会生成更多的汇编代码?

为什么在Linux(特别是Ubuntu 20.04LTS)上,POSIX共享内存对象在重启后仍然存在,然后突然变成了根用户?

无效指针值在函数调用之间莫名其妙地改变

Ruby C Api处理异常

C语言编译阶段与翻译阶段的关系

N的值设置为0或1(未定义的行为),而我正在try 学习realloc和Malloc的用法

C-使用指针返回修改后的整数数组

使用TCL C API导航到列表中的元素

从CentOS 7到Raspberry PI 2B的交叉编译-无法让LIBC和System Include标头一起工作

浮动目标文件,数据段

从系统派生线程调用CRT

'printf("%s", user_input)' 危险吗?

多行表达式:C 编译器如何处理换行符?

无法在线程内用 C 打印?

为什么需要struct in_addr

如何在 C 中的 Postgres 函数的表中 for 循环

设置具有非零终止字符串的大整数

为什么我的条件不起作用?使用 fgets 输出