Is it possible to cast pointers to arrays in C++?
Is casting pointers to arrays in C++, problem free? and / or, is it considered to be a good practice?
If it is possible, then what is the method of casting pointers to arrays in C++? and if there are problems with doing so, then how to avoid them?
Basically I am trying to cast a part of a const char[x] to const char[y], where y <= x and the Original const char[x] can not be accessed (in order to change it's forms to std::array or anything else) and (it's content) should not be copied to another array or pointer.
But to simplify the problem, lets consider the simple case of casting a pointerconst char *pointer; to an arrayconst char array[n];. I (guess) this can be accomplished by casting the address of the pointer to address of the array by (possibly) one of the following loosely described methods:
void *voidPointer = &pointer;
static_cast<const char (*)[n]>(voidPointer);
(const char (*)[n]) &pointer;
reinterpret_cast<const char (*)[n]>(&pointer);
And then reading the content of that address.
In order to test these cases of casting a pointer to an array , I ran the following code:
const char string[] = "123";
const char *pointer = string;
const char **pointerAddress = &pointer;
typedef const char array_type[sizeof(string) / sizeof(char)];
typedef array_type *arrayPointer_type;
void *voidPointer = pointerAddress;
arrayPointer_type arrayPointer[3];
arrayPointer[0] = static_cast<arrayPointer_type>(voidPointer);
arrayPointer[1] = (arrayPointer_type) pointerAddress;
arrayPointer[2] = reinterpret_cast<arrayPointer_type>(pointerAddress);
for(const arrayPointer_type& element : arrayPointer)
{
const char *array = *element;
bool sameValue = true;
bool sameAddress = true;
for(size_t idx = (sizeof(string) / sizeof(char)) - 1; idx--;) {
std::cout << "idx[" << idx << "]" << "pointer[" << pointer[idx]<< "]" << "array[" << array[idx]<< "], ";
if(pointer[idx] != array[idx]) {
sameValue = false;
}
if(&pointer[idx] != &array[idx]) {
sameAddress = false;
}
}
std::cout << std::endl << "sameValue[" << sameValue << "]" << "sameAddress[" << sameAddress << "]" <<std::endl <<std::endl;
}
And I got the following result:
idx[2]pointer[3]array[V], idx[1]pointer[2]array[], idx[0]pointer[1]array[�],
sameValue[0]sameAddress[0]
idx[2]pointer[3]array[V], idx[1]pointer[2]array[], idx[0]pointer[1]array[�],
sameValue[0]sameAddress[0]
idx[2]pointer[3]array[V], idx[1]pointer[2]array[], idx[0]pointer[1]array[�],
sameValue[0]sameAddress[0]
Which shows that non of the casts where correct in term of keeping(not changing) the content of string!
I studied Casting pointer to Array (int* to int[2]) and Passing a char pointer to a function accepting a reference to a char array , but I was not able to find the correct way!
So is it OK to cast pointers to arrays in C++? if so What is the correct way to cast pointers to arrays without changing their contents, in C++?
Update:
The library that I am working on is going to be used only on a very low resourced embedded platform and is going to be compiled only with GCC.
The reason for casting a portion of the const char [x] to const char [y] and then passing it to another functions or methods or ... is simply conformance with my other template functions or methods or ..., which can use the extra information in order to boost the speed of a process which it's current (non-optimized) version has already failed due to lack of speed. Please also note that the types of the strings that I want to deploy are not necessarily Null-terminated.
The following method is one example of such methods:
template<size_t STRING_SIZE>
requires conceptLowSize<STRING_SIZE>
self &operator<<(const char (&string)[STRING_SIZE])
{
.
.
.
return *this;
}
I am aware of the fact that deploying template functions/methods in this way might has the overhead of program size, but in this specific case, higher speed and lower memory consumption is more preferable than lower binary size of the compiled program.
Also I tried many other speed optimization solutions including compiling with -o3 option and the speed did not observably improve.
Your variable pointer contains the address of the first character in string; while, pointerAddress is a pointer to a variable containing the address of the first character in string. Basically pointerAddress has nothing to do with string so
void *voidPointer = pointerAddress;
arrayPointer_type arrayPointer[3];
arrayPointer[0] = static_cast<arrayPointer_type>(voidPointer);
arrayPointer[1] = (arrayPointer_type) pointerAddress;
arrayPointer[2] = reinterpret_cast<arrayPointer_type>(pointerAddress);
is all wrong in that it is all casting pointerAddress which contains the address of some other variable. The address of string is the address of its first character i.e. try this
void* voidPointer = const_cast<char*>(pointer);
arrayPointer_type arrayPointer[3];
arrayPointer[0] = static_cast<arrayPointer_type>(voidPointer);
arrayPointer[1] = (arrayPointer_type)pointer;
arrayPointer[2] = reinterpret_cast<arrayPointer_type>(pointer);
Related
Not really sure what's going on here, I'm using Clion as my IDE which I don't believe has anything to do with this but I figured I'd add that information. My confusion comes from a function that I wrote
int Arry()
{
int Mynumbers [5] = {10};
std::cout << Mynumbers;
}
something simple. It should be assigning 5 integers the value of 10. But when I print out Mynumbers I am shown the memory address. Why is this happening, I thought that was what calling pointers was for. Thank you for your time.
Sincerely,
Nicholas
It is a bit complicated, and there are a few issues at play:
std::cout (actually, std::ostream, of which std::cout is an instance, does not have an overload of operator<< that understands plain arrays. It does have overloads that understand pointers.
In C++ (and C) an array name can be used as an expression in a place where a pointer is needed. When there is no better option, the array name will decay to a pointer. That is what makes the following legal: int a[10] = {}; int* p = a;.
The overload that takes a pointer prints it as a hexadecimal address, unless the pointer is of type char* or const char* (or wchar versions), in which case it treats it as a null terminated string.
This is what is happening here: because there isn't an operator<< overload that matches the array, it decays to the overload taking a pointer. And as it isn't a character type pointer, you see the hexadecimal address. You are seeing the equivalent of cout << &MyNumbers[0];.
Some notes:
void Arry() // use void if nothing is being returned
{
int Mynumbers[5] = {10}; // first element is 10, the rest are 0
//std::cout << Mynumbers; // will print the first address because the array decays to a pointer which is then printed
for (auto i : Mynumbers) // range-for takes note of the size of the array (no decay)
std::cout << i << '\t';
}
In C++, you can think of an array as a pointer to a memory address (this isn't strictly true, and others can explain the subtle differences). When you are calling cout on your array name, you are asking for it's contents: the memory address.
If you wish to see what's in the array, you can use a simple for loop:
for (int i = 0; i < 5; i++)
std::cout << Mynumbers[i] << " ";
The value of Mynumbers is in fact the adress of the first element in the array.
try the following:
for(int i=0; i<5;i++) {
cout << Mynumbers[i];
}
I have encountered charImage = (unsigned char *) new unsigned char [M*N] in some tutorials for dynamically memory allocation of the 2D charImage. M and N are the row and columns numbers of the image.
charImage is declared as an unsigned char pointer at the beginning of the program.
What does the (unsigned char *) before 'new' mean?
Can somebody explain this?
It is a cast operator which can be used to convert one type to another. In this particular case its not required since the original variable is already an unsigned char. The cast will not do anything since types already match.
it means that you are allocating M*N unsigned bytes of memory and your charImage variabile is a pointer * to such array (a pointer to unsigned chars, so an unsigned char *)
if you look closely at your .h file you'll find the charImage variable defined as:
unsigned char *charImage;
It's not required. The code is casting the returned pointer to the type of a pointer, so it's basically a no-op. If you delete it nothing bad will happen!
It is a cast to a unsigned pointer to char.
Not only is is unneeded (char[] undergoes implicit conversion to a char* in your example), it is also a C style cast which is deprecated in C++.
If you do need to perform a cast in C++ then you should use one of the following:
dynamic_cast<type>
static_cast<type>
reinterpret_cast<type>
const_cast<type>
Each performs a different role.
You can find one of many tutorials on the subject here: http://www.cplusplus.com/doc/tutorial/typecasting/
Starting with C++11 you may use the term "auto" to salve some of the burden of re-typing the types of your object ( an making errors )
constexpr auto COLUMNS = 640;
constexpr auto ROWS = 480;
unsigned char img[COLUMNS*ROWS];
// auto ptr_to_img = img; // or = &img[0]; //or see line below
auto ptr_to_img = new unsigned char[COLUMNS*ROWS];
You may also use Boost ( 1.56 ) Type Index library to tell you in most cases the type of your object
#include <boost/type_index.hpp>
using std::cout;
using boost::typeindex::type_id_with_cvr;
//...
cout << "COL type : "
<< type_id_with_cvr<decltype(COLUMNS)>().pretty_name() << '\n';
cout << "ROWS type : "
<< type_id_with_cvr<decltype(ROWS)>().pretty_name() << '\n';
cout << "Image type : "
<< type_id_with_cvr<decltype(img)>().pretty_name() << '\n';
cout << "Ptr to Image type : "
<< type_id_with_cvr<decltype(ptr_to_img)>().pretty_name() << '\n';
The result is the following
COL type : int const
ROWS type : int const
Image type : unsigned char [307200]
Ptr to Image type : unsigned char*
Final remark is as usual that playing with raw pointers is discouraged in C++ as somewhere must exist the right container that will be specialized in storing image.
That object will be more easily managed by smart pointers ( the ones that will take care of automatically recovering the memory when you get rid off your image ).
This may be valid even when having to join to pure C library ( you convert to traditionnal form only at the interfaces of the C library )
But I have no knowledge of how C++ Image library solved this issue, this could be a question for this site.
Have a look before at some C++ image library. Boost has one too ( GIL ).
I'm looking for a way to associate a char array with a string so that whenever the char array changes, the string also changes. I tried to put both char array and string variables in a union but that didn't worked as the compiler complained...
Any ideas are welcome...
class Observable_CharArray
{
char* arr;
std::function<void(char*)> change_callback;
public:
Observable_CharArray(int size, std::function<void(char*)> callback)
: arr(new char[size]), change_callback(callback){}
~Observable_CharArray()/*as mentioned by Hulk*/
{
delete[] arr;
}
void SetCallback(std::function<void(char*)> callback)
{
change_callback = callback;
}
/*other member function to give access to array*/
void change_function()
{
//change the array here
change_callback(arr);
}
};
class Observer_String
{
std::string rep;
void callback(char* cc)
{
rep = std::string(cc);
}
public:
Observer_String(Observable_CharArray* och)
{
och->SetCallback(std::bind(&callback, this, _1));
}
/*other member functions to access rep*/
};
The design can definitely be improved.
There can be other ways to solve your actual problem rather than observing char arrays.
The problem is that the std::string may change the string array inside (especially when it resizes). For instance, c_str returns the address of the current string - documentation says that "The pointer returned may be invalidated by further calls to other member functions that modify the object.".
If you're sure you won't call string methods (hence the string will stay at the same memory location), you could try accessing the c_str pointer (your char array) directly and modify its content.
std::string str = "test";
char* arr = (char*)str.c_str();
arr[3] = 'a';
NOTE: I strongly advice against this unless in a testing context.
In other words, the string class doesn't guarantee it's going to stay in the same place in memory - meaning trying to access it through a char array is impossible.
The best is to create another string class that enforces the char array to always stay the same size (and so can stay in the same memory position all the time). You could also create a bigger array (max size string for instance) to cope with any string size changes - but that should be enforced in your wrapper class.
Well you can do this, but you shouldn't
#include <iostream>
#include <string>
int main()
{
std::string test("123456789");
std::cout << test << "\n";
char* data = &test.front(); // use &(*test.begin()) for pre-C++11 code
for ( size_t i(0); i < test.size(); ++i )
{
data[i] = 57 - i;
}
std::cout << test << "\n";
}
Output will be
123456789
987654321
This however goes again everything std::string is trying to facilitate for you. If you use data, you risk causing UB and changes to test may make data point to garbage.
You should not do this!
However, there are many (dangerous) ways to achieve it:
char* cStr = const_cast<char*>(cppStr.c_str());
or
char* cStr = const_cast<char*>(cppStr.data());
or
char* cStr = &cppStr[0];
But beware that the cppStr might be reallocated whenever you touch it, hence invalidating your cStr. That would crash at some point in time, although maybe not immediately (which is even worse).
Therefore, if you are going to do this anyway. Make sure to cppStr.reserve(SOMETHING) *before* you get the cStr out of it. This way, you will at least stabilise the pointer for a while.
How can I put the address of the array into a variable?
char * str1 = "Hello";
int add = 0;
Now I want to put the address of the array into add.
I know I can print out the address of the array by the following way:
printf("Address = %p", str1);
But, I want to store the address in the variable.
If you want to store a memory address in a variable, the correct way is to type the variable as std::intptr_t or std::uintptr_t. That is because these types are guaranteed large enough to hold any memory address:
char * str1 = "Hello";
uintptr_t p = (uintptr_t)str1;
Apart from that, note that the value of str1 is already a memory address (it points to H) albeit a different one from the value of &str1 (which points to str1).
Turning a pointer into a number requires reinterpretation:
add = reinterpret_cast<int>(str1);
But there are all kinds of problems associated with this approach:
If sizeof(int) < sizeof(char*) then part of the pointer is lost, you won't be able to restore it.
Some optimizations might turn your code invalid due to unexpected aliasing.
If you need a variable which can hold pointers or integers, it would be better to use a union instead.
Use reinterpret_cast (see 5.2.10/p4):
4 A pointer can be explicitly converted to any integral type large enough to hold it. The mapping function is
implementation-defined. [ Note: It is intended to be unsurprising to those who know the addressing structure
of the underlying machine. —end note ]
static_assert( sizeof( unsigned int ) >= sizeof( &str1[ 0 ] ), "warning: use a wider type!" );
unsigned int add = reinterpret_cast< unsigned int >( &str1[ 0 ] );
From your comment on Jon's accepted answer:
char str1[] = "Hello";
char* str2 = &str1[0];
uintptr_t p = (uintptr_t)str2;
std::cout << std::hex << p << std::endl;
p = (uintptr_t)&str1[1];
std::cout << std::hex << p << std::endl;
p = (uintptr_t)&str1[0];
std::cout << std::hex << p << std::endl;
This implies your objective is to be able to stream the pointer value in a readable format. The Standard provides for this in an implementation-defined fashion as follows:
basic_ostream<charT,traits>& operator<<(const void* p);
So, perhaps what you really want is satisfied by the C++ style or (concise but less self-doncumenting and compiler-checked) C-style code below:
std::cout << static_cast<void*>(str1) << '\n';
std::cout << (void*)str1 << '\n';
(But, if you specifically want a numeric versions, or to ensure it's displayed in hex with no leading 0x or whatever else an implementation may decide upon, then you're back to Jon's suggestion or your own (possibly compile-time checked) logic to find a big enough integral type.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ deprecated conversion from string constant to 'char*'
I want to pass a string via char* to a function.
char *Type = new char[10];
Type = "Access"; // ERROR
However I get this error:
error: deprecated conversion from string constant to 'char*'
How can I fix that?
If you really want to modify Type:
char *Type = new char[10];
strcpy( Type, "Access" );
If you don't want to modify access:
const char *Type = "Access";
Please note, that, however, arrays of char in C and in C++ come with a lot of problems. For example, you don't really know if the call to new has been successful, or whether it is going to throw an exception. Also, strcpy() could surpass the limit of 10 chars.
So you can consider, if you want to modify type later:
std::string Type = "Access";
And if you don't want to modify it:
const std::string Type = "Access";
... the benefit of using std::string is that it is able to cope with all these issues.
There are a couple of things going on here.
char *Type = new char[10];
This create a char* pointer named Type and initializes it to point to the first element of a newly allocated 10-element array.
Type = "Access"; // ERROR
This assignment doesn't do what you think it does. It doesn't copy the 6-character string "Access" (7 characters including the terminating '\0') to the array you just created. Instead, it assigns a pointer to the first element of that array into your pointer Type. There are two problems with that.
First, it clobbers the previous value of Type. That 10-character array you just allocated now has nothing pointing to it; you can no longer access it or even deallocate it. This is a memory leak.
This isn't what the compiler is complaining about.
Second, a string literal creates a statically allocated const array ("statically allocated" meaning it exists for the entire execution of your program). Type is not declared with a const qualifier. If the compiler allowed you to point Type to the string "Access", you could use that pointer to (attempt to) modify it:
Type = "Access";
Type[0] = 'a'; // try to change the string to "access"
The purpose of const is to prevent you from modifying, or even attempting to modify, things that are read-only. That's why you're not allowed to assign a non-const pointer value to a const pointer object.
Since you're programming in C++, you're probably better off using std::string.
I want to pass a string via char* to a function.
Here is how you can pass a string via char* to a function (note the required const keyword in the function signature.)
#include <iostream>
void f(const char* p) {
std::cout << p << "\n";
}
int main() {
f("Access");
}
But, what if you are invoking an existing function, and cannot modify its signature?
If you have some external guarantee that the function will not write through its argument pointer,
#include <iostream>
void f(char* p) {
std::cout << p << "\n";
}
int main() {
f(const_cast<char*>("Access"));
}
If, on the other hand, the function might write to the string, then you'll need to allocate space for the string:
#include <iostream>
void f(char* p) {
*++p;
std::cout << p << "\n";
}
int main() {
// Allocate read-write space on the heap
char *p = new char[strlen("Access"+1)];
// Copy string to allocated space
strcpy(p, "Access");
f(p);
delete p;
}
or,
#include <iostream>
void f(char* p) {
*++p;
std::cout << p << "\n";
}
int main() {
// Allocate read-write space on the stack
char arr[] = "Access";
f(arr);
}
But, the best course by far is to avoid the whole pointer mishegas:
#include <iostream>
void f(const std::string& p) {
std::cout << p << "\n";
}
int main() {
f("Access");
}
You've got a basic operations problem here, not a coding issue.
When you want to change the contents of a C char array, you do not use the assignment operator. That will instead change the value of the underlying pointer. Ick.
Instead you are supposed to use the C string library routines. For instance, strcpy (Type, "Access"); will copy the string literal "Access" into your character array, with its all-important trailing nul character.
If you are using C++ (as your tags indicate), you should probably be using std::string instead of arrays of char. Assignment works they way you are expecting there.