getting the length of an array after passing as a char* [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Sizeof an array in the C programming language?
I have code of the following form:
void arrLen(char* array){
// print length
}
int main(){
char bytes[16];
arrLen(bytes);
}
What I need to do is get the length of the underlying array and print it out. The issue is that the array MAY CONTAIN NULL CHARACTERS, and therefore strlen would not work. is there any way to do this, or would I have to pass it as a char[] instead of a char*?

C style arrays do not carry length information with them.
You have several solutions avaliable :
pass the size of your array to your function :
void arrLen(char* array, std::size_t size)
use std::array if you have access to C++ 11 (or TR1 as mentionned in comments)
std::array<char, 16> bytes;
If you don't have access to std::array, you can use boost::array. They are roughly equivalent to the standard one.
Regarding your comment
would I have to pass it as a char[] instead of a char*?
Arrays are always passed to functions as pointers, so void arrLen(char* array) and void arrLen(char[] array) are equivalent.

or would I have to pass it as a char[] instead of a char*?
Changing the declaration of arrLen() to take a parameter of type char[] instead of char* would have no effect, as in this scenario they are equivalent.
A possible solution would be to use a template function:
#include <iostream>
template <typename T, int N>
void array_size(T (&a)[N])
{
std::cout << N << "\n";
}
int main()
{
array_size("hello");
char bytes[16];
array_size(bytes);
return 0;
}
See http://ideone.com/l7GxDp for demo.
Alternatives to using an array:
std::string; these can contain NULL characters:
std::string s("hello\0world", 11);
std::vector<char>
boost::array<char, 16> (available as std::array<char,16> in C++11, or std::tr1::array in most every C++ compiler on the market)

In the traditional way (C) one has to pass the size as an attribute of the function
void arrLen(char* array, int maxSize){
// print length
}
int main(){
char bytes[16];
arrLen(bytes, 16);
}

arrays in C/C++ aren't handled that way per say, you have to manually keep track of the length yourself.. change your function to something like void arrLen(char * array, int size) and specify the size whenever you call the function.

If you have a C++11, may I suggest that you use std::array, it keeps track of it size.

Unfortunately, char[] and char* parameter types are equivalent.
You have two options:
Pass the length along with the pointer like one would in C:
void arrLen(char* array, size_t length)
or use a template:
template<size_t sz>
void arrLen(char (&array)[sz])

Related

How to get the number of columns of a char array?

Is there a way to get the number of columns a char array has?
It's declared like this: static const char *countries[][2] = { ... };
But I want to get it dynamically, so without typing '2' myself
No, you have to pass the size along with the array. There might exist system/compiler/library dependent ways, but it's not a good idea to rely on such functionalities.
If you're using the C++ standard library, you'd better use std::vector, which carries more metadata, such as the size() you're interested in.
Sure you may. Statically initialized arrays can be inspected with the sizeof operator easily. The following snippet (in C) prints all sizes that are assoiated to your 2D array of pointers.
#include <stdio.h>
static const char *countries[][2] = { { "dfdf", "dss" }, { "ss"}, { "toto"}};
int main(void) {
printf("dim0 %zu, dim1 %zu, elements %zu\n",
sizeof countries/sizeof countries[0],
sizeof countries[0]/sizeof countries[0][0],
sizeof countries/sizeof countries[0][0]
);
}

Difference between passing array, fixed-sized array and base address of array as a function parameter

I am confused about which syntax to use if I want to pass an array of known or unknown size as a function parameter.
Suppose I have these variants for the purpose:
void func1(char* str) {
//print str
}
void func2(char str[]) {
//print str
}
void func3(char str[10]) {
//print str
}
What are the pros and cons of using each one of these?
All these variants are the same. C just lets you use alternative spellings but even the last variant explicitly annotated with an array size decays to a normal pointer.
That is, even with the last implementation you could call the function with an array of any size:
void func3(char str[10]) { }
func("test"); // Works.
func("let's try something longer"); // Not a single f*ck given.
Needless to say this should not be used: it might give the user a false sense of security (“oh, this function only accepts an array of length 10 so I don’t need to check the length myself”).
As Henrik said, the correct way in C++ is to use std::string, std::string& or std::string const& (depending on whether you need to modify the object, and whether you want to copy).
Note that in C++, if the length of the array is known at compile time (for example if you passed a string literal), you can actually get its size:
template<unsigned int N>
void func(const char(&str)[N])
{
// Whatever...
}
int main()
{
func("test"); // Works, N is 5
}
In C++, use void func4(const std::string& str).
These are all functionally identical. When you pass an array to a function in C, the array gets implicitly converted to a pointer to the first element of the array. Hence, these three functions will print the same output (that is, the size of a pointer to char).
void func1(char* str) {
printf("sizeof str: %zu\n", sizeof str);
}
void func2(char str[]) {
printf("sizeof str: %zu\n", sizeof str);
}
void func3(char str[10]) {
printf("sizeof str: %zu\n", sizeof str);
}
This conversion only applies to the first dimension of an array. A char[42][13] gets converted to a char (*)[13], not a char **.
void func4(char (*str_array)[13]) {
printf("sizeof str_array: %zu\n"
"sizeof str_array[0]: %zu\n", sizeof str_array, sizeof str_array[0]);
}
char (*)[13] is the type of str_array. It's how you write "a pointer to an array of 13 chars". This could have also been written as void func4(char str_array[42][13]) { ... }, though the 42 is functionally meaningless as you can see by experimenting, passing arrays of different sizes into func4.
In C99 and C11 (but not C89 or C++), you can pass a pointer to an array of varying size into a function, by passing it's size along with it, and including the size identifier in the [square brackets]. For example:
void func5(size_t size, char (*str_array)[size]) {
printf("sizeof str_array: %zu\n"
"sizeof str_array[0]: %zu\n", sizeof str_array, sizeof str_array[0]);
}
This declares a pointer to an array of size chars. Note that you must dereference the pointer before you can access the array. In the example above, sizeof str_array[0] evaluates to the size of the array, not the size of the first element. As an example, to access the 11th element, use (*str_array)[11] or str_array[0][11].
In C, the first two definitions are equivalent.The third one is essentially same but it gives an idea about the size of the array.
If printing str is your intent, then you can safely use any of them.Essentially all three of the functions are passed a parameter of type char*,just what printf() needs to print a string.And lest you don't know, despite what it may seem, all parameter passing in C is done in pass-by-value mode.
Edit: Seems like I'll have to be very rigorous in my choice of words on SO henceforth.Well,in the third case it gives no idea about the size of the array to the function to which it is passed as eventually it is reduced to type char* just as in the first two cases.I meant to say it kinda tells the human reading it that the array's size is 10.Also,it is not wrong/illegal in C.But for the program,doing it is as good as useless.It gives no idea whatsoever about the array size to the function it is passed to.Mr.Downvoter, thanks for pointing out that casual attitude and negligence is not tolerated on SO.
In a one dimensional array they are all treated the same by the compiler. However for a two or more dimensional array, (e.g. myArray[10][10]), it is useful as it can be used to determine the row/column length of an array.
To add-on, describing in points.
1) As everyone told it is same.
2) Arrays are decayed into pointers when they are passed in the function arguments.
3) Fundamental problem could be finding the size of a array in the function. For that we can use macro like.
#define noOfElements(v) sizeof(v)/sizeof(0[v])
int arr[100]
myfunction ( arr, noOfElements(arr))
either 0[v] or v[0] can be used in the macro, where the first is used to avoid user defined data type passed in to noOfElements.
Hope this helps.

