82

For a char [], I can easily get its length by:

char a[] = "aaaaa";
int length = sizeof(a)/sizeof(char); // length=6

However, I cannot do like this to get the length of a char * by:

char *a = new char[10];
int length = sizeof(a)/sizeof(char);

because, I know, a here is a pointer, such that length here will be always be 4 (or something other in different systems).

My question is that how can I get the length of a char * afterwards? I know someone may challenge me that you already know its 10 because you just created it. I want to know this because this step of getting its length may come long long way from its creation and I don't want to come long long way back to check this number. Moreover, I also want to know its real length.

To be more specific

  • how can I get its real length=5?
  • how can I get its total length=10?

for the following example:

char *a = new char[10]; 
strcpy(a, "hello");
20
  • 15
    strlen? (....) Commented Jan 9, 2014 at 14:15
  • 4
    @KirilKirov that will not give the length of the array. Well, it will, but only in special circumstances. Commented Jan 9, 2014 at 14:18
  • 3
    This has been answered before, a pointer doesn't hold information about the size of the block of data it points to (if it points to an array), just its starting location in memory.
    – A Person
    Commented Jan 9, 2014 at 14:20
  • 6
    You may use std::vector<char>, so you have the size, and memory management is done for you
    – Jarod42
    Commented Jan 9, 2014 at 14:22
  • 2
    Could you please decide which language you're asking about? If it's C, then you can't use new; if it's C++, then you should use higher-level abstractions like vector to solve this problem. Commented Jan 9, 2014 at 14:32

16 Answers 16

75

You can't. Not with 100% accuracy, anyway. The pointer has no length/size but its own. All it does is point to a particular place in memory that holds a char. If that char is part of a string, then you can use strlen to determine what chars follow the one currently being pointed to, but that doesn't mean the array in your case is that big.
Basically:

A pointer is not an array, so it doesn't need to know what the size of the array is. A pointer can point to a single value, so a pointer can exist without there even being an array. It doesn't even care where the memory it points to is situated (Read only, heap or stack... doesn't matter). A pointer doesn't have a length other than itself. A pointer just is...
Consider this:

char beep = '\a';
void alert_user(const char *msg, char *signal); //for some reason
alert_user("Hear my super-awsome noise!", &beep); //passing pointer to single char!

void alert_user(const char *msg, char *signal)
{
    printf("%s%c\n", msg, *signal);
}

A pointer can be a single char, as well as the beginning, end or middle of an array...
Think of chars as structs. You sometimes allocate a single struct on the heap. That, too, creates a pointer without an array.

Using only a pointer, to determine how big an array it is pointing to is impossible. The closest you can get to it is using calloc and counting the number of consecutive \0 chars you can find through the pointer. Of course, that doesn't work once you've assigned/reassigned stuff to that array's keys and it also fails if the memory just outside of the array happens to hold \0, too. So using this method is unreliable, dangerous and just generally silly. Don't. Do. It.

Another analogy:
Think of a pointer as a road sign, it points to Town X. The sign doesn't know what that town looks like, and it doesn't know or care (or can care) who lives there. It's job is to tell you where to find Town X. It can only tell you how far that town is, but not how big it is. That information is deemed irrelevant for road-signs. That's something that you can only find out by looking at the town itself, not at the road-signs that are pointing you in its direction

So, using a pointer the only thing you can do is:

char a_str[] = "hello";//{h,e,l,l,o,\0}
char *arr_ptr = &a_str[0];
printf("Get length of string -> %d\n", strlen(arr_ptr));

But this, of course, only works if the array/string is \0-terminated.

As an aside:

int length = sizeof(a)/sizeof(char);//sizeof char is guaranteed 1, so sizeof(a) is enough

is actually assigning size_t (the return type of sizeof) to an int, best write:

size_t length = sizeof(a)/sizeof(*a);//best use ptr's type -> good habit

Since size_t is an unsigned type, if sizeof returns bigger values, the value of length might be something you didn't expect...

4
  • @herohuyongtao: using a pointer, you can't get the max-length. in your snippet new char[10] allocates 10 chars, and assigns the pointer to a. You can use strlen(a) after strcpy, and it'll return 5, but getting the 10 is not possible, not unless you do something like char *a = calloc(10, sizeof *a);, then for(i=0;a[i] == '\0';++i); after that, i-1 could give you the total length of the memory allocated, if the memory right next to the allocated block doesn't accidentally hold \0, too, so this is dangerous and bad. But you're using C++: use std::string or std::vector Commented Jan 9, 2014 at 14:51
  • Just out of curiosity, isn't a[0]==0[a]==*a? Why would using sizeof (*a) be a better habit than using sizeof (a[0])? Unless you meant that it's better than using sizeof(a) by itself...
    – A Person
    Commented Jan 9, 2014 at 16:40
  • @Siidheesh: Strictly speaking a[0] == 0[a] == *(a+0), but the main reason for using sizeof *a is when using other types than char, or usign pointers to pointers in custom allocators. consider void my_alloc(void **ptr, size_t size) { (*ptr) = malloc(size*sizeof(*(*ptr)));} this will work when allocating structs, ints, chars... any type, whereas sizeof(type) requires your knowing the type. Commented Jan 9, 2014 at 16:54
  • @APerson: I did mean to say that using sizeof *a is better than using sizeof <type>, and a lot better than sizeof a (which is not always what you want). Personally, I also happen to prefer *a over a[0], simply because it makes it very clearl (IMHO) that a pointer is being dereferenced. When reviewing code, or hunting down the cause of a segfault, these lines that are my first port of call. When I see a[0], I might be assume (wrongly) that a is a local array variable, and not a NULL pointer Commented Dec 29, 2014 at 15:18
24

If the char * is 0-terminated, you can use strlen

Otherwise, there is no way to determine that information

8
  • 5
    strlen will not reliably give the length of the array. Commented Jan 9, 2014 at 14:19
  • 1
    @Olotiar Unless you're working with a specific compiler and locate where the data regarding allocated memory is stored (after all, in order for memory allocation to work properly, the amount of memory that was allocated for that specific location needs to be stored somewhere so it won't be overlapped by another allocation and so that free will work properly).
    – JAB
    Commented Jan 9, 2014 at 14:19
  • 8
    strlen does not count the '\0'.
    – Maroun
    Commented Jan 9, 2014 at 14:19
  • @JAB This is a good remark, though I don't know of any standard way to access that information.
    – Olotiar
    Commented Jan 9, 2014 at 14:21
  • @JAB That would still only work if it's dynamically allocated.
    – molbdnilo
    Commented Jan 9, 2014 at 14:40
