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[];
Related
I want to convert a non constant variable to constant variable. I tried using const_cast but still the following program is giving error that ‘bitsize1’ cannot appear in a constant-expression. What am i doing wrong ?
#include <string>
#include <bitset>
#include <iostream>
using namespace std;
int main(){
int l = 3; // taken input from user
int bitsize2 = (l * 2);
int bitsize1 = const_cast<int&>(bitsize2);
string temp = "100101";
bitset<const_cast<int&>(bitsize2)> baz (temp);
cout << baz;
return 0;
}
const_cast is used to cast const away not to make something const. If you want constant expression the easiest way in post-C++11 programming is to use constexpr:
constexpr int l = 3;
constexpr int bitsize2 = l * 2;
The input from user cannot be a compile time constant expression so you must figure out something else.
Templates are expanded in compile time, this means that all template arguments should be known when compiling. Obviously user input is runtime data thus cannot be used as a template argument.
As stated by others, you cannot deduce template parameters at runtime.
You should look into using boost's dynamic bitset.
It exists for the exact problem that you have run into.
"The dynamic_bitset class is nearly identical to the std::bitset class.
The difference is that the size of the dynamic_bitset (the number of
bits) is specified at run-time during the construction of a
dynamic_bitset object, whereas the size of a std::bitset is specified
at compile-time through an integer template parameter."
This code will not compile:
#ifndef RemoteControl_h
#define RemoteControl_h
#include "Arduino.h"
class RemoteControl
{
public:
RemoteControl();
~RemoteControl();
static void prev_track();
static void next_track();
static void play_pause_track();
static void mute();
static void vol_up();
static void vol_down();
void respond(int code);
void add_code(int code, void (*func)());
private:
boolean active = true;
struct pair {
int _code;
void (*_func)();
};
const int max = 1000;
int database_length = 0;
pair database[max]; //This line doesn't compile unless I use a literal constant instead of "max"
};
#endif
But if I put the section below in the constructor for the class instead it works fine.
const int max = 1000;
int database_length = 0;
pair database[max];
Am I not allowed to declare an array within a class in c++ and use a virtual constant as the length? I am working in arduino if that makes a difference, but I expect that I am not understanding something with the c++ language since this is a standard .h file. Oh and the problem isn't the .cpp file because I completely removed it with the same results: compiles with literal constant length but not virtual constant length.
In C or C++,try using malloc() in stdlib.h, cstdlib for c++. Don't forget free()
const int max = 1000;
struct pair *ptr = malloc(sizeof(pair) * max); // allocated 1000 pairs
free(ptr); // when the amount of memory is not needed anymore
Let me first clear a few things up for you.
In C, a const variable is considered as const-qualified, it is not a compile-time constant value (unlike an integer literal, which is a compile time constant value). So, as per the rules for normal array size specification, you cannot even use a const variable in this case.
In C, we may have the provision to use VLA which enables us to use syntax like pair database[max] even if max is not a const variable but that is again some optional feature of the compiler (as per C11).
In C++, we can use a const variable as the size of array, as in C++, a const variable is a compile time constant.
So, to answer your question:
In C, your code will be ok if your compiler supports VLA. and even if max is not const.
In C++, there is no VLA, but it maybe supported as a gnu extension. If max is const, it will be ok.
The easiest fix is to just take the
const int max = 1000;
out of the class and put it above the class.
Even better would be to ensure that it is a compile-time constant like so:
constexpr int max = 1000;
Why compiler doesn't pass size of array char *arr[] in parameters? I wanted to get get size of array passed by parameter but I guess it doesn't work because even char *a[] is char ** my question is why is it and can I make it work?
#include <stdio.h>
#include <stddef.h>
#include <stdio.h>
template<class T, size_t len>
constexpr size_t lengthof(T(&)[len])
{
return len;
}
void printarr(const char *a[]);
int main()
{
const char *a[] = { "aba", "bd", "cd" };
printarr(a);
}
void printarr(const char *a[])
{
for(size_t i = 0, c = lengthof(a); i < c; i++) {
printf("str = %s\n", a[i]);
}
}
You can make it work by using the same trick you used in your lengthof function template.
template<size_t len>
void printarr(const char* (&a)[len])
{
for(size_t i = 0, c = lengthof(a); i < c; i++) {
printf("str = %s\n", a[i]);
}
}
That has been a feature of C since the beginning and carried through into C++.
In the case of string arrays, the solution has been to add a trailing null character to mark the end.
The was probably done for the sake of efficiency when C started on ancient PDP computers.
Use strlen; or better yet std::string or std::vector.
Because this is required by the C++ standard, which inherited this behavior from C (and since C++ wants to stay compatible with C).
As function parameters, arrays are decayed into pointers.
You really want to use something like std::vector<std::string> instead. Learn more about standard C++ STL containers.
C++ is a language what provides low level access to system resources.
Processor is not working with objects, but with memory addresses.
If you want predefined structures, use Java, C#, python, or c++ libs like stl.
From the point of view of the language, your array doesn't have a length; the compiler cannot read your mind and decide where the array begins and where it ends, and it cannot waste memory and processing to perform range checking.
The closest thing to an array length is the number of consecutive memory spaces that have been allocated by a single new[] invocation, but such information is only authoritative for the purpose of allocating and deallocating memory: the "array" you want to process in your function might be only a portion of a single allocation (for example, you might allocate memory to load a whole text file and process each line separately).
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])
Let's say I have a macro called LengthOf(array):
sizeof array / sizeof array[0]
When I make a new array of size 23, shouldn't I get 23 back for LengthOf?
WCHAR* str = new WCHAR[23];
str[22] = '\0';
size_t len = LengthOf(str); // len == 4
Why does len == 4?
UPDATE: I made a typo, it's a WCHAR*, not a WCHAR**.
Because str here is a pointer to a pointer, not an array.
This is one of the fine differences between pointers and arrays: in this case, your pointer is on the stack, pointing to the array of 23 characters that has been allocated elsewhere (presumably the heap).
WCHAR** str = new WCHAR[23];
First of all, this shouldn't even compile -- it tries to assign a pointer to WCHAR to a pointer to pointer to WCHAR. The compiler should reject the code based on this mismatch.
Second, one of the known shortcomings of the sizeof(array)/sizeof(array[0]) macro is that it can and will fail completely when applied to a pointer instead of a real array. In C++, you can use a template to get code like this rejected:
#include <iostream>
template <class T, size_t N>
size_t size(T (&x)[N]) {
return N;
}
int main() {
int a[4];
int *b;
b = ::new int[20];
std::cout << size(a); // compiles and prints '4'
// std::cout << size(b); // uncomment this, and the code won't compile.
return 0;
}
As others have pointed out, the macro fails to work properly if a pointer is passed to it instead of an actual array. Unfortunately, because pointers and arrays evaluate similarly in most expressions, the compiler isn't able to let you know there's a problem unless you make you macro somewhat more complex.
For a C++ version of the macro that's typesafe (will generate an error if you pass a pointer rather than an array type), see:
Compile time sizeof_array without using a macro
It wouldn't exactly 'fix' your problem, but it would let you know that you're doing something wrong.
For a macro that works in C and is somewhat safer (many pointers will diagnose as an error, but some will pass through without error - including yours, unfortunately):
Is there a standard function in C that would return the length of an array?
Of course, using the power of #ifdef __cplusplus you can have both in a general purpose header and have the compiler select the safer one for C++ builds and the C-compatible one when C++ isn't in effect.
The problem is that the sizeof operator checks the size of it's argument. The argument passed in your sample code is WCHAR*. So, the sizeof(WCHAR*) is 4. If you had an array, such as WCHAR foo[23], and took sizeof(foo), the type passed is WCHAR[23], essentially, and would yield sizeof(WCHAR) * 23. Effectively at compile type WCHAR* and WCHAR[23] are different types, and while you and I can see that the result of new WCHAR[23] is functionally equivalent to WCHAR[23], in actuality, the return type is WCHAR*, with absolutely no size information.
As a corellary, since sizeof(new WCHAR[23]) equals 4 on your platform, you're obviously dealing with an architecture where a pointer is 4 bytes. If you built this on an x64 platform, you'd find that sizeof(new WCHAR[23]) will return 8.
You wrote:
WCHAR* str = new WCHAR[23];
if 23 is meant to be a static value, (not variable in the entire life of your program) it's better use #define or const than just hardcoding 23.
#define STR_LENGTH 23
WCHAR* str = new WCHAR[STR_LENGTH];
size_t len = (size_t) STR_LENGTH;
or C++ version
const int STR_LENGTH = 23;
WCHAR* str = new WCHAR[STR_LENGTH];
size_t len = static_cast<size_t>(STR_LENGTH);