problem with sizeof operator

As i want to find array size dynamically in function, i used sizeof operator. But i got some unexpected result.
here is one demo program to show you, what i want to do.
//------------------------------------------------------------------------------------------
#include <iostream>
void getSize(int *S1){
int S_size = sizeof S1/sizeof(int);
std::cout<<"array size(in function):"<<S_size<<std::endl;
}
int main(){
int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6};
getSize(S);
std::cout<<"array size:"<<sizeof S/sizeof(int)<<std::endl;
return 0;
}
//------------------------------------------------------------------------------------------
compilation command : g++ demo1.cc -o demo1 {fedora 12}
output:
array size(in function):2
array size:19
please explain ,why this is happening.
what can be done to solve this problem.
void getSize(int *S1)
When you pass an array to this function, it decays to pointer type, so sizeof operator will return the size of pointer.
However, you define your function as,
template<int N>
void getSize(int (&S1)[N])
{
//N is the size of array
int S_size1 = N;
int S_size2 = sizeof(S1)/sizeof(int); //would be equal to N!!
std::cout<<"array size(in function):"<<S_size1<<std::endl;
std::cout<<"array size(in function):"<<S_size2<<std::endl;
}
int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6};
getSize(S); //same as before
then you can have the size of array, in the function!
See the demonstration yourself here : http://www.ideone.com/iGXNU
Inside getSize(), you're getting size of pointer, which is 8 bytes (since you're probably running 64-bit OS). In main(), you're getting size of array.
If you want to know array size, pass result of sizeof(S) as additional argument to getSize().
More alternatives would be using some container (like std::vector) or turning function into template function, as Nawaz proposed.
S is an int *, a pointer to an integer, which is a memory address, which is on your machine twice the size of an integer.
If you want the size of the array (I.e., the number of elements), you can't get that directly in pure C. But since this is a c++ question, there is a way: use a vector, which has a size() method.
Actually, this isn't quite true: within the function that you declare S (and only if it's explicitly initialized at compile time as you do in your example -- even new int[19] doesn't work), the sizeof operator actually does get the correct answer, which is why c++ allows you to do this:
int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6};
vector<int> v(S, S + sizeof(S) / sizeof(int) );
and then you can use v.size() (see these docs).
The template version by Nawaz elsewhere is another excellent suggestion which forces the compiler into carrying the full information about the construction of the c++ array around (again, note that this is all known at compile time, which is why you can be explicit about the size in the argument).
you are getting the size of the pointer to the array. If you want the size of the array you have to multiply the number of elements by the size of each element.
You will have to pass the size of the array to the function.
Since you are only passing a pointer to the first element in the array, your function has no information on its actual size.
void getSize(int *S1, size_t size)
{
int S_Size = sizeof(*S1) * size;
}
This is redundant though, if you think about it :D
To prevent this type of accidental misuse of sizeof, you can define a function which only works on arrays:
template<class T, int N>
int array_size(T (&)[N]) {
return N;
}
If you use this in your code, you'll see a compiler error when applied to S1, as it is not an array. Plus, it's shorter and a bit more explicit than sizeof array / sizeof array[0] (using the size of the first item means you don't have to repeat the array type).
This also already exists in Boost in a more general form (accepting anything with a size method, such as std::vector).

How do I use member functions of constant arrays in C++?

Here is a simplified version of what I have (not working):
prog.h:
...
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
const string c_astrExamples[] = {c_strExample1, c_strExample2};
...
prog.cpp:
...
int main()
{
int nLength = c_astrExamples.length();
for (int i = 0; i < nLength; i++)
cout << c_astrExamples[i] << "\n";
return 0;
}
...
When I try to build, I get the following error:
error C2228: left of '.length' must have class/struct/union
The error occurs only when I try to use member functions of the c_astrExamples.
If I replace "c_astrExamples.length()" with the number 2, everything appears to work correctly.
I am able to use the member functions of c_strExample1 and c_strExample2, so I think the behavior arises out of some difference between my use of strings vs arrays of strings.
Is my initialization in prog.h wrong? Do I need something special in prog.cpp?
Arrays in C++ don't have member functions. You should use a collection like vector<string> if you want an object, or compute the length like this:
int nLength = sizeof(c_astrExamples)/sizeof(c_astrExamples[0]);
Just use STL vector of strings instead of array:
#include <string>
#include <vector>
using namespace std;
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
vector<string> c_astrExamples;
c_astrExamples.push_back(c_strExample1);
c_astrExamples.push_back(c_strExample2);
int main()
{
int nLength = c_astrExamples.size();
Arrays in C++ are inherited from C, which wasn't object-oriented. So they aren't objects and don't have member functions. (In that they behave like int, float and the other built-in types.) From that ancestry stem more problems with array, like the fact that they easily (e.g., when passed into a function) decay into a pointer to the first element with no size information left.
The usual advice is to use std::vector instead, which is a dynamically resizable array. However, if you the array size is known at compile-time and you need a constant, then boost's array type (boost::array, if your compiler supports the TR1 standard extensions also available as std::tr1::array, to become std::array in the next version of the C++ standard) is what you want.
Edit 1:
A safe way to get the length of an array in C++ involves an incredible combination of templates, function pointers and even a macro thrown into the mix:
template <typename T, std::size_t N>
char (&array_size_helper(T (&)[N]))[N];
#define ARRAY_SIZE(Array_) (sizeof( array_size_helper(Array_) ))
If you (like me) think this is hilarious, look at boost::array.
Edit 2:
As dribeas said in a comment, if you don't need a compile-time constant, this
template <typename T, std::size_t N>
inline std::size_t array_size(T(&)[N])
{return N;}
is sufficient (and much easier to read and understand).
c_astrExamples is an array, there is no "length()" method in it.
In C++ arrays are not objects and have no methods on it. If you need to get the length of the array you could use the following macro
#define COUNTOF( array ) ( sizeof( array )/sizeof( array[0] ) )
int nLength = COUNTOF(c_astrExamples);
Also, beware of initialisation in a header file. You risk offending the linker.
You should have:
prog.h:
extern const string c_strExample1;
extern const string c_strExample2;
extern const string c_astrExamples[];

Calculating size of an array

I am using the following macro for calculating size of an array:
#define G_N_ELEMENTS(arr) ((sizeof(arr))/(sizeof(arr[0])))
However I see a discrepancy in the value computed by it when I evaluate the size of an array in a function (incorrect value computed) as opposed to where the function is called (correct value computed). Code + output below. Any thoughts, suggestions, tips et al. welcome.
DP
#include <stdio.h>
#define G_N_ELEMENTS(arr) ((sizeof(arr))/(sizeof(arr[0])))
void foo(int * arr) // Also tried foo(int arr[]), foo(int * & arr)
// - neither of which worked
{
printf("arr : %x\n", arr);
printf ("sizeof arr: %d\n", G_N_ELEMENTS(arr));
}
int main()
{
int arr[] = {1, 2, 3, 4};
printf("arr : %x\n", arr);
printf ("sizeof arr: %d\n", G_N_ELEMENTS(arr));
foo(arr);
}
Output:
arr : bffffa40
sizeof arr: 4
arr : bffffa40
sizeof arr: 1
That's because the size of an int * is the size of an int pointer (4 or 8 bytes on modern platforms that I use but it depends entirely on the platform). The sizeof is calculated at compile time, not run time, so even sizeof (arr[]) won't help because you may call the foo() function at runtime with many different-sized arrays.
The size of an int array is the size of an int array.
This is one of the tricky bits in C/C++ - the use of arrays and pointers are not always identical. Arrays will, under a great many circumstances, decay to a pointer to the first element of that array.
There are at least two solutions, compatible with both C and C++:
pass the length in with the array (not that useful if the intent of the function is to actually work out the array size).
pass a sentinel value marking the end of the data, e.g., {1,2,3,4,-1}.
This isn't working because sizeof is calculated at compile-time. The function has no information about the size of its parameter (it only knows that it points to a memory address).
Consider using an STL vector instead, or passing in array sizes as parameters to functions.
In C++, you can define G_N_ELEMENTS like this :
template<typename T, size_t N>
size_t G_N_ELEMENTS( T (&array)[N] )
{
return N;
}
If you wish to use array size at compile time, here's how :
// ArraySize
template<typename T>
struct ArraySize;
template<typename T, size_t N>
struct ArraySize<T[N]>
{
enum{ value = N };
};
Thanks j_random_hacker for correcting my mistakes and providing additional information.
Note that even if you try to tell the C compiler the size of the array in the function, it doesn't take the hint (my DIM is equivalent to your G_N_ELEMENTS):
#include <stdio.h>
#define DIM(x) (sizeof(x)/sizeof(*(x)))
static void function(int array1[], int array2[4])
{
printf("array1: size = %u\n", (unsigned)DIM(array1));
printf("array2: size = %u\n", (unsigned)DIM(array2));
}
int main(void)
{
int a1[40];
int a2[4];
function(a1, a2);
return(0);
}
This prints:
array1: size = 1
array2: size = 1
If you want to know how big the array is inside a function, pass the size to the function. Or, in C++, use things like STL vector<int>.
Edit: C++11 was introduced since this answer was written, and it includes functions to do exactly what I show below: std::begin and std::end. Const versions std::cbegin and std::cend are also going into a future version of the standard (C++14?) and may be in your compiler already. Don't even consider using my functions below if you have access to the standard functions.
I'd like to build a little on Benoît's answer.
Rather than passing just the starting address of the array as a pointer, or a pointer plus the size as others have suggested, take a cue from the standard library and pass two pointers to the beginning and end of the array. Not only does this make your code more like modern C++, but you can use any of the standard library algorithms on your array!
template<typename T, int N>
T * BEGIN(T (& array)[N])
{
return &array[0];
}
template<typename T, int N>
T * END(T (& array)[N])
{
return &array[N];
}
template<typename T, int N>
const T * BEGIN_CONST(const T (& array)[N])
{
return &array[0];
}
template<typename T, int N>
const T * END_CONST(const T (& array)[N])
{
return &array[N];
}
void
foo(int * begin, int * end)
{
printf("arr : %x\n", begin);
printf ("sizeof arr: %d\n", end - begin);
}
int
main()
{
int arr[] = {1, 2, 3, 4};
printf("arr : %x\n", arr);
printf ("sizeof arr: %d\n", END(arr) - BEGIN(arr));
foo(BEGIN(arr), END(arr));
}
Here's an alternate definition for BEGIN and END, if the templates don't work.
#define BEGIN(array) array
#define END(array) (array + sizeof(array)/sizeof(array[0]))
Update: The above code with the templates works in MS VC++2005 and GCC 3.4.6, as it should. I need to get a new compiler.
I'm also rethinking the naming convention used here - template functions masquerading as macros just feels wrong. I'm sure I will use this in my own code sometime soon, and I think I'll use ArrayBegin, ArrayEnd, ArrayConstBegin, and ArrayConstEnd.
If you change the foo funciton a little it might make you feel a little more comfortable:
void foo(int * pointertofoo)
{
printf("pointertofoo : %x\n", pointertofoo);
printf ("sizeof pointertofoo: %d\n", G_N_ELEMENTS(pointertofoo));
}
That's what the compiler will see something that is completely a different context than the function.
foo(int * arr) //Also tried foo(int arr[]), foo(int * & arr)
{ // - neither of which worked
printf("arr : %x\n", arr);
printf ("sizeof arr: %d\n", G_N_ELEMENTS(arr));
}
sizeof(arr) is sizeof(int*), ie. 4
Unless you have a very good reason for writing code like this, DON'T. We're in the 21st century now, use std::vector instead.
For more info, see the C++ FAQ: http://www.parashift.com/c++-faq-lite/containers.html
Remember: "Arrays are evil"
You should only call sizeof on the array. When you call sizeof on the pointer type the size will always be 4 (or 8, or whatever your system does).
MSFT's Hungarian notation may be ugly, but if you use it, you know not to call your macro on anything that starts with a 'p'.
Also checkout the definition of the ARRAYSIZE() macro in WinNT.h. If you're using C++ you can do strange things with templates to get compile time asserts if do it that way.
Now that we have constexpr in C++11, the type safe (non-macro) version can also be used in a constant expression.
template<typename T, std::size_t size>
constexpr std::size_t array_size(T const (&)[size]) { return size; }
This will fail to compile where it does not work properly, unlike your macro solution (it won't work on pointers by accident). You can use it where a compile-time constant is required:
int new_array[array_size(some_other_array)];
That being said, you are better off using std::array for this if possible. Pay no attention to the people who say to use std::vector because it is better. std::vector is a different data structure with different strengths. std::array has no overhead compared to a C-style array, but unlike the C-style array it will not decay to a pointer at the slightest provocation. std::vector, on the other hand, requires all accesses to be indirect accesses (go through a pointer) and using it requires dynamic allocation. One thing to keep in mind if you are used to using C-style arrays is to be sure to pass std::array to a function like this:
void f(std::array<int, 100> const & array);
If you do not pass by reference, the data is copied. This follows the behavior of most well-designed types, but is different from C-style arrays when passed to a function (it's more like the behavior of a C-style array inside of a struct).