im going to risk getting a beating, because this is something i should (used to?) know...

anyhoo, given a function, how do you tell the size of the array that is passed? obviously trying to find the sizeof the pointer doesn't work (it returns the size of the pointer, duh)

but im having a brainfart trying to remember how to find the size of the passed array...

void myFunction (char * myString) 
{
    size_t len = sizeof(myString) 
    // gives size of pointer, not string

}

assume the string being pointed to is properly declared and of a significant length.

.

Recommended Answers

All 23 Replies

>given a function, how do you tell the size of the array that is passed?
Given a function where the only parameter is a pointer to the first element of said array, you don't. There's no portable method, which is why the usual advice is a second parameter with the size:

void myfunction(char * pointerToString, size_t size)

er. i was hoping that wasnt the only answer.

oh, well, it's not a big deal. i just thoguht there was some clever trick that i had forgotten.

okay wait, even though this thread is solved, if it's a string couldn't you use strlen? Or just int length = 0; while(length++,*myString++); ?

Good point. I was assuming jephthah wanted the capacity of an array, but that might have been an unwarranted assumption.

no, i dont want a length of some arbitrary string, that may or may not be null-terminated

Narue was right: i wanted the size of the entire array.

alright, just throwing it out there

s'cool. thanks :)

you can do also

void get_size(char *buffer,int size)
{
       fgets(buffer,size,stdin);
}
int main(void)
{
       char buffer[100];
       get_size(buffer,sizeof buffer);
}
commented: LOL, guy. +9

lolguy> you can do also
Did you read post number two before?
Did you notice that the thread is marked as solved? Which unless you are sure something has been overlooked, you should learn to leave alone.

>you can do also
You say "also", but that's identical to the solution I mentioned. :icon_rolleyes:

lolguy> you can do also
Did you read post number two before?
Did you notice that the thread is marked as solved? Which unless you are sure something has been overlooked, you should learn to leave alone.

Clearly he has duplicated Narue's answer,
however, I don't agree with your second point...
I see no problem with contributing something to a solved thread, especially if there's more than one way to do it. If the OP doesn't need any other way to do it, that's fine, alternative answers can be a benefit to other readers of a thread. I often click on solved links to read about a problem and its solutions to learn something about it--and it makes it all the more beneficial if there are lots of different fixes to it. I don't stop reading after the first acceptable answer, so why stop posting solutions after the first?

I agree to winrawr at post # 12:

I see no problem with contributing something to a solved thread, especially if there's more than one way to do it. If the OP doesn't need any other way to do it, that's fine, alternative answers can be a benefit to other readers of a thread. I often click on solved links to read about a problem and its solutions to learn something about it--and it makes it all the more beneficial if there are lots of different fixes to it. I don't stop reading after the first acceptable answer, so why stop posting solutions after the first?

But, if
this "iterating" posts have really been normed as discouraged
(I know it's in the rules), so be it. I would rather keep quiet in
order to help people in need rather than to be kicked out and
could not help other people anymore...

I'm sorry for this pathetic post,

winrawr> I see no problem with contributing something to a solved thread,[...]
"contributing something" is the key that you are overlooking concerning my comment.

Ok, let's just calm down...We are not here to argue...
We are here, as a member, to help those who have
problems...

neigyl_noval> Ok, let's just calm down...We are not here to argue...

:-/ :?: :icon_rolleyes: :yawn:

We are not here to argue...
We are here, as a member, to help those who have
problems...

speak for yourself.

i'm here for the smackdown.

>i'm here for the smackdown.
If you come for the smackdown, don't be surprised when you get smacked.

Back to the topic. I have another solution.

The capacity of the array must be known to the function. If the capacity is not hardcoded or saved in a global variable, you need to pass it to the function. Narue proposed to pass it in a second parameter.

Another solution is to make a bundle of the array and its capacity. A cheap, dirty trick is misusing the first array element for it. For strings, the first byte is the string length (lengths from 0 to 255 are possible), for integer array, the first integer is the array length, etc. For non-char or non-integer array, a cast would be neccessary. But this is very dirty and dangerous. Pascal-type strings do this implicitly, which is fine because Pascal hides this trick.

A third solution is to create a struct both of capacity and an array of length 1 (or 0 with gcc).

struct example {
  unsigned int len;
  char string[1];
}

Allocate dynamically with malloc(sizeof(struct example) + (len - 1) * sizeof(char)) (not tested). Drop -1 if using string[0].

This works, because C does not check the array bounds. When we say string[2] , the C compiler won't report errors, and because we allocated memory for it, it will work.

>Another solution is to make a bundle of the array and its capacity.
Let's consider some of the decisions you have to make:

  • Type (generic or non-generic): If you want a generic array, you have a problem because C doesn't support parametric types. You have to hack your way around it using pointers to void, or nasty preprocessor tricks. The former is unsafe, the latter is insanity.
  • Memory (dynamic or non-dynamic): If you want to use a real array, you have to figure out how to generate the size of the array without restricting your flexibility of the bundle. Naturally, the bundle itself would be a structure, and for structures to be used across functions, they need to be defined at file scope. If you want to simulate an array using dynamic memory, you need to consider the performance hit of allocation and release.

A reasonable implementation using generic pointers and dynamic memory might look like this:

#include <stdio.h>
#include <string.h>

struct array {
    size_t size;
    void *data;
};

void foo ( struct array *a )
{
    memset ( a->data, 'A', a->size );
}

int main ( void )
{
    struct array a = {10};

    a.data = calloc ( a.size + 1, 1 );
    foo ( &a );
    puts ( a.data );
    free ( a.data );

    return 0;
}

That doesn't really buy you anything over passing the size as a second argument. In fact, it's worse because now you have to deal with an almost-but-not-quite abstraction.

>A cheap, dirty trick is misusing the first array element for it.
Or multiple elements depending on the size. The problem here is that you need to skip the size when looking for actual data. One option is to take a slice of the array and then use a negative index to find the size. This is actually a decent solution. Decent enough that it's a common string implementation, so I wouldn't call it a dirty trick. It is tedious though, enough that I'd say it's more effort than necessary if your only goal is to avoid a second parameter for the size.

It's also tricky when you want to create a generic solution for all array types and sizes.

>A third solution is to create a struct both of capacity
>and an array of length 1 (or 0 with gcc).

This is called the "struct hack", and it's officially undefined in the C89 standard. The C99 standard blesses it with an explicit feature which is only slightly different than the traditional hack. However, it's generally perceived to be a poor practice.

commented: interesting +9

Interesting. I didn't know that the struct hack is undefined in C89 and defined in C90 (omit the capacity).

What's the difference?

>I didn't know that the struct hack is undefined in C89 and defined in C90 (omit the capacity).
It's undefined until C99. C89 and C90 are pretty much the same standard with slightly different wording here and there.

>What's the difference?
Wording. In C89 (and C90, and C95), there wasn't any special handling for an array as the last member of a structure. As such, even if you allocate extra memory to the structure instance, you're still bound by the rules when it comes to accessing the array member. In your example, when you say instance.string[2], it invokes undefined behavior because you're accessing the array out of bounds. C99 changes the wording such that if you use the correct syntax, you no longer invoke undefined behavior on the array access.

I mistyped. I meant C99. :-/

Thanks for the clarification about the wording. Seems that there are lawyers in the committees.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.