How do I allocate the size of an array dynamically? - arrays

include <stdio.h>
int main() {
int num = 10;
int arr[num];
for(int i = 0; i < num; i++){
arr[num] = i+1;
}
}
Some colleague of mine says that this code is not correct and that it is illegal. However, when I am running it, it is working without any errors. And he does not know how to explain why it is working and why I should not code like this. Can you please help me. I am a beginner and I want to learn C.

If you want to dynamically allocate an array of length n ints, you'll need to use either malloc or calloc. Calloc is preferred for array allocation because it has a built in multiplication overflow check.
int num = 10;
int *arr = calloc(num, sizeof(*arr));
//Do whatever you need to do with arr
free(arr);
arr = NULL;
Whenever you allocate memory with malloc or calloc, always remember to free it afterwards, then set the pointer to NULL in order to prevent any accidental, future references, as well as to prevent a double free.

While not necessarily illegal, this code won't do what you intend. When you declare an array, you declare the number of items you want to store, in this instance num. So when you declare num = 10 and arr[num] you get an array that can hold 10 integers. C arrays are indexed from 0, so the indices are 0-9, not 1-10. This is probably what they mean by illegal. Since you are writing to arr[num] or arr[10], you are attempting to use memory beyond the memory allocated for the array.
Additionally, if I understand the intent of the program correctly, you want to fill in the array with the numbers 1-10. To do this, you'd need to access each index individually. You're almost there, the only problem being arr[num] = i + 1;. As mentioned before, it is beyond the end of the array. However, you should probably be using i as your index, so arr[i], because this will access each index, 0-9.

Are you learning C or C++?
Your colleague meant that in that code of yours you are doing something different from what you wanted. It's working because of some additional factors. Because C/C++ standards are evolving and so do compilers as well. Let me show you.
Static array
When you a beginner, it's generally advised to stick to the concept that "a typed array of the compilation-given size" is int arr[N], where N is a constant. You allocate it on the stack and you don't manage it's memory.
In C++11 you can use a constexpr (constant expression), but is still not an arbitrary variable.
In C++14 you can use a "simple expression" for size, but you shouldn't try a lot of it before getting the array concept beforehand. Also, GCC compiler provides an extension to support variable sized arrays, it could be an explanation of "why the code is working at all".
Notice: variable sized arrays are not the same as dynamic arrays. They are not that static arrays from the first chapter of a C/C++ guide book as well.
There also exists a modern approach – std::array<int, 10> but once again, don't start with it.
Dynamic array
When you need to create an array in runtime everything changes. First of all, you allocate it on the heap and either you mange it's memory yourself (if you do not, you get a memory leak, a Pure C way) or use special C++ classes like std::vector. Once again, vectors should be used after getting to know Pure C arrays.
Your colleague must have been meaning something like that:
int* arr = new int[some_variable]; // this is dynamic array allocation
delete[] arr; // in modern C/C++ you can write "delete arr;" as well
So, your compiler made it work in this exact case, but you definitely should not rely on the approach you've tried. It's not an array allocation at all.
TL;DR:
In C++ variable length arrays are not legal
g++ compiler allows variable length arrays, because C99 allows them
Remember that C and C++ are two different languages
The piece of code from the question seems to be not doing what you'd wanted it to do
As others mentioned, it should be arr[i] = i + 1 instead, you are assigning to the same array item all the time otherwise

Related

How to pass C array to Swift [duplicate]

