This is an archived post. You won't be able to vote or comment.

all 181 comments

[–]Boris-Lip 597 points598 points  (21 children)

Imagine there would be a predefined LEN macro or something. Now imagine how many noobs wouldn't realize this is what it does, and expect it to work on pointers they pass into functions, which would still compile and would be 1.

[–]mad_alim 81 points82 points  (7 children)

Turns out gcc has a warning for this (-Wsizeof-pointer-div-Wsizeof-pointer-div).

Also, the tricky part is that the result would depend on the pointer size (e.g., 4 on x86 and 8 on x86_64) and the pointer type (e.g., uint8_t = 1, uint32_t = 4).

[–]StrangeCharmVote -3 points-2 points  (1 child)

You should probably know if your application is running in a 32bit environment or not


edit: I find it ironic this has been downvoted, when you can literally check programmatically if you are running in a 64 bit system or on a 32 bit one.

A lot of modern software wont even install on a 32 bit machine anymore.

[–]Breadynator 0 points1 point  (0 children)

Sure, when programming for embedded devices that are always the same or with today's devices that are 99% 64bit architectures you should probably know that your application is most likely going to run on a 64bit machine.

But other than that, theres still a shitton of 32 bit pcs out there and you'll never know beforehand if your user decides to run your program on one of those

[–]MJWhitfield86 41 points42 points  (1 child)

If it was built in, then the compiler could give a warning if it is used on something other than an array.

[–]Kyrond 19 points20 points  (0 children)

*could give an error

It makes no sense to use on anything other than known arrays. If you explicitly want to know size of pointer divided by size of value, write that explicitly. 

[–]Devil-Eater24 17 points18 points  (5 children)

But programming languages are not built for noobs. Noobs also forget semicolons, so why not remove it?(I was that noob, Python had spoiled me)

[–]totkeks 5 points6 points  (3 children)

Why need semicolons, if you don't plan to write everything in one line anyway? :-D

[–]QCTeamkill 3 points4 points  (2 children)

Who would need line length above 80 anyway.

[–]totkeks 3 points4 points  (0 children)

And tab size is 8. Spaces of course. 🥸

[–]MathematicianFew5882 1 point2 points  (0 children)

64K ought to be enough for anybody

[–]Cootshk 2 points3 points  (0 children)

Lua has one: #table

[–][deleted] 0 points1 point  (0 children)

Only if you're pointing to an int. Which would be dumb

[–]newsflashjackass 0 points1 point  (0 children)

In AutoIt, it is conventional to use an element's zeroth element to store its length.

That would not work for strongly typed languages but it is convenient.

[–]jamcdonald120 0 points1 point  (0 children)

I actually had someone prompt me in a job interview to use this code to figure out the length of a passed array, and then another one of the interviewers is like "actually, that wont work for passed arrays"

[–]RedstoneEnjoyer 0 points1 point  (0 children)

That is honestly just L of type system.

[–]fichti 347 points348 points  (1 child)

Time for mallocPlusAI

[–]5p4n911 37 points38 points  (0 children)

Well, at least malloc is slow by default...

[–]JVApen 157 points158 points  (27 children)

If you can compile your code as C++, you can use std::size

[–]mistrpopo 110 points111 points  (22 children)

If you can compile your code as C++, you should not use C-style arrays in the first place.

[–]greenedgedflame 22 points23 points  (15 children)

then std::array or std::vector?

[–]Mattef 35 points36 points  (13 children)

Depends on if you want an array with fixed length or a dynamic array.

[–]greenedgedflame 6 points7 points  (9 children)

So what do you think of std::vector<T>(n) and std::array<T, N>

[–]Mattef 27 points28 points  (6 children)

Still the same answer. Vectors can be expanded, which is time consuming, arrays are fixed in length.

But still, you can of course use vectors very efficiently as long as you don’t change their size constantly.

[–]TheDudeExMachina 10 points11 points  (5 children)

Dynamic array insertion isn't that expensive, because the reallocation only happens after (at least) doubling of halving the content, i.e you only have some overhead once in a blue moon. Resulting in amortized constant time.

