-2
void myfunc(char* passedArray)
{
    cout << sizeof(passedArray) << endl; // prints 4
}

int main(void)
{
    char charArray[] = "abcdefghiklmop";

    cout << sizeof(charArray) << endl; // prints 15
    myfunc(charArray);
    cout << sizeof(charArray) << endl; // prints 15
}

I believe it should still print 15 inside that function...

LihO
  • 41,190
  • 11
  • 99
  • 167
Nick Pickering
  • 3,095
  • 3
  • 29
  • 50
  • 2
    this has been asked sooo many times. Have you even tried googling it? – Dariusz Feb 18 '13 at 10:04
  • YES, thoroughly. It isn't on SO, and I couldn't find it on any forum. – Nick Pickering Feb 18 '13 at 10:05
  • you passed in a pointer for a parameter and `sizeof(char*)==4` holds for your platform by chance. There is basically no way to determine the length of the array from a pointer to the first element. – phoeagon Feb 18 '13 at 10:06
  • 1
    Then not only this question is a fail, your googling skills seem lacking too. stackoverflow.com/questions/4941142/c-sizeof-string-is-always-8/ http://stackoverflow.com/questions/1392200/sizeof-string-literal/1392228#1392228 http://stackoverflow.com/questions/11919369/why-sizeofa-pointer-returns-incorrect-value http://stackoverflow.com/questions/1392200/sizeof-string-literal – Dariusz Feb 18 '13 at 10:07
  • I recommend that next time anyone posts with `c++` `array` `sizeof` related topic, show this list of posts before they get to click "post". – phoeagon Feb 18 '13 at 10:13
  • @phoeagon, you mean like the list of possible duplicates that is already displayed when you type in a question!? – StoryTeller - Unslander Monica Feb 18 '13 at 10:15
  • NONE of those questions answered my question concisely, but sorry if I've offended the SO crowd. New to C/++ and had no reason to expect it would be converted to a pointer. – Nick Pickering Feb 18 '13 at 10:18
  • @storyteller Yeah, but for this particular question (and some others that have been asked sooooooo many times), make the author click on at least one of the link or use some other means of extra notification... – phoeagon Feb 18 '13 at 10:18
  • I checked the similar answers, folks. They didn't answer my question. – Nick Pickering Feb 18 '13 at 10:20

7 Answers7

9

This is a classic problem with pointers and arrays. The issue is that arrays decay to pointers, as you can see. Pointer types hold no metadata about the data it points to except for the size of the pointed to type. All other metadata, such as array length is lost.

The issue therefore is that you have called myfunc with a pointer to the array; all metadata about the array is then invisible to the myfunc function. This then triggers a subtle difference in the sizeof operator, which is that when it is applied to a pointer, it gives the size of the pointer type, not the length of the array. When applied to an array however, it gives the length of the array, as you can see in the main function.

Short fix, use strlen instead.

