How to Get the Real and Total Length of Char * (Char Array)

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

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

C++ Size of char* buffer

There is general no way of determining the size of an array based on a pointer to an element of that array.

Here are typical ways to find out the size:

  • Store the size in a variable
    • A variant of this is to store both the pointer and the size (or alternatively, pointer past the end) as members of a class. An example of this approach is the std::span class template (this standard class is not in C++98, but you can write your own, limited version).
      • A variant this, which is generally used when the array is allocated dynamically (such as in your example), is to deallocate the memory in the destructor of the class and conforming to the RAII idiom. Examples of this approach are std::string and std::vector.
  • Or choose certain element value to represent the last element of the array. When iterating the array, encountering this "terminator" element tells you that the end has been reached. This is typically used with character strings, especially in C interfaces, where the null terminator character ('\0') is used.

How to access a pointer's value that is a char array

You can't use the pointer to a local array outside the scope where that array was defined because it's stored in the stack frame of the function and will be popped out when the function finishes and returns, so it will no longer be valid to use it (read it). Instead, you could pass the array from the caller function.

// In the caller function
char data[64];
intToAscii(1234, data);

And the intToAscii() function, simply

void intToAscii(unsigned long x, char *str)
{
int i;
unsigned long n;
for (i = 0; i < 63; i++) {
n = x >> 63;
if (n == 0) {
str[i] = '0';
} else {
str[i] = '1';
}
x = x << 1;
}
str[i] = '\0';
printf("Value of x is %s \n", str);
}

Another mistake, is that you are accessing index 64 of str, but arrays are 0-indexed so 64 is out of bounds besides, the '\0' terminator must be the character right after the last, you can achieve that by using the index i which will have the correct value at the end of the loop and this way it doesn't matter if it's 63 or 64, it's the right value as long as the loop is ending before the last element of the array.

One more thing, functions like this are very dangerous, instead you can pass another parameter to tell the function how many bytes are available in the destination array like this,

void intToAscii(unsigned long x, char *str, size_t size)
{
int i;
unsigned long n;
for (i = 0; i < size - 1; i++) {
n = x >> 63;
if (n == 0) {
str[i] = '0';
} else {
str[i] = '1';
}
x = x << 1;
}
str[i] = '\0';
printf("Value of x is %s \n", str);
}

And finally, as was commented by @David C. Rankin your function returns char but it's body does not return anywhere, that will cause undefined behavior. You don't need your function to return anything because it modifies the array in place.

How to get array size within function?

so here are my answers for your questions:

  1. The array is "converted" into char* type when passed into the function (with the char* parameter).
  2. AFAIK there is no such way. You could use strlen function for strings. Otherwise, you have to pass the length as parameter.
  3. See How does an array pointer store its size?

Don't use sizeof(buf)/sizeof(buf[0]) to get length of an array when passing array parameters. See this. for more information.

Printing each character of char array instead of each partial one

char mess[] = "abcd"; means mess aka &mess[0] is the address of the string {'a', 'b', 'c', 'd', \0 }. ptr = mess + strlen(mess); means ptr initially points to the \0 of mess. In the loop ptr is decremented, and the subsequent printf() will print from where ptr points to till it sees \0 (i.e. tail of mess):

// initial:
abcd\0
^----- mess aka &mess[0]
^ ptr = mess + strlen(mess) = mess + 4

Get length of a pointer ( not sizeoff )

You can cast the ptr to type intptr_t and from there use a standard digit counting algorithm :

int main() {
int counter = 0;
int* ptr = &counter;
intptr_t val = (intptr_t)ptr;

while ( val > 0 )
{
val/=16;
++counter;
}

printf("%d", counter);

return 0;
}

Why I get the length of an array like this?

An array decays to a pointer to the first element of the array in most expressions. There are two cases where it does not and hence the outcome is not the same.

int array[5];
int* ptr = array; // Array decays to a pointer, OK.

// Same
int a = array[0];
int a = ptr[0];

// Same
void foo(int*);
foo(array);
foo(ptr);

// Not same
size_t s = sizeof(array); // s is 5*sizeof(int)
size_t s = sizeof(ptr); // s is sizeof(int*)

// Not same
int (*p1)[5] = &array; // p1 is a pointer to "an array of 5 ints"
int **p1 = &ptr; // p1 is a pointer to "an int*"


Related Topics



Leave a reply



Submit