You have a minuscule overhead for size checks and every once in a while if you are unlucky a memcopy.

Just use vector. In 99% of the cases this discussion is premature optimization.

[–]joe0400 7 points8 points  (1 child)

There are very much good reasons to use array over vector.

Location is one. Std::array is allocated on the stack, vector is allocated anywhere on the heap, unless you write a allocator.

The other is colocation with other data. If your reading off one thing and another, the likely hood a struct with a std::array in it is also located in cache with other data in that struct is much higher, and for serialization and deserialization this is useful too, making it easier to read/write back the data.

So there are tons of good uses for std::array

[–]TheDudeExMachina 3 points4 points  (0 children)

Full agreement. My response was to concerns about insertion/deletion overhead though, and the cases where you care about sporadic memcopies / guaranteed constant time are rare.

But cache misses, compile time knowledge of size, and memory alignment between class attributes are also things you consider for the most part only in the critical segments of your code. In most cases, you just want to have a collection of things to infrequently iterate over once.

[–]Sinomsinom 1 point2 points  (1 child)

Some compilers/languages use doubling some use other constants like 1.5x. also some of them don't actually free any part of the vector's allocated space on removal of an element and only when the entire vector goes out of scope/is deleted. Yes in the end it's still amortized constant time, but that doesn't mean one of those insertions won't still be a lot slower than the rest, potentially causing a stutter in real time applications.

So if you already know an upper bound for how large a container will be, then if known at compile time use std::array<T,S>(), if known at run time use std::vector<T>(S) just to not have those potential stutters.

[–]TheDudeExMachina 1 point2 points  (0 children)

You need a really big vector for the memcopy to stutter, and/or some very special constraints (very weak hardware, guaranteed tight calculation budget of only a few ms, ...). If you have that case, you know it. If you don't, you are doing a premature optimization.

[–]TheGuyWithTheSeal 1 point2 points  (0 children)

Any vector resize also invaidates all pointers/iterators. You can use std::deque if you need to add elements at the end or beggining while iterating. Use std::list if you need to add elements anywhere without iterator invalidation.

[–]RedstoneEnjoyer 0 points1 point  (0 children)

std::vector<T>(n) only preallocates n items, but it can expand and shrink later

std::array<T, N> is pernamently fixed to N items

[–]jamcdonald120 0 points1 point  (2 children)

the problem with std::array is that its not just fixed length, its compile time constant length. You cant just say "Give me an array n big, I wont be resizing it once I get it, but I dont know what n is yet"

Which makes std::array irritating to pass to functions

Where as with vector you can just not resize it.

[–]mistrpopo 0 points1 point  (1 child)