This question already has answers here:
float* array to NSArray, iOS
(1 answer)
Inter-operability of Swift arrays with C?
(4 answers)
Closed 5 months ago.
Newbie to Objective-C and Swift here. I'm creating an NSArray from a C float array with the following code:
float* output_f = output.data_ptr<float>();
NSMutableArray *results = [NSMutableArray arrayWithCapacity: 1360*1060]
for (int i = 0; i < 1360 * 1016; i++) {
[results insertObject:#(output_f[i]) atIndex:i];
}
However since there are over a million samples to be inserted this is slow and is becoming a bottle-neck in my application. Is there a quicker way to create an NSArray from a C array without copying the elements one-by-one?
There's no need to go through Obj-C. Assuming that output_f appears in an include file that's included via your bridging header, Swift will see its type as UnsafeMutablePointer<CFloat> (CFloat is just a typealias for Float, named to clarify that it corresponds to the C type).
Assuming you also make the number of floats in the array available, lets say included somewhere in your bridged header files is:
extern float* output_f;
extern int output_f_count;
Then on the Swift-side, you can use them like this:
let outputFloats = UnsafeMutableBufferPointer<CFloat>(
start: output_f,
count: Int(output_f_count))
The cast of output_f_count to Int is necessary because Swift interprets C's int as CInt (aka Int32).
You can use UnsafeMutablePointer much like array, but there's no copying. It just aliases the C data in Swift.
If you want to make sure you don't mutate the data, you can create an UnsafeBufferPointer instead, but you'll need to cast the pointer.
let outputFloats = UnsafeBufferPointer<CFloat>(
start: UnsafePointer(output_f),
count: Int(output_f_count))
Since there's no copying, both of those options are very fast. However, they are pointers. If Swift modifies the contents, the C code will see the changed data, and vice-versa. That may or may not be a good thing, depending on your use case, but you definitely want to be aware of it.
If you want to make a copy, you can make a Swift Array very easily like this:
let outputFloatsArray = [CFloat](outputFloats)
Now you have you Swift-side copy in an Array.
As a very closely related thing, if in a C header, output_f were declared as an actual array like this,
extern float output_f[1360*1060];
Then Swift doesn't see a pointer. It sees, believe it or not, a tuple... a great big ugly tuple with a crap-load of CFloat members, which has the benefit of being a value type, but is hard to work with directly because you can't index into it. Fortunately you can work around that:
withUnsafeBytes(of: output_f)
{
let outputFloats = $0.bindMemory(to: CFloat.self)
// Now within the scope of this closure you can use outputFloats
// just as before.
}
Note: You can also use the pointer directly without going through the buffer pointer types, and because you avoid bounds-checking that way, it is a tiny bit faster, but just a very tiny bit, it's more awkward, and well... you lose the error catching benefits of bounds-checking. Plus the buffer pointer types provide all the RandomAccessCollection methods like map, filter, forEach, etc...
Update:
In comments OP said that he had tried this approach but got EXEC_BAD_ACCESS while dereferencing them. Missing is the context of what is happening between obtaining the pointer from output and its being available to Swift.
Given the clue from earlier that it's actually C++, I think output is probably std::vector<float>, and its probably going out of scope before Swift does anything with the pointers, so its destructor is being called, which of course, deletes its internal data pointer. In that case Swift is accessing memory that is no longer valid.
There are two ways to address this. The first is to make sure that output is not cleaned up until after Swift is done with it's data. The other option, is to copy the data in C.
const int capacity = 1360*1060;
float* p = output.data_ptr<float>();
// static_cast because the above template syntax indicates
// this is actually C++, not C.
float* output_f = static_cast<float*>(calloc(capacity, sizeof(float)));
memcpy(output_f, p, capacity * sizeof(float));
Now output can be cleaned up before Swift accesses output_f. Also this makes the copy that was originally asked about much faster that using NSArray. Assuming the C code doesn't use output_f after this, Swift can just take ownership of it. In that case, Swift needs to be sure to call free(outout_f) when it's done.
If the Swift code doesn't care about it being in an actual array, the Unsafe...BufferPointer types will do the job.
However, if an actual Array is desired, this will be yet another copy, and copying the same data twice just to get it in a Swift Array doesn't make sense if it can be avoided. How to avoid it depends on whether C (or Obj-C) is calling Swift, or Swift is calling Obj-C. I'm going to assume that it's Swift calling C. So let's assume that Swift is calling some C function get_floats() defined like this:
extern "C" *float get_floats()
{
const int capacity = 1360*1060;
float* p = output.data_ptr<float>();
// static_cast because the above template syntax indicates
// this is actually C++, not C.
float* output_f = static_cast<float*>(
calloc(capacity, sizeof(float))
);
memcpy(output_f, p, capacity * sizeof(float));
// Maybe do other work including disposing of `output`
return output_f;
}
You want to change the interface so that a pre-allocated pointer is provided as a parameter, along with its capacity.
extern "C" void get_floats(float *output_f, int capacity)
{
float* p = output.data_ptr<float>();
memcpy(output_f, p, capacity * sizeof(float));
// Maybe do other work including disposing of `output`
// can use return for something else now -- maybe error code?
}
On the Swift side, you could allocate pointers, but since you want it in an Array anyway:
var outputFloats = [Array](repeating: 0, count: 1360*1060)
outputFloats.withUnsafeMutableBuffer {
get_floats($0.baseAddress, CInt($0.count))
}
// Now the array is populated with the contents of the C array.
One last thing. The above code makes an assumption that output.data_ptr() points to at least capacity number of floats. Are you sure this is true? Assuming output is std::vector, it would be better to change the memcpy call to:
const size_t floatsToCopy = std::min(capacity, output.size())
memcpy(output_f, p, floatsToCopy * sizeof(float));
That ensures that you're not reading garbage from the end of real data if it's actually less than capacity. Then you can return floatsToCopy; from get_floats.
Then on the Swift side, it looks like this:
var outputFloats = [Array](repeating: 0, count: 1360*1060)
let floatsCopied = outputFloats.withUnsafeMutableBuffer {
get_floats($0.baseAddress, CInt($0.count))
}
outputFloats.removeLast(
outputFloats.count - Int(floatsCopied),
keepingCapacity: true)
You don't actually have to use the keepingCapacity parameter, but doing so allows you to re-use the array without having to pay for more memory allocations. Just refill out to full capacity before calling get_floats again with the same array. Plus unless your peak memory usage is an issue, keepingCapacity: true is likely faster, and at least no worse, than the default, because without it, Array might choose to reallocate to the smaller size, which internally is an allocation, a copy, and a free, and the whole point was to avoid a copy... but the dynamic memory allocation is the really slow part. Given CPU caches and the way instruction pipelines work, you can do a lot of sequential copying in the time it takes to do a single memory allocation.
According to the comments section your final goal is to read C-array data in Swift. Provided you know the length of the array, you can return it from an Objective-C function as a pointer:
- (float *)cArray {
float *arr = (float *)malloc(sizeof(float) * 4);
for (int i = 0; i < 4; ++i) {
arr[i] = i;
}
return arr;
}
And just read it from an UnsafePointer in Swift:
let ptr = TDWObject().cArray()
(0 ..< 4).forEach {
print(ptr.advanced(by: $0).pointee)
}
Don't forget to deallocate the pointer when you are done with it:
ptr.deallocate()

Is it good programming practice in C to use first array element as array length?

Because in C the array length has to be stated when the array is defined, would it be acceptable practice to use the first element as the length, e.g.
int arr[9]={9,0,1,2,3,4,5,6,7};
Then use a function such as this to process the array:
int printarr(int *ARR) {
for (int i=1; i<ARR[0]; i++) {
printf("%d ", ARR[i]);
}
}
I can see no problem with this but would prefer to check with experienced C programmers first. I would be the only one using the code.
Well, it's bad in the sense that you have an array where the elements does not mean the same thing. Storing metadata with the data is not a good thing. Just to extrapolate your idea a little bit. We could use the first element to denote the element size and then the second for the length. Try writing a function utilizing both ;)
It's also worth noting that with this method, you will have problems if the array is bigger than the maximum value an element can hold, which for char arrays is a very significant limitation. Sure, you can solve it by using the two first elements. And you can also use casts if you have floating point arrays. But I can guarantee you that you will run into hard traced bugs due to this. Among other things, endianness could cause a lot of issues.
And it would certainly confuse virtually every seasoned C programmer. This is not really a logical argument against the idea as such, but rather a pragmatic one. Even if this was a good idea (which it is not) you would have to have a long conversation with EVERY programmer who will have anything to do with your code.
A reasonable way of achieving the same thing is using a struct.
struct container {
int *arr;
size_t size;
};
int arr[10];
struct container c = { .arr = arr, .size = sizeof arr/sizeof *arr };
But in any situation where I would use something like above, I would probably NOT use arrays. I would use dynamic allocation instead:
const size_t size = 10;
int *arr = malloc(sizeof *arr * size);
if(!arr) { /* Error handling */ }
struct container c = { .arr = arr, .size = size };
However, do be aware that if you init it this way with a pointer instead of an array, you're in for "interesting" results.
You can also use flexible arrays, as Andreas wrote in his answer
In C you can use flexible array members. That is you can write
struct intarray {
size_t count;
int data[]; // flexible array member needs to be last
};
You allocate with
size_t count = 100;
struct intarray *arr = malloc( sizeof(struct intarray) + sizeof(int)*count );
arr->count = count;
That can be done for all types of data.
It makes the use of C-arrays a bit safer (not as safe as the C++ containers, but safer than plain C arrays).
Unforntunately, C++ does not support this idiom in the standard.
Many C++ compilers provide it as extension though, but it is not guarantueed.
On the other hand this C FLA idiom may be more explicit and perhaps more efficient than C++ containers as it does not use an extra indirection and/or need two allocations (think of new vector<int>).
If you stick to C, I think this is a very explicit and readable way of handling variable length arrays with an integrated size.
The only drawback is that the C++ guys do not like it and prefer C++ containers.
It is not bad (I mean it will not invoke undefined behavior or cause other portability issues) when the elements of array are integers, but instead of writing magic number 9 directly you should have it calculate the length of array to avoid typo.
#include <stdio.h>
int main(void) {
int arr[9]={sizeof(arr)/sizeof(*arr),0,1,2,3,4,5,6,7};
for (int i=1; i<arr[0]; i++) {
printf("%d ", arr[i]);
}
return 0;
}
Only a few datatypes are suitable for that kind of hack. Therefore, I would advise against it, as this will lead to inconsistent implementation styles across different types of arrays.
A similar approach is used very often with character buffers where in the beginning of the buffer there is stored its actual length.
Dynamic memory allocation in C also uses this approach that is the allocated memory is prefixed with an integer that keeps the size of the allocated memory.
However in general with arrays this approach is not suitable. For example a character array can be much larger than the maximum positive value (127) that can be stored in an object of the type char. Moreover it is difficult to pass a sub-array of such an array to a function. Most of functions that designed to deal with arrays will not work in such a case.
A general approach to declare a function that deals with an array is to declare two parameters. The first one has a pointer type that specifies the initial element of an array or sub-array and the second one specifies the number of elements in the array or sub-array.
Also C allows to declare functions that accepts variable length arrays when their sizes can be specified at run-time.
It is suitable in rather limited circumstances. There are better solutions to the problem it solves.
One problem with it is that if it is not universally applied, then you would have a mix of arrays that used the convention and those that didn't - you have no way of telling if an array uses the convention or not. For arrays used to carry strings for example you have to continually pass &arr[1] in calls to the standard string library, or define a new string library that uses "Pascal strings" rather then "ASCIZ string" conventions (such a library would be more efficient as it happens),
In the case of a true array rather then simply a pointer to memory, sizeof(arr) / sizeof(*arr) will yield the number of elements without having to store it in the array in any case.
It only really works for integer type arrays and for char arrays would limit the length to rather short. It is not practical for arrays of other object types or data structures.
A better solution would be to use a structure:
typedef struct
{
size_t length ;
int* data ;
} intarray_t ;
Then:
int data[9] ;
intarray_t array{ sizeof(data) / sizeof(*data), data } ;
Now you have an array object that can be passed to functions and retain the size information and the data member can be accesses directly for use in third-party or standard library interfaces that do not accept the intarray_t. Moreover the type of the data member can be anything.
Obviously NO is the answer.
All programming languages has predefined functions stored along with the variable type. Why not use them??
In your case is more suitable to access count /length method instead of testing the first value.
An if clause sometimes take more time than a predefined function.
On the first look seems ok to store the counter but imagine you will have to update the array. You will have to do 2 operations, one to insert other to update the counter. So 2 operations means 2 variables to be changed.
For statically arrays might be ok to have them counter then the list, but for dinamic ones NO NO NO.
On the other hand please read programming basic concepts and you will find your idea as a bad one, not complying with programming principles.

Malloc or normal array definition?

When shall i use malloc instead of normal array definition in C?
I can't understand the difference between:
int a[3]={1,2,3}
int array[sizeof(a)/sizeof(int)]
and:
array=(int *)malloc(sizeof(int)*sizeof(a));
In general, use malloc() when:
the array is too large to be placed on the stack
the lifetime of the array must outlive the scope where it is created
Otherwise, use a stack allocated array.
int a[3]={1,2,3}
int array[sizeof(a)/sizeof(int)]
If used as local variables, both a and array would be allocated on the stack. Stack allocation has its pros and cons:
pro: it is very fast - it only takes one register subtraction operation to create stack space and one register addition operation to reclaim it back
con: stack size is usually limited (and also fixed at link time on Windows)
In both cases the number of elements in each arrays is a compile-time constant: 3 is obviously a constant while sizeof(a)/sizeof(int) can be computed at compile time since both the size of a and the size of int are known at the time when array is declared.
When the number of elements is known only at run-time or when the size of the array is too large to safely fit into the stack space, then heap allocation is used:
array=(int *)malloc(sizeof(int)*sizeof(a));
As already pointed out, this should be malloc(sizeof(a)) since the size of a is already the number of bytes it takes and not the number of elements and thus additional multiplication by sizeof(int) is not necessary.
Heap allocaiton and deallocation is relatively expensive operation (compared to stack allocation) and this should be carefully weighted against the benefits it provides, e.g. in code that gets called multitude of times in tight loops.
Modern C compilers support the C99 version of the C standard that introduces the so-called variable-length arrays (or VLAs) which resemble similar features available in other languages. VLA's size is specified at run-time, like in this case:
void func(int n)
{
int array[n];
...
}
array is still allocated on the stack as if memory for the array has been allocated by a call to alloca(3).
You definately have to use malloc() if you don't want your array to have a fixed size. Depending on what you are trying to do, you might not know in advance how much memory you are going to need for a given task or you might need to dynamically resize your array at runtime, for example you might enlarge it if there is more data coming in. The latter can be done using realloc() without data loss.
Instead of initializing an array as in your original post you should just initialize a pointer to integer like.
int* array; // this variable will just contain the addresse of an integer sized block in memory
int length = 5; // how long do you want your array to be;
array = malloc(sizeof(int) * length); // this allocates the memory needed for your array and sets the pointer created above to first block of that region;
int newLength = 10;
array = realloc(array, sizeof(int) * newLength); // increase the size of the array while leaving its contents intact;
Your code is very strange.
The answer to the question in the title is probably something like "use automatically allocated arrays when you need quite small amounts of data that is short-lived, heap allocations using malloc() for anything else". But it's hard to pin down an exact answer, it depends a lot on the situation.
Not sure why you are showing first an array, then another array that tries to compute its length from the first one, and finally a malloc() call which tries do to the same.
Normally you have an idea of the number of desired elements, rather than an existing array whose size you want to mimic.
The second line is better as:
int array[sizeof a / sizeof *a];
No need to repeat a dependency on the type of a, the above will define array as an array of int with the same number of elements as the array a. Note that this only works if a is indeed an array.
Also, the third line should probably be:
array = malloc(sizeof a);
No need to get too clever (especially since you got it wrong) about the sizeof argument, and no need to cast malloc()'s return value.

Dynamic Array printing

I am trying to print a dynamic array, but I am having trouble with the bounds for the array.
For a simple example, lets say I'm trying to loop through an array of ints. How can I get the size of the array? I was trying to divide the size of the array by the size of the type like this sizeof(list)/sizeof(int) but that was not working correctly. I understand that I was trying to divide the size of the pointer by the type.
int *list
// Populate list
int i;
for(i = 0; i < ????; i++)
printf("%d", list[i]);
With dynamic arrays you need to maintain a pointer to the beginning address of the array and a value that holds the number of elements in that array. There may be other ways, but this is the easiest way I can think of.
sizeof(list) will also return 4 because the compiler is calculating the size of an integer pointer, not the size of your array, and this will always be four bytes (depending on your compiler).
YOU should know the size of the array, as you are who allocated it.
sizeof is an operator, which means it does its job at compile time. It will give you the size of an object, but not the length of an array.
So, sizeof(int*) is 32/62-bit depending on architecture.
Take a look at std::vector.
There is no standardized method to get the size of allocated memory block. You should keep size of list in unsigned listSize like this:
int *list;
unsigned listSize;
list = malloc(x * sizeof(int));
listSize = x;
If you are coding in C++, then it is better to use STL container like std::vector<>
As you wrote, you really did tried to divide the size of a pointer since list is declared as a pointer, and not an array. In those cases, you should keep the size of the list during the build of it, or finish the list with a special cell, say NULL, or anything else that will not be used in the array.
Seeing some of the inapropriate links to C++ tools for a C question, here is an answer for modern C.
Your ideas of what went wrong are quite correct, as you did it you only have a pointer, no size information about the allocation.
Modern C has variable length arrays (VLA) that you can either use directly or via malloc. Direcly:
int list[n];
and then your idea with the sizeof works out of the box, even if you changed your n in the mean time. This use is to be taken with a bit of care, since this is allocated on the stack. You shouldn't reserve too much, here. For a use with malloc:
int (list*)[n] = malloc(*list);
Then you'd have to adapt your code a bit basically putting a (*list) everywhere you had just list.
If by size you mean the number of elements then you could keep it in a counter that gets a ++ each time you push an element or if you dont mind the lost cycles you could make a function that gets a copy of the pointer to the first location, runs thru the list keeping a counter until it finds a k.next==null. or you could keep a list that as a next and a prev that way you wouldnt care if you lost the beginning.

Is there a standard function in C that would return the length of an array?

Is there a standard function in C that would return the length of an array?
Often the technique described in other answers is encapsulated in a macro to make it easier on the eyes. Something like:
#define COUNT_OF( arr) (sizeof(arr)/sizeof(0[arr]))
Note that the macro above uses a small trick of putting the array name in the index operator ('[]') instead of the 0 - this is done in case the macro is mistakenly used in C++ code with an item that overloads operator[](). The compiler will complain instead of giving a bad result.
However, also note that if you happen to pass a pointer instead of an array, the macro will silently give a bad result - this is one of the major problems with using this technique.
I have recently started to use a more complex version that I stole from Google Chromium's codebase:
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
In this version if a pointer is mistakenly passed as the argument, the compiler will complain in some cases - specifically if the pointer's size isn't evenly divisible by the size of the object the pointer points to. In that situation a divide-by-zero will cause the compiler to error out. Actually at least one compiler I've used gives a warning instead of an error - I'm not sure what it generates for the expression that has a divide by zero in it.
That macro doesn't close the door on using it erroneously, but it comes as close as I've ever seen in straight C.
If you want an even safer solution for when you're working in C++, take a look at Compile time sizeof_array without using a macro which describes a rather complex template-based method Microsoft uses in winnt.h.
No, there is not.
For constant size arrays you can use the common trick Andrew mentioned, sizeof(array) / sizeof(array[0]) - but this works only in the scope the array was declared in.
sizeof(array) gives you the size of the whole array, while sizeof(array[0]) gives you the size of the first element.
See Michaels answer on how to wrap that in a macro.
For dynamically allocated arrays you either keep track of the size in an integral type or make it 0-terminated if possible (i.e. allocate 1 more element and set the last element to 0).
sizeof array / sizeof array[0]
The number of elements in an array x can be obtained by:
sizeof(x)/sizeof(x[0])
You need to be aware that arrays, when passed to functions, are degraded into pointers which do not carry the size information. In reality, the size information is never available to the runtime since it's calculated at compile time, but you can act as if it is available where the array is visible (i.e., where it hasn't been degraded).
When I pass arrays to a function that I need to treat as arrays, I always ensure two arguments are passed:
the length of the array; and
the pointer to the array.
So, whilst the array can be treated as an array where it's declared, it's treated as a size and pointer everywhere else.
I tend to have code like:
#define countof(x) (sizeof(x)/sizeof(x[0]))
: : :
int numbers[10];
a = fn (countof(numbers),numbers);
then fn() will have the size information available to it.
Another trick I've used in the past (a bit messier in my opinion but I'll give it here for completeness) is to have an array of a union and make the first element the length, something like:
typedef union {
int len;
float number;
} tNumber;
tNumber number[10];
: : :
number[0].len = 5;
a = fn (number);
then fn() can access the length and all the elements and you don't have to worry about the array/pointer dichotomy.
This has the added advantage of allowing the length to vary (i.e., the number of elements in use, not the number of units allocated). But I tend not to use this anymore since I consider the two-argument array version (size and data) better.
I created a macro that returns the size of an array, but yields a compiler error if used on a pointer. Do however note that it relies on gcc extensions. Because of this, it's not a portable solution.
#define COUNT(a) (__builtin_choose_expr( \
__builtin_types_compatible_p(typeof(a), typeof(&(a)[0])), \
(void)0, \
(sizeof(a)/sizeof((a)[0]))))
int main(void)
{
int arr[5];
int *p;
int x = COUNT(arr);
// int y = COUNT(p);
}
If you remove the comment, this will yield: error: void value not ignored as it ought to be
The simple answer, of course, is no. But the practical answer is "I need to know anyway," so let's discuss methods for working around this.
One way to get away with it for a while, as mentioned about a million times already, is with sizeof():
int i[] = {0, 1, 2};
...
size_t i_len = sizeof(i) / sizeof(i[0]);
This works, until we try to pass i to a function, or take a pointer to i. So what about more general solutions?
The accepted general solution is to pass the array length to a function along with the array. We see this a lot in the standard library:
void *memcpy(void *s1, void *s2, size_t n);
Will copy n bytes from s1 to s2, allowing us to use n to ensure that our buffers never overflow. This is a good strategy - it has low overhead, and it actually generates some efficient code (compare to strcpy(), which has to check for the end of the string and has no way of "knowing" how many iterations it must make, and poor confused strncpy(), which has to check both - both can be slower, and either could be sped up by using memcpy() if you happen to have already calculated the string's length for some reason).
Another approach is to encapsulate your code in a struct. The common hack is this:
typedef struct _arr {
size_t len;
int arr[0];
} arr;
If we want an array of length 5, we do this:
arr *a = malloc(sizeof(*a) + sizeof(int) * 5);
a->len = 5;
However, this is a hack that is only moderately well-defined (C99 lets you use int arr[]) and is rather labor-intensive. A "better-defined" way to do this is:
typedef struct _arr {
size_t len;
int *arr;
} arr;
But then our allocations (and deallocations) become much more complicated. The benefit of either of these approaches is, of course, that now arrays you make will carry around their lengths with them. It's slightly less memory-efficient, but it's quite safe. If you chose one of these paths, be sure to write helper functions so that you don't have to manually allocate and deallocate (and work with) these structures.
If you have an object a of array type, the number of elements in the array can be expressed as sizeof a / sizeof *a. If you allowed your array object to decay to pointer type (or had only a pointer object to begin with), then in general case there's no way to determine the number of elements in the array.

Resources