slugonamission
  • 9,562
  • 1
  • 34
  • 41
  • All this is a nice explination of a different issue. He _has_ declared _passedArray_ as a pointer, so there's no issue of decay at the point where he's using `sizeof`. And the solution is not to use `strlen`, but `std::string`. – James Kanze Feb 18 '13 at 10:14
  • No, it's the same issue because he's calling `sizeof` on a pointer, I'm just trying to articulate why this is the issue. My solution of "use `strlen` instead" comes simply from my pure C background, so yes, `std::string` is another valid fix. The issue of decay still appears when he is implicitly converting an array to a pointer when calling the function. – slugonamission Feb 18 '13 at 10:16
  • Exactly. He's using `sizeof` on an object which is declared and defined as a pointer. There's no issue of decay surrounding the `sizeof`. (If he were asking how he could pass an array to a function declared to take a pointer, or if he'd declared `myfunc` to take an array, your answer would be appropriate.) – James Kanze Feb 18 '13 at 10:24
  • @JamesKanze Fair enough, I take your point there. I see this a lot though when people are learning C, they expect `sizeof` to be a run-time function which gives the size of whatever they throw at it, including the length of arrays. Typically, it's because they don't realise the actual differences between pointers and arrays properly. I was just trying to give an explanation that showed he was passing said array as a pointer, and the effects of doing so while also trying to articulate that `sizeof(ptr)` returns the size of the pointer, not the array as he expected. – slugonamission Feb 18 '13 at 10:28
  • I also appreciate that is looks flaming obvious when you look over the code, but new programmers *do* end up getting locked in a loop that sizeof in a foreign function on a passed array will do exactly the same as expected when called on the array. Sometimes it just takes the extra kick for the "oh...yeah." moment. – slugonamission Feb 18 '13 at 10:30
  • I appreciate the fact that new programmers get confused, especially because there seem to be sites that claim that pointers and arrays are the same thing. And he does seem to suffer a little from this. But in that case, you should probably start out by insisting on the fact that they are different. (And that you cannot pass an array to a function, and ... You could end up with a book. That's why I alway say: just use `std::string`.) – James Kanze Feb 18 '13 at 10:58
  • That's a good point, looking back I should have made the clear distinction within `myfunc`, the array had decayed to a pointer and was a completely different type. It is basically what I was trying to articulate throughout though, and explain the difference between `sizeof` on a pointer and array. Finally, yeah, my pure C background tends to burn me on C++ questions like that :P – slugonamission Feb 18 '13 at 11:02
4

Although you defined your array as char charArray[], when you pass it to your function that takes char*, the charArray is being converted into the pointer to the first element, thus when you call sizeof in the body of your function, it prints the size of the pointer (which is 4 bytes on 32bit machines) as expected.

Even if your function took char passedArray[] as an argument, original charArray would be decayed into pointer to the first element and ability to retrieve the size of this array by calling sizeof would be lost. (see What is array decaying?).

So you can call strlen() to retrieve the size of this C-style string but since you are writing C++ code then the most reasonable solution is to use std::string instead of C-style strings.

Community
  • 1
  • 1
LihO
  • 41,190
  • 11
  • 99
  • 167
4

First, what do you expect? You've defined passedArray to be a pointer, so sizeof(passedArray) will return the size of a pointer on your machine. What else could it do? I could understand some confusion if your function was:

void myFunc( char passedArray[15] )

A reasonable person could expect sizeof(passedArray) to be 15 in this case (but he'd be wrong, because when used as a parameter, and array is converted by the compiler into a pointer, and this definition is exactly the same as yours).

The answer to all this is to use std::string:

void
myFunc( std::string const& passedValue )
{
    std::cout << passedValue.size() << std::endl;
}

Unlike char[], std::string actually works. C style arrays, whether used as strings or not, are broken, and should only be used in a very limited set of cases, mostly related to objects with static lifetime and order of initialization issues.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • relatively new to C/++, had no reason to expect it would be converted to a pointer. I'm debugging an old piece of code that was using sizeof() on a pointer expecting an array. – Nick Pickering Feb 18 '13 at 10:16
  • 1
    @NicholasPickering The function was defines `myFunc( char* )`. `char*` is a pointer. Period. There's no implicit conversion or anything involved in `myFunc`. (There's an implicit conversion at the call site, of course. But that's a different issue.) And regardless of how new you are to C++ (there's no such thing as C/C++), if you define a type `X`, why would you expect a type `Y`. (In fact, as I point out, there is one such case. But it doesn't occur in your program.) – James Kanze Feb 18 '13 at 10:21
  • I was implying I was new to both, not that the program is using both. I would expect that probably because I really only have experience in weakly typed languages. – Nick Pickering Feb 18 '13 at 10:26
2

Use strlen(), not sizeof(), to get the length of your string.

In C, a string is just a zero-terminated character array. There is no special String type in C. strlen() is a function which counts the number of characters until the terminating zero byte.

sizeof() is an operator which can be used to determine the size of a variable or of a datatype. In your case, sizeof() returns the size of the char* pointer (which seems to be 4 bytes on your platform).

Andreas Fester
  • 36,091
  • 7
  • 95
  • 123
  • then what does sizeof() do? why does it differ from within main to within the function? – Nick Pickering Feb 18 '13 at 10:04
  • @NicholasPickering `sizeof` returns the size of the object which is its argument. You're argument has type `char*`, so it returns the size of a `char*`. It gives different results in `main` because you've applied it to a different object. – James Kanze Feb 18 '13 at 10:15
  • He's marked the posting C++, and is using `std::cout`, so what C does is more or less irrelevant. In C++, a string is a class type defined in the standard library, and until you're an expert, that's really all you should be using. – James Kanze Feb 18 '13 at 10:17
  • 1
    This code is old. I'm debugging it. The original developer used `sizeof`, when he should of used any of the other code you've all suggested. – Nick Pickering Feb 18 '13 at 10:22
1

Inside the function, this

cout << sizeof(passedArray) << endl;

is printing the size of a passedArray, which is achar*. A pointer is size 4 on your platform. If you pass a pointer to a function, the function has no way of knowing that it is pointing to the first element of a fixed size array. If you want the size of a fixed array, then pass an array, not a pointer:

template< class T, size_t N >
void myfunc( const T (&passedArray)[N] )
{
  std::cout << N << "\n";
}
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
1

sizeof(char*) gives the size of the pointer, not of the pointed-to string.

What you really want is strlen.

The reason why it gives the string size in main() is because it's defined as a char[] (an array which size is known at compile-time) not a char*.

syam
  • 14,701
  • 3
  • 41
  • 65
0

sizeof(passedArray) returns size of the pointer passedArray, which is of type char *, and in your system, apparently 4 bytes.

use strlen instead, or rather, use std::string

Hayri Uğur Koltuk
  • 2,970
  • 4
  • 31
  • 60