7

There are only two ways:

  • If the memory pointer to by your char * represents a C string (that is, it contains characters that have a 0-byte to mark its end), you can use strlen(a).

  • Otherwise, you need to store the length somewhere. Actually, the pointer only points to one char. But we can treat it as if it points to the first element of an array. Since the "length" of that array isn't known you need to store that information somewhere.

4
  • In C++:

Just use std::vector<char> which keep the (dynamic) size for you. (Bonus, memory management for free).

Or std::array<char, 10> which keep the (static) size.

  • In pure C:

Create a structure to keep the info, something like:

typedef struct {
    char* ptr;
    int size;
} my_array;

my_array malloc_array(int size)
{
    my_array res;
    res.ptr = (char*) malloc(size);
    res.size = size;
    return res;
}

void free_array(my_array array)
{
    free(array.ptr);
}
4

So the thing with the sizeof operator is that it returns you the amount of storage needed, in bytes, to store the operand.

The amount of storage needed to store a char is always 1 byte. So the sizeof(char) will always return 1.

char a[] = "aaaaa";

int len1 = sizeof(a)/sizeof(char); // length = 6
int len2 = sizeof(a);              // length = 6;

This is the same for both len1 and len2 because this division of 1 does not influence the equation.

The reason why both len1 and len2 carry the value 6 has to do with the string termination char '\0'. Which is also a char which adds another char to the length. Therefore your length is going to be 6 instead of the 5 you were expecting.

char *a = new char[10];
int length = sizeof(a)/sizeof(char);

You already mentioned that the length turns out to be 4 here, which is correct. Again, the sizeof operator returns the storage amount for the operand and in your case it is a pointer a. A pointer requires 4 bytes of storage and therefore the length is 4 in this case. Since you probably compile it to a 32-bit binary. If you'd created a 64-bit binary the outcome would be 8.

This explanation might be here already be here. Just want to share my two cents.

3

Given just the pointer, you can't. You'll have to keep hold of the length you passed to new[] or, better, use std::vector to both keep track of the length, and release the memory when you've finished with it.

Note: this answer only addresses C++, not C.

