是否可以将预定义大小的数组传递给C函数,以便在该函数中使用`sizeof`检索其大小?

时间:2014-12-09 23:55:25

标签: c arrays

在下面的示例中,是否可以使用这样的签名声明test(),以便打印6?我希望这可以用于样式和可读性目的,因此很清楚该函数采用了正好6个字符的数组,并且它实际上可以使用sizeof获取此信息。

#include <stdio.h>

void test( char foo[ 6 ] )
{
  printf( "%zu\n", sizeof( foo ) ); // Prints 8 as it's a pointer now, but I want 6 as in an array
}

int main()
{
  char foo[ 6 ];
  printf( "%zu\n", sizeof( foo ) ); // Prints 6, which is what I want
  test( foo );
  return 0;
}

到目前为止,我能想到的最好的是:

typedef char Foo[ 6 ];
void test( Foo foo )
{
  printf( "%zu\n", sizeof( Foo ) ); // Works, but it doesn't even use foo, and I want to get the size information from foo! What if I change the signature of the function later? I would have to update this line too, which is something I'd like to avoid
}

2 个答案:

答案 0 :(得分:4)

是的,有可能:

#include <stdio.h>

void test(char (*foo)[6]) // "declare foo as pointer to array 6 of char" 
{
  printf("%zu\n", sizeof(*foo)); // mind the asterisk
}

int main(void)
{
  char foo[6];
  test(&foo); // mind the ampersand
  return 0;
}

比较cdecl.org(“C gibberish↔English”)


另一个选择是包装数组。但是如果你不喜欢引用/解除引用,那么这个带有附加成员访问权限的解决方案可能不是你想要的:

#include <stdio.h>

typedef struct
{
  char data[6];
} char_6_array_t;

void test(char_6_array_t foo)
{
  // prints "6: abcdef"
  printf("%zu: %.*s\n", sizeof(foo.data), (int) sizeof(foo.data), foo.data);
}

int main(void)
{
  char_6_array_t foo = { {"abcdef"} };

  // Depending on the ABI, this prints 6, 8, or possibly 16:
  printf("%zu\n", sizeof(foo));

  test(foo);
  return 0;
}

答案 1 :(得分:2)

不是没有一些杂技。

有很多方法可以让它发挥作用,无论是你问题中的全局变量,还是凯提出的解决方案。但是C语言不会通过值将整个数组作为函数参数传递。您的test函数只接收指向char的指针,编译器不会告诉您指针指向的数组大小。

其他一些语言,比如C ++,会为你处理这类事情。但是在C中,你只需要自己跟踪尺寸,无论如何。一种常见的方法是在函数中添加另一个参数,传递数组的大小。

在你给出的函数原型中:

void test( char foo[ 6 ] )

我认为不幸的是编译器忽略了6,尽管你可能会认为这并没有多大意义。对于多维数组,编译器确实注意你给出的大小,除了第一个,所以foo[][6]有效,并且必须告诉编译器每行的每一行你的阵列结束了。 (见this question。)

另一种解决方法是使用这样的结构:

struct array {
    char *a;   // pointer to your real array
    size_t s;  // how many elements your array has
};

您可以将其中一个结构传递给您的函数,然后从中读取大小。