How to get the real and total length of char * (char array)?

C++CArraysPointersChar

C++ Problem Overview


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");

C++ Solutions


Solution 1 - C++

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...

Solution 2 - C++

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

Otherwise, there is no way to determine that information

Solution 3 - C++

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.

Solution 4 - C++

  • 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);
}

Solution 5 - C++

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.

Solution 6 - C++

> 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;

Solution 7 - C++

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.

Solution 8 - C++

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.

Solution 9 - C++

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:

Solution 10 - C++

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.

Solution 11 - C++

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.

Solution 12 - C++

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;
}

Solution 13 - C++

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.

Solution 14 - C++

You could try this:

int lengthChar(const char* chararray) {
   int n = 0;
   while(chararray[n] != '\0')
	 n ++;
   return n;  
}

Solution 15 - C++

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

// char *s

unsigned int  strLength=strlen(s);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionherohuyongtaoView Question on Stackoverflow
Solution 1 - C++Elias Van OotegemView Answer on Stackoverflow
Solution 2 - C++OlotiarView Answer on Stackoverflow
Solution 3 - C++DarkDustView Answer on Stackoverflow
Solution 4 - C++Jarod42View Answer on Stackoverflow
Solution 5 - C++Mike SeymourView Answer on Stackoverflow
Solution 6 - C++Vlad from MoscowView Answer on Stackoverflow
Solution 7 - C++MontaldoView Answer on Stackoverflow
Solution 8 - C++barak manosView Answer on Stackoverflow
Solution 9 - C++SiddharthView Answer on Stackoverflow
Solution 10 - C++Pratik SinghalView Answer on Stackoverflow
Solution 11 - C++sakView Answer on Stackoverflow
Solution 12 - C++HolyRandomView Answer on Stackoverflow
Solution 13 - C++DevonJohnView Answer on Stackoverflow
Solution 14 - C++Вениамин РаскинView Answer on Stackoverflow
Solution 15 - C++ragipView Answer on Stackoverflow