数组指针如何存储其大小?

时间:2010-12-24 07:22:28

标签: c arrays pointers

#include "stdio.h"

#define COUNT(a) (sizeof(a) / sizeof(*(a)))

void test(int b[]) {
  printf("2, count:%d\n", COUNT(b));
}

int main(void) {
  int a[] = { 1,2,3 };

  printf("1, count:%d\n", COUNT(a));
  test(a);

  return 0;
}

结果很明显:

1, count:3
2, count:1

我的问题:

  1. 声明“a”时存储的长度(计数/大小)信息在哪里?
  2. 当“a”传递给test()函数时,为什么长度(计数/大小)信息会丢失?

6 个答案:

答案 0 :(得分:7)

C语言中没有“数组指针”这样的东西。

尺寸不存储在任何地方。 a不是指针,aint[3]类型的对象,这是编译器在编译时熟知的事实。因此,当您要求编译器在编译时计算sizeof(a) / sizeof(*a)时,编译器知道答案是3

当您将a传递给函数时,您有意要求编译器将数组类型转换为指针类型(因为您将函数参数声明为指针)。对于指针,您的sizeof表达式会产生完全不同的结果。

答案 1 :(得分:5)

  
      
  1. 声明“a”时存储的长度(计数/大小)信息在哪里?
  2.   

它没有存储在任何地方。 sizeof运算符(在COUNT()宏中使用)返回整个数组的大小,当它被赋予一个真实数组作为操作数时(就像它在第一个printf()中)

  
      
  1. 当“a”传递给test()函数时,为什么长度(计数/大小)信息会丢失?
  2.   

不幸的是,在C中,函数的数组参数是虚构的。数组不会传递给函数;该参数被视为一个指针,并且在函数调用中传递的数组参数被“衰减”为一个简单的指针。 sizeof运算符返回指针的大小,该大小与用作参数的数组的大小无关。

作为旁注,在C ++中,您可以将一个函数参数作为数组的引用,在这种情况下,完整的数组类型可供该函数使用(即,参数没有不会衰减到指针,sizeof将返回完整数组的大小)。但是,在这种情况下,参数必须与数组类型完全匹配(包括元素数),这使得该技术最常用于模板。

例如,以下C ++程序将按预期执行:

#include "stdio.h"

#define COUNT(a) (sizeof(a) / sizeof(*(a)))

template <int T>
void test(int (&b)[T]) {
  printf("2, count:%d\n", COUNT(b));
}

int main(int argc, char *argv[]) {
  int a[] = { 1,2,3 };

  printf("1, count:%d\n", COUNT(a));
  test(a);

  return 0;
}

答案 2 :(得分:1)

  1. 无处。
  2. 因为它没有存储在第一位。

  3. 当您在main()中引用数组时,实际的数组声明定义是可见的,因此sizeof(a)以字节为单位给出数组的大小。

    当你在函数中引用数组时,参数实际上是'void test(int *b),并且指针的大小除以它指向的东西的大小恰好在32位平台上为1而在具有LP64架构的64位平台上(或者,实际上,在像Windows-64这样的LLP64平台上)它将是2,因为指针是8个字节而int是4个字节。

    没有通用的方法来确定传递给函数的数组的大小;你必须明确地和手动地传递它。


    来自评论:

      

    我还有两个问题:

         
        
    1. 你是什么意思“......实际的声明是可见的......”?编译器(或OS)可以通过sizeof(a)函数得到长度信息吗?
    2.   
    3. 为什么指针&amp;(a [0])不包含长度信息作为指针“a”?
    4.   
    1. 我认为你在学习C或其他更现代的语言之前学过Java。最终,它归结为“因为这是C定义的方式”。操作系统不涉及;这是一个纯粹的编译器问题。

      • sizeof()是一个运算符,而不是一个函数。除非您正在处理VLA(可变长度数组),否则它将在编译时进行求值并且是一个常量值。

      main()里面,数组定义(当我说'声明'时我错过了),当sizeof()运算符应用于实际数组的名称时 - 而不是数组函数的参数 - 然后返回的大小是以字节为单位的数组大小。

    2. 因为这是C而不是Algol,Pascal,Java,C#,......

      C不存储数组的大小 - 句点。这是生活中的事实。并且,当数组传递给函数时,大小信息不会传递给函数;数组'衰减'到指向数组的第0个元素的指针 - 只传递该指针。

答案 3 :(得分:1)

  
      
  1. 声明“a”时存储的长度(计数/大小)信息在哪里?
  2.   

无处。这个问题没有意义BTW。

  
      
  1. 当“a”传递给test()函数时,为什么长度(计数/大小)信息会丢失?
  2.   

传递给函数时,数组衰减为指针(指向第一个元素)。所以答案是'无处',与上一个问题类似,这个问题再没有任何意义。

答案 4 :(得分:1)

1. Where is the length(count/size) info stored when "a" is declared?

未存储。编译器知道它是什么,因此知道它的大小。因此编译器可以用实际大小替换sizeof()

2. Why is the length(count/size) info lost when "a" is passed to the test() function?

在这种情况下,b被声明为指针(即使它可能指向a)。给定一个指针,编译器不知道指向的数据的大小。

答案 5 :(得分:0)

数组指针不存储大小。但是,[]类型实际上不是指针。这是一种不同的类型。当你说int a[] = {1,2,3};时你定义了3个元素的数组,并且由于它是这样定义的,sizeof(a)给出了整个数组的大小。

然而,当你将参数声明为int a []时,它与int * a几乎相同,而sizeof(a)将是指针的大小(它恰好可能与{{1}的大小相同}}, 但不总是)。

在C中,无法将大小存储在指针类型中,因此如果需要大小,则必须将其作为附加参数传递或使用int