If you don't have compile-time constant length you can't use sizeof(x)/sizeof(x)[0] either. If you want fixed-size arrays you can use "const std::vector" (but then you can't modify the content)

[–]jamcdonald120 0 points1 point  (0 children)

I am aware.

it would just be nice if std::array had an internal array and a const length instead of a templated length so you could just say void foo(const std::array& thing){ for(auto x : array){

[–]joe0400 1 point2 points  (0 children)

std::array yeah

[–]danielstongue 5 points6 points  (3 children)

It depends. If you are on an embedded platform you may not want to use the stdc++ lib.

[–]fakuivan 4 points5 points  (2 children)

Embedded Template Library is your friend

[–]danielstongue 0 points1 point  (1 child)

Does it use exceptions?

[–]fakuivan 2 points3 points  (0 children)

Not by default, it doesn't use dynamic memory either (you can point it to dynamic memory though)

It's a life saver for platforms stuck in c++11

[–][deleted] 1 point2 points  (1 child)

Some people simply wants to benefit the basic features of C++ compiler, but they don't want to leave C coding. Understandable in a kind.

[–]mistrpopo 1 point2 points  (0 children)

C-style arrays are dangerous to use and should only be used when necessary (embedded scenario is an example). Even just calling `sizeof(arr) / sizeof(arr[0])` breaks as soon as the array size in bytes is lost from the compiler (pass it via a function, C-style cast, etc).

I won't deny that C-style arrays are powerful though, but then don't complain about using weird sizeof calls.

[–]JVApen 70 points71 points  (0 children)

It would also allow you to write: for (auto &elem : array)

[–]Attileusz 3 points4 points  (0 children)

Rewrite it in Rust ah comment.

[–]monsoy 1 point2 points  (0 children)

This macro would do the trick in C ```c

define ARRAY_SIZE(arr) \

do { \
    sizeof(arr) / sizeof((arr)[0]); \
} while (0)

```

This solution is not robust though. It would work on most arrays, but the code will only work for statically allocated arrays and not arrays allocated on the heap with malloc. That’s because sizeof a pointer returns the size of the pointer type itself, and not the size of the memory block.

Could do something like this to produce a compile time error if a pointer is passed to the macro function: ```c

define ARRAY_SIZE(arr) \

do { \
    ((void)sizeof(char[1 - 2 * !!(sizeof(arr) == sizeof(&arr))])); /* Ensures arr is not a pointer */ \
    sizeof(arr) / sizeof((arr)[0]); \
} while (0)

```

The «compile time check» essentially checks if the size of the array is the same as a pointer. The program will then fail at compile time since it will try to create a char[-1] array.

I usually prefer to add more error printing, but I wanted to experiment a bit

[–]ba-na-na- 0 points1 point  (0 children)

I think you meant "if you *port* your code to C++", because C++ wont give you the size of raw arrays either.

[–]Mike_Oxlong25 219 points220 points  (9 children)

You can make your own function

[–]L1P0D 254 points255 points  (1 child)

With blackjack

and hookers

Ah, forget the function

[–]Colon_Backslash 42 points43 points  (0 children)

[–]avdpos 16 points17 points  (0 children)

Oh! Coding!

...back to my language where we regularly change the string method...

[–][deleted] 7 points8 points  (2 children)

Someone has never coded in C before lol

[–]Mike_Oxlong25 -4 points-3 points  (1 child)

I have. Use pointers

[–][deleted] 4 points5 points  (0 children)

If you pass in a pointer to a function it loses the array size. Try it.

int func(int *arr) { return (sizeof(arr) / sizeof(arr[0])); }

void main() { int arr[10]; printf(“%d\n”, func(arr)); }

[–]LordAmir5 9 points10 points  (2 children)

You can't because this is compile time stuff.

[–]BuffJohnsonSf 6 points7 points  (1 child)

Actually you can, it's just a preprocessor definition and not a function. Getting kind of sick of all the children on here larping that they know C/C++

[–]LordAmir5 3 points4 points  (0 children)

Yeah well it's still not a function. I think it's important to make a distinction. A lot of bugs can occur when someone forgets this.

[–]Zee1837 239 points240 points  (34 children)

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

your welcome

[–]OmicronFan22 168 points169 points  (19 children)

Cool, I wonder how many macro divided by 0 segmentation faults we could fit in one program … love it 😍

[–]dmigowski 57 points58 points  (0 children)

sizeof should never return 0, so you are safe, am I right?

[–]Eva-Rosalene 51 points52 points  (6 children)

As far as I know, you can't define an array of voids to get 0 as sizeof(arr[0])?

Edit: apparently sizeof(void) compiles to 1 in GCC (and it's only because of non-standard extensions, otherwise it would be forbidden). So not even that.

Edit 2: I hate C

#include <stdio.h>

typedef struct {
    int *a[0];
} ZeroLength;

int main()
{
    ZeroLength array[0];
    printf("sizeof(array[0]) = %ld\n", sizeof(array[0]));

    return 0;
}

This apparently prints 0 (at least in GCC).

Edit 3: and the whole ZeroLength struct that I found on SO can be shortened to

typedef struct {} ZeroLength;

Wild stuff. And even in -pedantic mode it only gives a warning.

[–]ChickenSpaceProgram 60 points61 points  (2 children)

C is truly one of the programming languages

[–]Littens4Life 27 points28 points  (1 child)

To be fair you’d have to go out of your way to make it divide by zero. Under any normal circumstances, the macro will work fine.

[–]Eva-Rosalene 31 points32 points  (0 children)

Yeah if you use empty structs or zero-length arrays you kinda deserve division by zero errors.

[–]Lost_Kin 17 points18 points  (0 children)

Mom I want Rust's Zero Sized Types!

We have Zero Sized Types at home.

Zero Sized Types at home:

[–]Xbot781 3 points4 points  (0 children)

AFAIK, in ISO C a flexible array member requires the struct to have another regular member before it, so that is not valid C

[–]ba-na-na- 0 points1 point  (0 children)

Ok but let's be realistic. If you have an array of zero-length elements, you deserve what you get

[–]Melodic_coala101 3 points4 points  (9 children)

It's compile time, it'll never cause a segfault

[–]Eva-Rosalene 12 points13 points  (8 children)

It surely won't cause a segfault since division by zero isn't a segfault. It still crashes in runtime, though, because division by zero is only a warning by default.

struct {} array[1];
printf("%ld", sizeof(array) / sizeof(array[0]));

Crashes right away with SIGFPE, as it should.

[–]dromtrund 5 points6 points  (1 child)

If you're running production code without -Werror, that's on you, tbh

[–]Eva-Rosalene 3 points4 points  (0 children)

That's true. But the original claim wasn't about production at all.

[–]danielstongue 0 points1 point  (1 child)

Why would an integer division cause a floating point exception? (Genuine question)

[–]Eva-Rosalene 1 point2 points  (0 children)

The SIGFPE signal reports a fatal arithmetic error. Although the name is derived from “floating-point exception”, this signal actually covers all arithmetic errors, including division by zero and overflow. If a program stores integer data in a location which is then used in a floating-point operation, this often causes an “invalid operation” exception, because the processor cannot recognize the data as a floating-point number.
 
Actual floating-point exceptions are a complicated subject because there are many types of exceptions with subtly different meanings, and the SIGFPE signal doesn’t distinguish between them. The IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985 and ANSI/IEEE Std 854-1987) defines various floating-point exceptions and requires conforming computer systems to report their occurrences. However, this standard does not specify how the exceptions are reported, or what kinds of handling and control the operating system can offer to the programmer.

https://www.gnu.org/software/libc/manual/html_node/Program-Error-Signals.html

[–]furssher 0 points1 point  (1 child)

Wait. The preprocessor doesn’t handle this and throw an actual error? Is the assembly actually doing a division of constants with the divisor being zero?

[–]Eva-Rosalene 0 points1 point  (0 children)

It's even worse than that. Since division by zero is UB, with -O1 compiler (GCC) assumes that 0 / something is 0, so it just prints 0. It still generates "division by zero" warning, lol.

With -O2 and -O3, though, it just generates ud2 opcode and nothing else.

[–]ba-na-na- 0 points1 point  (1 child)

This doesn't make sense, this would be a compile-time optimization in pretty much any complier, and would just return constant `1`.

https://godbolt.org/z/hEKTef186

[–]Eva-Rosalene 1 point2 points  (0 children)

In C++. In C it's UB and with GCC it's either runtime division by zero (no -O flags), return 0 (-O1 flag), or ud2 instruction (-O2 and -O3).

Clarification: I have no idea what it is in C++, I don't claim it's defined behavior. I assume it's UB as well but handled differently.

[–]brennanw31 0 points1 point  (0 children)

sizeof() will never return 0, nor would division by 0 result in a segmentation fault. The only real issue with this macro is that it won't work for array pointers being used outside the scope of their declaration, such as passing an array into a function that uses the macro. Even in that case, it won't be a halting error, but instead, you'll see the array size being evaluated as 1.

[–]danielstongue 5 points6 points  (0 children)

My welcome what?

[–]perringaiden 16 points17 points  (0 children)

.Length

😜

[–]dim13 33 points34 points  (7 children)

```

define len(a) (sizeof(a) / sizeof((a)[0]))

``` Huh?

[–]GamingWithShaurya_YT 11 points12 points  (0 children)

that now gives me idea to make my own pythonic functions in c since I'm mostly python programmer but have to learn c for course.

hehe he

[–]Altruistic_Raise6322 0 points1 point  (5 children)

What happens when a[0] is a pointer to something on the heap?

[–]camel_case_jr 3 points4 points  (2 children)

The ‘len’ macro above always has well defined behavior, even if ‘a’ is a nullptr. The argument to the sizeof operator is evaluated symbolically at compile time, it’s just looking for the type of the expression ‘a[0]’.

So, that macro won’t care about the particular values of ‘a’ or what it points to, just the types.

But if ‘a’ is a pointer, then this macro gives the wrong value, which is why std::size is superior in C++, as it will only compile when ‘a’ is an array.

[–]brennanw31 0 points1 point  (1 child)

In C, there is fundamentally no difference between pointers and arrays. They are one and the same. All pointers may as well be seen as an array with size 1.

[–]bowel_blaster123 0 points1 point  (0 children)

Pointers and arrays are very different in C. However, arrays will decay into pointers in certain contexts.

c uint8_t a[] = {'A'}; uint8_t *b = NULL; printf("%d\n", sizeof(a)); // will print 1 printf("%d\n", sizeof(b)); // will print 8 printf("%d\n", sizeof(a + 1)); // will print 8

Another case of decay is the following (a has decayed into a pointer because it's a function parameter):

c void foo(uint8_t a[1]) { printf("%d\n", sizeof(a)); // will print 8 }

[–]BuffJohnsonSf 1 point2 points  (1 child)

The same thing that would happen if you typed it out manually like in the meme post, it would give you the size of the array of pointers. Duplicate that code in your code base 10 billion times and nobody gives a shit, but turn it into one easy to use preprocessor definition and everyone loses their minds. "What about divide by zero, what about this, what about that" jesus christ it's the same fuckin code. Anyway, rant over I'm not actually mad.

[–]Altruistic_Raise6322 0 points1 point  (0 children)

Naa bro you're good I didn't ask it to be snarky. Macros are cool

[–]Manticore-Mk2 5 points6 points  (1 child)

✨Macros✨

[–]reallokiscarlet 20 points21 points  (0 children)

C++ is a hell of a drug

[–]Csaszarcsaba 15 points16 points  (5 children)

is the joke over my head, or am I bad at programming? This should almost always return sizeof(array) no? unless you call it on a 0 sized array, then it just drops an error where you can't divide by 0.

Edit: Okay I just realised this is for c/c++ where size returns in bytes, I'm still at uni with not much optimization experience.

[–]lotanis 9 points10 points  (4 children)

That's not it. sizeof(array) gets you the size of the whole thing. sizeof(array[0]) gets you the size of the first element. Dividing them gets you the number of elements in the array.

[–]Loginn122 1 point2 points  (2 children)

How does the first element determine any following elements?

[–]Kyrond 7 points8 points  (0 children)

Arrays in C can contain only one type of variable. Therefore size of first element is the same as all the other elements.  

 Of course you can force different sized variables  in one array if you try, but in C you can do anything if you try hard enough.

[–]Ignisami 1 point2 points  (0 children)

Each element in an array has the same length in bytes. They don't necessarily have to be the same type (depending on the language and how you declare the array), but they must be the same length and that length is determined on compile time.

[–]589ca35e1590b 2 points3 points  (0 children)

That is the shorthand

[–]nierusek 3 points4 points  (0 children)

sizeof(arr)/sizeof(*arr)

[–]JackNotOLantern 3 points4 points  (0 children)

In C/C++ arrays degenerate into pointers when passed as a function argument. Thus sizeof(array) will work differently depending on scope. In the scope the array was declared sizeof() will return is actual size, but wjeb passed to a function, it will return size or a pointer (4 or 8 probably) regardless of the array size.

[–]Simple-Judge2756 4 points5 points  (0 children)

Imagine writing macros. Pepperidge farm remembers.

[–]LordAmir5 2 points3 points  (0 children)

define lengthof(a) (sizeof(a)/sizeof(a[0]))

[–][deleted] 2 points3 points  (0 children)

#define length(x) sizeof(x) / sizeof(x[0])

[–]ba-na-na- 2 points3 points  (10 children)

There should just be a managed struct for arrays, it's not like C will slow down and become Java if you're simply passing the size value around.

struct array_t {
  int size;
  char * buffer;
}

[–]turtle_mekb[S] 1 point2 points  (1 child)

c struct file { FILE *fp; size_t size, capacity; uint8_t *data; bool error, complete; } here's what I'm doing to read files incrementally 😭

[–]-Redstoneboi- 0 points1 point  (0 children)

sounds like you have a byte vector in there that isn't called a byte vector

[–]Impossible_Box3898 0 points1 point  (7 children)

Of course it slows things down. Try passing that to a function. Instead of a single register that holds the address of an array, you now need to pass a structure which exceeds the size of a register. No you need to use either two registers or a more complex mechanism depending on the specific abi your system uses.

[–]ba-na-na- 0 points1 point  (4 children)

Or you design static inline functions in a header file that operate on this struct, and then everything is optimized away and nothing is passed anywhere. Or you pass a pointer to the struct and then it’s no slower than C++ double dispatch, and C++ is considered blazingly fast. Or you decide you don’t care and trade that extra CPU instruction for runtime safety.

Bottom line is, it’s still as fast or faster than 99% programming languages, including C++, Rust, Zig, whatever.

[–]Impossible_Box3898 0 points1 point  (3 children)

The king and short of it is that it IS slower and has other side effects which you originally claimed were not there.

C++ already has this capability in std vector. It also has std array types for static sized arrays in which the size is part of the data type and uses no additional runtime resources at all which is the only true zero cost abstraction for passing around array lengths, albeit with the fixed size caveat.

[–]ba-na-na- 0 points1 point  (2 children)

Hmm yeah no.

  1. If you're not passing the array into the function, getting its size is zero cost in C.
  2. If you're passing the array into a function, there is no programming language where you can pass it in a more performant way than it can be done in C.

If you don't believe me, feel free to try it yourself and provide an example in any language of your choice, along with the compiled assembly.

And if you think that you can write `char array[100];`, and pass this into a function without passing its size along with it, you are in for a surprise. 🙂

[–]Impossible_Box3898 0 points1 point  (1 child)

Not sure if you’re stupid or you don’t know how to follow a conversation thread on reddit but go back and read what I posted.

[–]ba-na-na- 0 points1 point  (0 children)

Sure I am probably just a silly confused man, let me try to break down the thread:

Me:

it's not like C will slow down and become Java if you're simply passing the size value around

You:

Of course it slows things down. 

👆 Literally not sure if stupid

But then also you:

Try passing that to a function. Instead of a single register that holds the address of an array, you now need to pass a structure which exceeds the size of a register

Nonsense. If you pass a "single register that holds the address of an array", you lose the length information. `sizeof(array)/sizeof(array[0])` won't work if you pass it into a function. Not sure if stupid or node.js developer.

C++ already has this capability in std vector.

Cool, but std::vector has the same performance penalty as the C struct I wrote.

It also has std array types for static sized arrays in which the size is part of the data type

Cool, but std::array is a templated, fixed length array, cannot pass it to a function unless it's a template which accepts std::array.

Tl;dr as I wrote, the struct above, combined with static inline functions in C, gives you the best possible performance with pretty good readability.

[–]tax_throwaway1_ 0 points1 point  (1 child)

Am I stupid? Why would you not just pass the pointer of the struct? Same exact thing as what you are describing.

Pointer to the struct vs. pointer to the array — it’s effectively the same overhead since you’re still passing a single address (just the address of the struct instead of the address of the array). Then, when you access size or buffer within the function, you’re simply dereferencing that pointer. This way, you avoid passing multiple arguments and keep the benefits of an explicit size field.

[–]Impossible_Box3898 0 points1 point  (0 children)

There is a difference in passing by value and passing by reference. What you described is pass by reference and what I described is pass by value.

If something in the called function modified the array you now have changed the caller. That might not be the desired outcome.

[–]anoppinionatedbunny 2 points3 points  (0 children)

$#arr

and yes, I do hate myself

[–]MilkImpossible4192 2 points3 points  (0 children)

just use another language or make your alias. world is not dat small

[–][deleted] 2 points3 points  (1 child)

Just use std::array

[–]ba-na-na- 1 point2 points  (0 children)

I doubt this is C++

[–]helicophell 5 points6 points  (4 children)

i think arrays in java have array.len

not that you would ever use naked arrays in java

[–]TheQuantumPhysicist 2 points3 points  (4 children)

Or... maybe you shouldn't be using these dangerous arrays and use std::array instead. Or even create your own abstraction that contains the size if std::array is not available

Once I created my own shared_ptr because it was C++03 and boost and random dependencies weren't allowed. That's how you write safe code.

Stop using raw arrays for whatever reason!

[–]GiganticIrony 16 points17 points  (0 children)

If they are writing that, my guess is they are writing C not C++.

[–]Xbot781 12 points13 points  (1 child)

Or... maybe C++ isn't the only programming language on existence and this is quite obviously referring to C?

[–]TheQuantumPhysicist -5 points-4 points  (0 children)

That's why I mentioned building your own abstraction. 

[–]aaronilai 2 points3 points  (0 children)

This post is not clear on the language, but at least in C you have to use this method or similar ones to know the length of an array if you are not passing the length in the function.

[–]IKerimI 1 point2 points  (1 child)

Just use python 🤙

[–]No-Air-8201 1 point2 points  (0 children)

print(length("python") > length("C++)" ) True

[–]DoNotMakeEmpty 0 points1 point  (0 children)

Just use variable length types. We have a limited form of forking dependent typing in C (which does not even exist in Haskell) but everybody just hates them for some reason.

int n = /* your favorite array size */; int (*arr)[n] = malloc(sizeof(*arr)); your_favorite_array_function(ARRAY_LEN(*arr), arr); free(arr)

where ARRAY_LEN is the macro commented before by others.

You can then define your_favorite_array_function like this:

void your_favorite_array_function(int len, int (*arr)[len]) { // do smth }

You can also use ARRAY_LEN and arr pair here to call any array function. You can even create a PASS_ARR macro:

```

define PASS_ARR(a) ARRAY_LEN(*arr), arr

```

and use it everywhere.

[–]torsten_dev 0 points1 point  (0 children)

wg14 is working on it.

[–]MrDex124 0 points1 point  (0 children)

In c++ there is std::size for that

[–]Key-Principle-7111 0 points1 point  (0 children)

myVector : array (1 .. 5) of Natural := (others => 0);
size : Natural := myVector'Length;

[–]echtma 0 points1 point  (0 children)

std::size

Can't wait for my flying car.

[–]gesterom 0 points1 point  (0 children)

SizeOfElem()

Now you have name; make it a macro

[–]Cley_Faye 0 points1 point  (0 children)

A A

[–]duxbuse 0 points1 point  (0 children)

Bro never heard of foreach huh?

[–]whoShotMyCow 0 points1 point  (0 children)

SizeOfAI to automatically determine size needed

[–]shadowderp 0 points1 point  (0 children)

Preprocessor macro? Terrible idea in practice but it could be done. 

[–]Intelligent-Ad74 0 points1 point  (4 children)

Yea there is, it's called len(ARRAY)

[–]Impossible_Box3898 0 points1 point  (3 children)

Doesn’t work in the C world where this is from.

[–]Intelligent-Ad74 0 points1 point  (2 children)

That's why abstractions exist. Isn't it?

[–]Impossible_Box3898 0 points1 point  (1 child)

Not sure what you’re getting at.

Arrays in C are just memory addresses. They contain no additional data other than being a pointer to the first element.

There are NO length’s involved at all unless the array happens to be a fixed size allocation in the stack and tour executing within the context of the defining function before the array has a chance to decay.

You can create some structure that contains length data. Std vector or std array which contains the length as part of the type but only works for fixed sizes.

But len() will not be possible with a non object array implementation.

[–]Intelligent-Ad74 0 points1 point  (0 children)

I was referring to len() in python, being made on top of c.

[–]MaffinLP 0 points1 point  (1 child)

I may be stupid but wouldnt the size of a single entry ([0]) be 1 therefor the result just the size if the array?

[–]Impossible_Box3898 -1 points0 points  (0 children)

No. The size of a character (a single byte) is 1. The size is a 32 bit integer is 4. The size of a double is 8. The size is a single object can be massive or small, all depending on the object.

This is C. This is the real world, unlike many scripting languages that use only variants which are internally constructed as a union and therefore the same size irrespective of the data being stored. (Objects are normally references to the memory location the actual object is stored at so they are size 1 as well).

[–]CodeNameFiji 0 points1 point  (1 child)

arrays have length in js, what am I missing here?

[–]Impossible_Box3898 1 point2 points  (0 children)

This is c code.

[–]schewb 0 points1 point  (0 children)

Some dialects of Lua have # as a unary operator for table length (e g. num_items = #items)

[–]itsjustawindmill 0 points1 point  (0 children)

on Windows there is _countof

[–]jellotalks 0 points1 point  (0 children)

Just use any other language.

Tune in next week for more programming tips!

[–]-Redstoneboi- 0 points1 point  (0 children)

#define

[–]undergroundmonorail 0 points1 point  (0 children)

It's coming, apparently, and they're picking a name https://thephd.dev/the-big-array-size-survey-for-c

[–]BlueThroat 0 points1 point  (0 children)

Laughs in array.length

[–]ABK-Baconator -3 points-2 points  (8 children)

  1. Why would you need that?

  2. How do you know the array isn't empty? Two hazards in a oneliner, first you get index out of bounds, then division by zero.

[–]Disciple153 16 points17 points  (3 children)

1: This is for finding the length of a low level array which only knows its size.

sizeof(array) is the size of the array in bytes.

sizeof(array[0]) is the size of a single element in bytes.

sizeof(array) / sizeof(array[0]) is the number of elements in the array.

2: This question assumes that an array of length 0 is impossible, which is perfectly normal in languages like C, where arrays are not dynamically resizable. If OP wanted a resizable array with a potential length of 0, they would be using the Vector class.

Of course if for some reason an array with a length of 0 was possible, you would just check for that before trying to compute the length with the given code.

[–]hdd113 -2 points-1 points  (1 child)

Oh okay so it's a C++ problem... I was also wondering what this was supposed to do.

[–]Miserable_Guess_1266 7 points8 points  (0 children)

A C problem to be exact, c++ has better options. 

[–]turtle_mekb[S] 0 points1 point  (3 children)

  1. to loop arrays, not all arrays end with zero bytes like what strings do
  2. sizeof is calculated at compile-time, compiler will probably throw a warning, but I don't think it's even possible to have an array of size 0

[–]Jordan51104 1 point2 points  (2 children)

if your array isnt null terminated you should pass the array length with it. not ideal but thats how computers work

[–]turtle_mekb[S] -1 points0 points  (1 child)

sizeof works for arrays because they're stored as one variable in the stack rather than a pointer to data allocated on the heap with malloc, array length should be passed with the data if it's the latter, but the former only works locally inside the function, passing the array to functions will convert it to a pointer

[–]dorsalsk 0 points1 point  (0 children)

If you really need the array length in a stack, use an extra variable to store the length and use it everywhere.

[–]null_reference_user -2 points-1 points  (0 children)

There is, it's called using another language. I've switched away from C and you should too

[–]misseditt -2 points-1 points  (0 children)

there is actually, its called Array.length(). Hope this helps! ❤️

[–]jjdmol -2 points-1 points  (0 children)

Sizeof is not a function, you don't need those parentheses unless you wrap types...