4
  • Assuming he's only using C++. If the code needs to work as a C program as well, then std::vector will unfortunately not be much help.
    – JAB
    Commented Jan 9, 2014 at 14:22
  • 2
    @JAB: Oh yes, I just noticed the question is asking about two languages at once. I wish people would stop doing that. Commented Jan 9, 2014 at 14:23
  • 3
    If he's using new, he can't be using C. Commented Jan 9, 2014 at 14:27
  • @JohnDibling True, but the question was tagged with both C++ and C (though it is not anymore).
    – JAB
    Commented Jan 9, 2014 at 14:45
3

char *a = new char[10];

My question is that how can I get the length of a char *

It is very simply.:) It is enough to add only one statement

size_t N = 10;
char *a = new char[N];

Now you can get the size of the allocated array

std::cout << "The size is " << N << std::endl;

Many mentioned here C standard function std::strlen. But it does not return the actual size of a character array. It returns only the size of stored string literal.

The difference is the following. if to take your code snippet as an example

char a[] = "aaaaa";
int length = sizeof(a)/sizeof(char); // length=6

then std::strlen( a ) will return 5 instead of 6 as in your code.

So the conclusion is simple: if you need to dynamically allocate a character array consider usage of class std::string. It has methof size and its synonym length that allows to get the size of the array at any time.

For example

std::string s( "aaaaa" );

std::cout << s.length() << std::endl;

or

std::string s;
s.resize( 10 );

std::cout << s.length() << std::endl;
2

You can implement your own new and delete functions, as well as an additional get-size function:

#define CEIL_DIV(x,y) (((x)-1)/(y)+1)

void* my_new(int size)
{
    if (size > 0)
    {
        int* ptr = new int[1+CEIL_DIV(size,sizeof(int))];
        if (ptr)
        {
            ptr[0] = size;
            return ptr+1;
        }
    }
    return 0;
}

void my_delete(void* mem)
{
    int* ptr = (int*)mem-1;
    delete ptr;
}

int my_size(void* mem)
{
    int* ptr = (int*)mem-1;
    return ptr[0];
}

Alternatively, you can override the new and delete operators in a similar manner.

1
  • 2
    +1 for creativity, although I wouldn't recommend doing that in a real application. You'd also have to implement copy and resize. When using C++, there are better ways to solve the problem.
    – DarkDust
    Commented Jan 9, 2014 at 14:51
2

Ok, I know this is an ancient thread. According to my experiments, an assignment like:

char* str = "blah";

does indeed append a null character. This code:

char* str = "blah";
cout << str;
cout << strlen(str);

Outputs:

blah

4

It still works if I change the number of characters assigned. Since the assignment does seem to add a \0 at the end, I don't understand the above admonitions ("strlen only works if there's a nul char" etc.) Am I missing something?

2
  • 1
    String literals are null terminated automatically. See en.cppreference.com/w/cpp/language/string_literal
    – BuvinJ
    Commented Jun 6, 2023 at 12:59
  • 1
    That said, in my opinion, it's a truly terrible practice to write code passing around a char * with the assumption that it is definitely null terminated. If you want a "string", I think 99% of the time one is better off just using an std::string (or string type from some other library). You can pass them around just as well by reference, or pointer, to avoid needless copies (if that's a concern). The disadvantage of using some tiny amount of extra memory or processing with a wrapped object is generally negligible compared to the risk, or the pita, of using char * primitives.
    – BuvinJ
    Commented Jun 6, 2023 at 13:46
1

This may sound Evil™ and I haven't tested it, but how about initializing all values in an array at allocation to '\0' and then using strlen() ? This would give you your so-called real value since it would stop counting at the first '\0' it encounters.

Well, now that I think about it though, please don't Ever™ do this. Unless, you want to land in a pile of dirty memory.

Also, for the allocated memory or the total memory you may use the following functions if your environment provides them:

3
  • 1
    If you set all of the values of a char * array to '\0', then strlen() will return 0.
    – Bill Lynch
    Commented Jan 9, 2014 at 15:40
  • @sharth, that is indeed the real value he wants, since what you mentioned is only the case when the memory hasn't been used yet. Assuming he changes the elements by equalising them to real values he won't get 0 from a call to strlen() anymore.
    – Siddharth
    Commented Jan 9, 2014 at 16:04
  • This can lead to some problems when the char array contains binary informations (image pointer for instance) : the array can contains '\0' bytes in the data and in this case, the data length is greater than strlen(data). Commented Oct 21, 2020 at 11:15
0

You can make a back-tracker character, ex, you could append any special character say "%" to the end of your string and then check the occurrence of that character.
But this is a very risky way as that character can be in other places also in the char*

