I see this being commonly used in file handling, (char*)&obj.
There are so many casting methods available since C++11,like static cast, cant we employ one over these ?
The & sign is there to take the address of obj.
Example:
#include <cstdio>
void printData(const char* p, int n) {
for(int i = 0; i < n; i++)
printf("byte %2d : %d\n", i, (int)p[i]);
}
struct DataStruct {
int x;
int y;
};
int main() {
DataStruct obj;
obj.x = 5;
obj.y = 257;
char* dataPtr = (char*)&obj;
printData(dataPtr, sizeof(DataStruct));
return 0;
}
where the (char*)&obj maneouver is used to get a char* that can be passed to the printData function which just wants an array of chars to print.
In that example, the line
char* dataPtr = (char*)&obj;
could instead have been written using reinterpret_cast like this:
char* dataPtr = reinterpret_cast<char*>(&obj);
which would do the same thing. An advantage of using reinterpret_cast instead of the cryptic (char*)&obj is that when you write reinterpret_cast it becomes more clearly visible that you are doing something kind of strange and possibly dangerous at that point in the code.
Related
I have a struct that contains a const array, and would like to initialise it to specific values upon construction. Unfortunately, its contents depend on several parameters which are passed into the constructor as parameters, and require a function to compute the contents of the array.
What I'd ideally like to do looks something like this:
struct SomeType {
const unsigned int listOfValues[32];
unsigned int[32] processParameters(unsigned int parameter) {
unsigned int arrayValues[32];
for(int i = 0; i < 32; i++) {
arrayValues[i] = i * parameter;
}
return arrayValues;
}
SomeType(unsigned int parameter) : listOfValues(processParameters(parameter)) {
}
};
Of course there are several issues here (returning an array from a function is not possible, data type mismatches, etc). However, is there any way this is possible?
I've seen other similar questions suggest using a std::vector for this, but the heap allocation(s) this incurs is something my performance budget can't afford.
As Nathan suggested you should change the raw array with an std::array. This way you still have the benefit of stack allocation but now you can initialize from a copy.
using MyArray = std::array<unsigned int, 32>;
const MyArray listOfValues;
MyArray processParameters(unsigned int parameter) {
MyArray arrayValues;
for(int i = 0; i < 32; i++) {
arrayValues[i] = i * parameter;
}
return arrayValues;
}
I removed the const from the array data type since it's not necesary because your array is const already, also with const unsigned int you wouldn't be able to set the values of arrayValues at run time.
Does this serve your purpose? No heap allocations that I can see.
struct SomeType {
const unsigned int *listOfValues;
const unsigned int * processParameters(unsigned int parameter) {
for(int i = 0; i < 32; i++) {
_listOfValues[i] = i * parameter;
}
return _listOfValues;
}
SomeType(unsigned int parameter) :
listOfValues(processParameters(parameter))
{
}
private:
unsigned int _listOfValues[32];
};
How correctly declare pointers, allocate memory, and send them as parameters in fuctions to write values ? The code below is what I tried but it doesn't work correctly. I need the same logic. I mean declare, set, then show.
...
struct complex {
int i;
int r;
};
void set(complex *n, int i, int r){
n = new complex;
n->i = i;
n->r = r;
}
void show(complex *n){
std::cout << n->i << " " << n->r;
}
int main(int argc, char* argv[])
{
complex *n;
set(n,10,20);
show(n);
system("pause");
return 0;
}
Actually, your function set couldn't work, because by doing
n = new complex;
whatever the pointer you pass to the function, the pointer will be overwritten by the pointer on the new object.
You can pass the pointer via reference (on C++ only...) like that
void set(complex* &n, int i, int r)
And by doing so you'll modify the value of the original pointer.
You can also simply return the pointer by a return n
But obviously if the prototype of your function must stay like that, it's not possible...
Or, but it's highly discouraged, as many said, you can use a double pointer, and it's quite tricky !
If I don't make mistake, you create a
complex** n
You pass it to your function
set(complex** n, int i, int r)
And then you load
*n = new complex
And it must work if you pass *n to all your function instead of n...
And don't forget to delete your object at the end ;)
Remove the initialization part from set function and put it in the main function.
see this link for explanation.
Why can I not initialize an array by passing a pointer to a function?
Check this code
//#include<windows.h>
#include <iostream>
using namespace std;
struct complex {
int i;
int r;
};
void set(complex *n, int i, int r) {
// n = new complex;
n->i = i;
n->r = r;
}
void show(complex *n) {
std::cout << n->i << " " << n->r;
}
int main(int argc, char *argv[]) {
complex *n = new complex();
set(n, 10, 20);
show(n);
delete n;
//system("pause"); TRY TO AVOID THIS. MAKES YOUR CODE LESS PORTABLE.
return 0;
}
see this link.
c++ - system("pause"); - Why is it wrong? - Stack Overflow
I want to map data from an array to a C++ class. The class will ONLY have private member variables, no inheritance or virtual stuff. Is this safe or should I use a struct in C++?
void main(void)
{
uint8_t data[50];
MyClass *msg;
msg = nullptr;
for (int i = 0; i < 50; i++)
{
data[i] = i;
}
msg = (MyClass *) &data[0];
cout << msg->name();
}
The class looks like this:
class MyClass
{
private:
int name;
public:
int name(); //Getter
void setName(); //Setter
};
You can do it for standard layout types but you need to consider alignment was well:
constexpr int bufmax = 50*sizeof(MyClass);
alignas(X) char buffer[bufmax];
However just because you can doesn't mean you should.
It is safe to use a uint8_t[] as a storage buffer if that's what you're asking, yes. A valid use would look something like this:
constexpr size_t array_size = 5;
alignas(MyClass) uint8_t data[sizeof(MyClass) * array_size ];
MyClass *msg = new(data) MyClass[array_size];
Then you can use msg however you'd like. Your usage is incorrect - if you populate data with uint8_t values, you cannot access it as if it were a MyClass. That would result in undefined behavior.
I'm trying to create my own version of an array called a safearray, to test my knowledge of operator overloading and creating proper class's and such.
I'm encountering two errors.
SafeArray.h:11:15: error: ‘const int SafeArray::operator’ cannot be overloaded
SafeArray.h:10:10: error: with ‘int& SafeArray::operator’
My code is split between three files.
Main.cpp
#include <cstdlib>
#include <iostream>
#include "SafeArray.h"
using namespace std;
int main(int argc, char** argv) {
SafeArray a(10); // 10 integer elements
for (int i = 0; i < a.length(); i++) {
cout << i << " " << a[i] << "s" << endl; // values initialise to 0
}
cout << endl << a[1]; // Program exits here.
a[3] = 42;
cout << a[3];
a[10] = 10;
cout << a[10];
a[-1] = -1; // out-of-bounds is "safe"?
SafeArray b(20); // another array
b = a; // array assignment
for (int i = 0; i < b.length(); i++) {
cout << b[i] << endl; // values copied from a
}
return 0;
}
SafeArray.h
#ifndef SAFEARRAY_H
#define SAFEARRAY_H
class SafeArray {
public:
SafeArray(int); // int variable will be the array size
int length();
int boundsCheck(int y); // constructor will call this function
// const SafeArray operator= (const SafeArray&);
int& operator[] (int y);
const int operator [] (const int y); // you need this one too.
SafeArray &operator=(SafeArray rhs) {
std::swap(array, rhs.array);
std::swap(length_, rhs.length_);
}
SafeArray(SafeArray const &other);
~SafeArray();
private:
int length_;
int *array;
//int array[];
};
#endif /* SAFEARRAY_H */
SafeArray.cpp
#include "SafeArray.h"
#include <iostream>
SafeArray::SafeArray(int x) {
length_ = x;
array = new int[length];
for (int i = 0; i < length_; i++) {
array[i] = 0;
}
}
int SafeArray::length() {
return this->length_;
}
int SafeArray::boundsCheck(int y) {
}
int& SafeArray::operator[] (int y) {
return array[y];
}
SafeArray::~SafeArray() {
delete [] array;
}
SafeArray::SafeArray(SafeArray const &other) {
int *temp = new int[rhs.size_];
for (int i=0; i<rhs.size_; i++)
temp[i] = rhs.array[i];
std::swap(temp, array);
delete [] temp;
return *this;
}
Your class definition isn't valid. int array[] is an incomplete type, which must not appear as a (non-static) class member. Some compilers accept this as a synonym for int array[0], but zero-sized arrays are not valid in C++, either (only in C99).
In short, you cannot write your code the way you do. You need to learn about dynamic allocation and manage your own memory. Check out how std::vector is implemented.
In C++11, I might recommend a std::unique_ptr<int[]> array as a quick-fix approach, to be initialized as array(new int[x]).
Actually int array[] is valid, and may appear as a class member. The following compiles with strict C++11 conformance:
class foo
{
public:
foo() {}
int length;
int A[];
};
void ralph()
{
foo *bar = (foo *)new int[ 21 ];
bar->length = 20;
bar->A[0] = 1;
}
This is legal, and has its advantages (occasionally). Although it is not commonly used.
However, I suspect that the OP wanted something more along the lines of
class SafeArray {
public:
SafeArray(int); // int variable will be the array size
int length();
int boundsCheck(int y); // constructor will call this function
int& operator[] (int y);
const int operator [] (const int y) // you need this one too.
private:
int length_;
int *array;
};
along with
SafeArray::SafeArray(int x) {
length_ = x;
array = new int[length];
for (int i = 0; i < length_; i++) {
array[i] = 0;
}
}
As #Kerrek already pointed out, your class definition is clearly wrong (shouldn't compile).
To fix it, you want to change the definition to something like:
int *array;
Then in your default ctor you could use something like this:
SafeArray::SafeArray(unsigned size = 0)
: array(new int[size])
{
for (unsigned i=0; i<size; i++)
array[i] = 0;
}
Then, yes, you'll need to write an assignment operator. The usual way is called the copy and swap idiom. You create a copy, then swap the contents of the current one with those of the copy:
SafeArray &operator=(SafeArray rhs) {
std::swap(array, rhs.array);
std::swap(length_, rhs.length_);
}
Along with that, you'll need a copy constructor that makes a copy of the data as well:
SafeArray::SafeArray(SafeArray const &other) {
int *temp = new int[rhs.size_];
for (int i=0; i<rhs.size_; i++)
temp[i] = rhs.array[i];
std::swap(temp, array);
delete [] temp;
return *this;
}
Finally, you'll need a destructor to destroy an object and (particularly) delete the memory it holds:
SafeArray::~SafeArray() {
delete [] array;
}
Then realize that all of that is an ugly mess that will never really work well. In particular, the basic methodology is restricted to an array that's basically fixed in size. As long as you only store ints, it's fairly easy to overlook the problems, and make a dynamic array that (sort of) works. When/if you want to store some other type, however, you just about need to separate allocating memory from initializing objects in that memory, which means throwing away essentially all the code above, and replacing it with something that:
keeps track of the array size and allocation size separately
allocates memory with ::operator new, an Allocator object, or something else similar
uses placement new to initialize objects in the memory when needed.
uses explicit destructor calls to destroy the objects
uses ::operator delete to release memory
and so on. To summarize, std::vector is not a trivial piece of work.
The error message refers to these two lines:
int& operator[] (int y);
const int operator [] (const int y); // you need this one too.
Your error message says that (int y) and (const int y) are too similar to be two different overloads of the [] operator. You cannot overload on (int y) and (const int y) because the calls would all be ambiguous.
You probably meant to return a const int if your SafeArray is const, but return an int& if your SafeArray is not const. In that case, you declare the second function to apply to const SafeArray, by putting the word const after the parameter list. This is what you should write in SafeArray.h:
int& operator[] (int y);
const int operator [] (int y) const; // you need this one too.
You would then have to write both of these functions in SafeArray.cpp:
int& SafeArray::operator[] (int y) {
return array[y];
}
const int SafeArray::operator[] (int y) const { // you need this one too.
return array[y];
}
A few examples of what I'm referring to:
typedef struct SOME_STRUCT {
unsigned int x1;
unsigned int x2;
unsigned int x3;
unsigned int x4;
// What I expected would work, but doesn't; the 2nd parameter gets
// turned into an 8-bit quantity at some point within memset
SOME_STRUCT() { memset( this, 0xFEEDFACE, sizeof( *this ) ); }
// Something that worked, but seems hokey/hackish
SOME_STRUCT() {
unsigned int *me = (unsigned int *)this;
for( int ii = 0; ii < sizeof(*this)/sizeof(*me); ++ii ) {
me[ii] = 0xFEEDFACE;
}
}
// The far-more-verbose-but-C++-way-of-doing-it
// This works, but doesn't lend itself very well
// to being a drop-in way to pull this off on
// any struct.
SOME_STRUCT() : x1( 0xFEEDFACE )
, x2( 0XFEEDFACE )
, x3( 0XFEEDFACE )
, x4( 0XFEEDFACE ) {}
// This would work, but I figured there would be a standard
// function that would alleviate the need to do it myself
SOME_STRUCT() { my_memset( this, 0xFEEDFACE, sizeof(*this) ); }
}
I can't use valgrind here, and my options are limited as far as various debugging libraries I have access to -- which is why I'm doing it myself for this one-off case.
Here’s a partial example of using std::generate() safely:
#include <algorithm>
struct Wizard {
size_t i;
static unsigned char magic[4];
Wizard() : i(0) {}
unsigned char operator()() {
size_t j = i++;
i %= sizeof(magic); // Not strictly necessary due to wrapping.
return magic[j];
}
};
unsigned char Wizard::magic[4] = {0xDE,0xAD,0xBE,0xEF};
std::generate(reinterpret_cast<unsigned char*>(this),
reinterpret_cast<unsigned char*>(this) + sizeof(*this),
Wizard());
(Of course, the endianness may or may not be right, depending on how you’re looking and what you’re expecting to see when you do!)
I would declare this constructor:
SOME_STRUCT( unsigned int magic) : x1 (magic), x2 (magic), x3 (magic), x4 (magic) {}
This is very similar to your third option, and seems to be the natural C++ way of doing it.
A point not made by others is this:
I think it is unsafe to do this for Non-POD types. Ironically, adding the initialization into a constructor makes it non-pod. Therefore I propose a freestanding function that checks for POD-ness statically (sample uses c++0x type_traits but you could use Boost as well)
#include <iostream>
#include <type_traits>
template <typename T>
typename std::enable_if<std::is_pod<T>::value>::type* FeedFace(T& v)
{
static const unsigned char MAGIC[] = { 0xFE, 0xED, 0xFA, 0xCE };
unsigned char *me = reinterpret_cast<unsigned char *>(&v);
for( size_t ii = 0; ii < sizeof(T)/sizeof(unsigned char); ++ii )
me[ii] = MAGIC[ii % sizeof(MAGIC)/sizeof(unsigned char)];
}
struct Pod { char data[37]; };
struct NonPod : Pod { virtual ~NonPod() { } };
int main()
{
Pod pod;
FeedFace(pod);
NonPod nonpod;
// FeedFace(nonpod); // fails to compile (no matching function call)
return 0;
}
I assume this allows for nasty hacky stuff, like this:
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
int main(void)
{
struct SOME_STRUCT {
unsigned int x1;
unsigned int x2;
unsigned int x3;
unsigned int x4;
} foo;
fill(reinterpret_cast<unsigned int *>(&foo),
reinterpret_cast<unsigned int *>(&foo) + sizeof(foo) / sizeof(unsigned int),
(unsigned int)0xDEADBEEF);
cout << foo.x1 << endl;
cout << foo.x2 << endl;
cout << foo.x3 << endl;
cout << foo.x4 << endl;
return (0);
}
Basically abusing std::fill() with pointer casts.
You could reinterpret_cast this as a char* and then use std::generate with a predicate that rotates through the values you care about. If I get time later I'll try to sketch the code.
Also have you considered for example an LD_PRELOAD memory checking malloc library?
Here's another hacky method.
SOME_STRUCT() {
x1 = 0xFEEDFACE;
memmove(&(this->x2), this, sizeof(*this)-sizeof(x1));
}
Even if your memset() attempt did work, it makes an assumption about the structure packing and is therefore not guaranteed to be correct. There is no programmatic way to iterate through the members of a struct and assign them in C or C++. You will therefore need to be content with assigning the members individually. Having said that, if you feel that you are comfortable with the memory layout of the structure and don't need to worry about portable code, you can just as easily initialize it with a for loop.
unsigned int i, *ar = (unsigned int *)&my_struct;
for (i = 0; i < sizeof(my_struct) / sizeof(unsigned int); i++) {
ar[i] = 0xdeadbeef;
}