Reputation: 5821
In the following example, is it possible to declare test() with such a signature so it would print 6
? I would like this for style and readability purposes, so that it's clear that the function takes an array of exactly 6 chars, and it actually can get this information with 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;
}
So far, the best I could come up with is this:
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
}
Upvotes: 0
Views: 109
Reputation: 1493
Not without some acrobatics.
There are ways to make it work, either with global variables as in your question, or the solutions proposed by Kay. But the C language does not pass entire arrays by value as function arguments. Your test
function only receives a pointer to a char
, and the compiler will not tell you what size of array the pointer might point to.
Some other languages, like C++, handle this sort of thing for you. But in C, you just have to track the size yourself, one way or another. A common way is to add another argument to your function, where you pass in the size of your array.
In the function prototype you gave:
void test( char foo[ 6 ] )
I think that the compiler unfortunately just ignores the 6
, although you could argue that that doesn't make much sense. For a multi-dimensional array, the compiler does pay attention to the sizes you give, except for the first one, so foo[][6]
works, and is necessary to tell the compiler where each row of your array ends. (See this question.)
Yet another workaround would to use a structure like this:
struct array {
char *a; // pointer to your real array
size_t s; // how many elements your array has
};
You could pass one of those structures to your function, and then read the size out of it.
Upvotes: 2
Reputation: 26022
Yes, it is possible:
#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;
}
Compare cdecl.org ("C gibberish ↔ English") for
char (*foo)[6]
: "declare foo as pointer to array 6 of char"char foo[6]
: "declare foo as array 6 of char"char *foo[6]
: "declare foo as array 6 of pointer to char"Another option is wrapping the array. But if you don't like referencing/dereferencing, then this solution with an addition member access probably is not what you are looking for, either:
#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;
}
Upvotes: 4