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
andstd::vector
.
- 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
- 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
- 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:
- The array is "converted" into
char*
type when passed into the function (with the char* parameter). - AFAIK there is no such way. You could use
strlen
function for strings. Otherwise, you have to pass the length as parameter. - 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
How to Make a Variadic MACro for Std::Cout
Waitforinputidle Doesn't Work for Starting Mspaint Programmatically
How Is the C++ Exception Handling Runtime Implemented
Are C++ Templates Just MACros in Disguise
What Are the Use Cases for Having a Function Return by Const Value for Non-Builtin Type
Error: Variable "Cannot Be Implicitly Captured Because No Default Capture Mode Has Been Specified"
C++ Threads, Std::System_Error - Operation Not Permitted
What's the Most Reliable Way to Prohibit a Copy Constructor in C++
Inheritance and Method Overloading
Struct Initialization of the C/C++ Programming Language
Map Set/Get Requests into C++ Class/Structure Changes
Iterative Dfs VS Recursive Dfs and Different Elements Order
Are Virtual Destructors Inherited
How Much Footprint Does C++ Exception Handling Add
What Is Decltype with Two Arguments