char* stringVar = new char[4] ; 
stringVar[0] = 'H' ; 
stringVar[1] = 'E' ; 
stringVar[2] = '$' ; // back-tracker character.
int i = 0 ;
while(1)
{
   if (stringVar[i] == '$')
     break ; 
   i++ ; 
}
//  i is the length of the string.
// you need to make sure, that there is no other $ in the char* 

Otherwise define a custom structure to keep track of length and allocate memory.

2
  • 2
    Ugh, that smells awfully! Null-terminate the string instead. It's a bad idea to use a character that might turn up in actual text (like, "You owe me $1 for that terrible idea" ;-)
    – DarkDust
    Commented Jan 9, 2014 at 14:24
  • @ps06756: still crashes stringVar = new char[10], and doesn't answer the OP question.
    – Jarod42
    Commented Jan 9, 2014 at 14:27
0

when new allocates an array, depending on the compiler (i use gnu c++), the word in front of the array contains information about the number of bytes allocated.

The test code:

#include <stdio.h>
#include <stdlib.h>

int
main ()
{
    int arraySz;
    char *a;
    unsigned int *q;

    for (arraySz = 5; arraySz <= 64; arraySz++) {

        printf ("%02d - ", arraySz);

        a = new char[arraySz];
        unsigned char *p = (unsigned char *) a;

        q = (unsigned int *) (a - 4);
        printf ("%02d\n", (*q));

        delete[] (a);

    }
}

on my machine dumps out:

05 - 19
06 - 19
07 - 19
08 - 19
09 - 19
10 - 19
11 - 19
12 - 19
13 - 27
14 - 27
15 - 27
16 - 27
17 - 27
18 - 27
19 - 27
20 - 27
21 - 35
22 - 35
23 - 35
24 - 35
25 - 35
26 - 35
27 - 35
28 - 35
29 - 43
30 - 43
31 - 43
32 - 43
33 - 43
34 - 43
35 - 43
36 - 43
37 - 51
38 - 51
39 - 51
40 - 51
41 - 51
42 - 51
43 - 51
44 - 51
45 - 59
46 - 59
47 - 59
48 - 59
49 - 59
50 - 59
51 - 59
52 - 59
53 - 67
54 - 67
55 - 67
56 - 67
57 - 67
58 - 67
59 - 67
60 - 67
61 - 75
62 - 75
63 - 75
64 - 75

I would not recommend this solution (vector is better), but if you are really desperate, you could find a relationship and be able to conclude the number of bytes allocated from the heap.

0

Legit question. I personally think people confuse pointers with arrays as a result of character pointers (char*), which serve almost the same purpose as character arrays (char __[X]). This means that pointers and arrays are not the same, so pointers of course don't contain a specific size, only an address if I could say so. But nonetheless you can try something similar to strlen.

int ssize(const char* s)
{
    for (int i = 0; ; i++)
        if (s[i] == 0)
            return i;

    return 0;
}
-1

You can find the length of a char* string like this:

char* mystring = "Hello World";
int length = sprintf(mystring, "%s", mystring);

sprintf() prints mystring onto itself, and returns the number of characters printed.

1
  • 1
    So it's exactly equivalent to strlen, and only works if the last character in the array is a NUL, and there are no NULs before that. Commented Feb 7, 2020 at 14:24
-2

You could try this:

int lengthChar(const char* chararray) {
   int n = 0;
   while(chararray[n] != '\0')
     n ++;
   return n;  
}
1
  • That's just (a poor implementation of) strlen(), with all its limitations (). Commented Feb 7, 2020 at 14:25
-4

Strlen command is working for me . You can try following code.

// char *s

unsigned int  strLength=strlen(s);
10
  • Depends on s.. Is it a C String?
    – Maroun
    Commented Jan 9, 2014 at 14:22
  • Only if you put a terminated string in the array; and then you'll get the length of the string, not the array. Commented Jan 9, 2014 at 14:22
  • I guess the you didn't want to paste the first three lines.
    – DarkDust
    Commented Jan 9, 2014 at 14:23
  • Put your array like this , and try please... char a[]="aaaaa"; WriteString (100, 225, &a);
    – ragip
    Commented Jan 9, 2014 at 14:27
  • 2
    Why do you insist on wrapping strlen in a function called WriteString? Your function does not write a string, it returns the length of a string.
    – DarkDust
    Commented Jan 9, 2014 at 14:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.