I am writing a member function for a class where I would like to print out some dynamically allocated array according to the string name passed to the member function. The following code somehow get a compilation error:
error: 'tmp' was not declared in this scope
How should I do the coding? What is the problem of my code?
void backgrnd::print(const char m[]){
if (m == "interior")
int* tmp = this->interior;
else if (m == "fB")
float* tmp = this->fB;
for (int i=0;i<this->n_vox;++i)
cout << tmp[i] << ' ';
}
There are a few problems with your code.
You're passing a string by pointer (writing const char [] is quite the same as writing const char * – BTW, const is left associative and you could write it as char const * as well).
void backgrnd::print(const char m[]){
Anyway, in the next line you're comparing this pointer m with the pointer refering to the string literal constant "interior"
if (m == "interior")
And this does not what you had most likely in mind. This operation compares the values of the pointers and not the strings! The pointers would only compare as equal, if the pointer you passed to the function was that of the same string literal "interior", which is very unlikely the case. If it was just any other string, even if it also contained the character sequence interior, it would not compare equal. It would also happen if the compiler and/or linker didn't redact redundant string literals into a single pointer constant.
And of course the other pointer - string literal comparisions suffer from the same problem.
Now the next problem is, that you create a scoped pointer variable tmp, which you initialize with some instance class member pointer variable of the same type. But as soon as the scope is left that variable is no longer visible...
int* tmp = this->interior;
else if (m == "fB")
float* tmp = this->fB;
... and this for loop can no longer see it. Now this loop is problematic by itself, because it's unclear what n_vox means.
for (int i=0; i < this->n_vox; ++i)
I guess you wrote the above to save some code duplication below. The problem is: C++ is a statically typed language so the following statement can not "dynamically" type to the type of the tmp variable.
cout << tmp[i] << ' ';
}
Here are a few suggestions:
when using C++ you should use std::string instead of naked char arrays. This also makes the equality operator == do what you naively expected. If you insist on using C-style char arrays, use a string comparision function like strncmp.
Since you need to write statically typed cout<< statements anyway, move that loop into the if clauses. Use curly braces to enclose them!.
Use braces if you are new to programming.. those variables are in local scope.
if (m == "interior")
{
int* tmp = this->interior;
}
....
tmp is out of scope..
tmp variable is only in if/else scope, it's not available in for loop.
However, I suggest a better print function:
void backgrnd::print(const std::string& m)
{
if (m == "interior")
{
std::cout << *interior << std::endl;
}
else if (m == "fB")
{
std::cout <<fB << std::endl;
}
}
Related
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);
I am in a problem in which I have to write a function which will tokenize the array of characters and then return the array.... I cannnot understand how to use double pointers... The whole code is here:
#include<iostream>
using namespace std;
char** StringTokenize(char*);
int main()
{
char *string1=new char[50];
cout<<"Enter: ";
cin.getline(string1,50);
StringTokenize(&string1[0]);
return 0;
}
char** StringTokenize(char *string1)
{
int i = 0, j = 0;
char **tokenArray[50];
**tokenArray[0] = &string1[0];
while (string1[i] != '\0')
{
tokenArray[i] = string1[i];
i++;
if (string1[i] == ' ')
{
tokenArray[i] = '\n';
i++;
}
else
{
continue;
}
}
tokenArray[i] = '\0';
cout << tokenArray << endl;
return tokenArray;
}
Please help me and write this function for me... Remember that prototype of function should not change
and then return the array.
In C++, return type of a function cannot be an array.
char *string1=new char[50];
It's a bad idea to use bare owning pointers to dynamic memory. If the program compiled at all, you would be leaking memory. I recommend using std::string instead.
StringTokenize(&string1[0]);
&string1[0] is redundant. You indirect through a pointer, and then get the address of the result... which is the pointer that you indirected through.
int i = 0, j = 0;
You've declared j, but aren't using it for anything.
char **tokenArray[50];
The pointers to substrings should be pointers to char. It's unclear why your array contains pointers to pointers to char.
Note that these pointers are uninitiallised at the moment.
**tokenArray[0] = &string1[0];
**tokenArray[0] will indirect through the first uninitialised pointer and the behaviour of the program will be undefined. And the right hand side has the aforementioned redundancy.
And the types don't match. The type of left hand operand is char while the type of right hand operand is char*. This is ill-formed and meaningless. Your compiler should be telling you about bugs like this.
tokenArray[i] = string1[i];
tokenArray[i] = '\n';
tokenArray[i] = '\0';
The types don't match. The type of left hand operand is char** while the type of right hand operand is char. These are ill-formed and meaningless. Your compiler should be telling you about bugs like this.
return tokenArray;
This is wrong because
The types don't match. You're supposed to return a char**, but tokenArray is an array of char**.
Returning an automatic array would result in implicit conversion to pointer to first element (which is a char***) and the automatic array would be automatically destroyed after the function returns, so the returned pointer would be invalid.
prototype of function should not change
That's rather unfortunate since it prevents writing a well designed function. You will either have to use static storage for the array, or return an owning bare pointer to (first element of) dynamic array. Neither is a good idea.
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];
}
To fully understand how pointers, values, and references work, I am making a basic C++ program that attempts to tamper with some static and dynamic arrays and understand exactly how they should be passed in.
First I generate a static array of 3 elements. I then pass it into a function that modifies all elements. I then pass it into another function with a slightly different signature, but can also alter the array's values.
Next I generate a dynamically sized array, pass it into a function by reference so that all of the values in this dynamically sized array can be altered.
The code is as follows:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
void changeIndexStaticArrayMethod1(int* stat);
void changeIndexStaticArrayMethod2(int (&stat)[3]);
void changeIndexDynamicArrayMethod1(int* dyn, int size);
int main() {
const int MAX = 3;
int arr[MAX] = { 1,2,3 };
changeIndexStaticArrayMethod1(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
cout << endl;
changeIndexStaticArrayMethod2(arr);
cout << arr[0] << endl;
cout << arr[1] << endl;
cout << arr[2] << endl;
int SIZE;
cout << "Please choose a size for the array" << endl;
cin >> SIZE;
int *ne = new int[SIZE];
//Build array
for (int i = 0; i < SIZE; i++) {
ne[i] = i;
}
changeIndexDynamicArrayMethod1(ne, SIZE);
for (int i = 0; i < SIZE; i++) {
cout << "ne[" << i << "] = " << ne[i] << endl;
}
//To hang program
cin >> SIZE;
delete[] arr;
delete[] ne;
return 0;
}
void changeIndexStaticArrayMethod1(int* stat) {
stat[0] = 10;
stat[1] = 20;
stat[2] = 30;
}
void changeIndexStaticArrayMethod2(int (&stat)[3]) {
stat[0] = 40;
stat[1] = 50;
stat[2] = 60;
}
void changeIndexDynamicArrayMethod1(int* dyn, int size) {
for (int i = 0; i < size; i++) {
dyn[i] = i * 10;
}
}
All of the above code works how I want it to, I just have a few questions as to why (some of the methods of passing arrays by reference I have found on other SO questions).
In the changeIndexStaticArrayMethod1() and changeIndexDynamicArrayMethod1() functions, why are we able to use the dereference * operator for our array as reference? My knee jerk reaction is seeing that as practically passing the array in by values since it is the dereference operator. I know that with arrays, it is much different than using variables, but also, why will the following not work for single int variables:
void changeStaticNumber(int* num){
num = 100;
}
Obviously the above will work if we use &num and not int* num, and obviously I don't fully understand the relationship between pointers and arrays, but I cannot figure out why when we pass an array by reference, int* staticArray is ok.
Any explanation for these problems I am having would be much appreciated. Thanks.
why are we able to use the dereference * operator for our array as reference?
The * in C means many things. It can mean the unary indirection ("contents of") operator, it can mean the binary multiplication operator and it can mean a pointer declaration. The int* stat is a pointer declaration.
Since you aren't using the * to dereference the contents of the pointer inside that function, I'm not quite sure what you are asking.
When you take the array name of your array in main(), it "decays" into a pointer to the first element. So what those function do, is to take a pointer by value. If you dereference the pointer by typing *stat = something; you access the actual array in main.
Should you do something weird like changing the pointer itself, for example stat++;, then it will not affect the address used in main. You passed the pointer itself by value, so the pointer is a local copy.
My knee jerk reaction is seeing that as practically passing the array in by values since it is the dereference operator.
You can't really pass arrays by value in C or C++, without resorting to dirty tricks (storing them inside structs or classes). For example, had your function been written as void changeIndexStaticArrayMethod1(int stat[3]) it would still give you a pointer to the first element. It will not pass an array by value, as the syntax might trick you into believing.
why will the following not work for single int variables:
void changeStaticNumber(int* num){ num = 100; }
Because num is the pointer itself, not its contents. In order to write code like that, you could pass the variable by reference int& num. Behind the lines this is really the same thing as passing a pointer, just with simplified syntax.
To understand the relation between pointers and arrays better, start by reading this whole chapter: http://c-faq.com/aryptr/index.html (C and C++ are identical when it comes to pointers).
Let me see if I can take a stab at this.
Pointers are simply address holders. Once you do int * ptr = myarray; --- what you are in tern doing is storing the address of the pointer my array into ptr --- array names are actually pointers to the first memory location in the array. You can use pointer arithmetic to get at everything else for example myarray +1 will point you to the next location or myarray[1].
Passing by value is not very useful when you need to modify your array. Passing in by reference is essentially making a pointer to the array and passing that. Since arrays like vectors are contiguous blocks of memory you can index through them rather easily.
As far as your example goes void changeStaticNumber(int* num){ num = 100; } will not work because what you are attempting to do is store 100 into the pointer's address. If you deference num and make it void changeStaticNumber(int* num){ *num = 100; } it will work because you are actually going one step further and accessing the data that num is pointing to. When you use &num it is essentially the same thing - & just gives you the address of something.
For example if you want to point a pointer to an int what you would do is
int num = 5;
int *ptr = #
at this point in time ptr has the same address in num. To print out the data in num or that ptr is pointing to you need to dereference or go one step further as I like to tell myself and dereference to so cout << *ptr;
In both changeIndexStaticArrayMethod1 and changeIndexDynamicArrayMethod1 you are not passing an array there is no pass by reference (which only happens if the parameter type is a reference type -- i.e. with &). The parameter has type int * (pointer to int). You are passing a pointer to int by value. There is no "dereference operator" in either function.
ne is already an int *, so passing it is nothing special. arr is an int [3], an array, not a pointer. In C, when an array-of-T is used in a context that expects a pointer-to-T, it is implicitly converted (without you needing to do anything) to a pointer to its first element. So when you do, changeIndexStaticArrayMethod1(arr), the compiler gets a pointer to the first element of arr, and passes that to the function.
The [] operator works on pointers. a[i] is always guaranteed to be the same as *(a + i). Inside both the changeIndexStaticArrayMethod1 and changeIndexDynamicArrayMethod1 functions, [] is used to access subsequent elements using a pointer to the first element.
I wrote a simple test program in c++ but why does this crash on:
s[i] = s[i] - 'a' + 'A';
with the exception: Access violation writing location 0x01327808
#include "stdafx.h"
#include <iostream>
using namespace std;
class String
{
public:
char *s;
int len();
void upper();
String(char*);
};
String::String(char*x)
{
s = x;
}
int String::len()
{
return strlen(s);
}
void String::upper()
{
for (int i = 0; i < len(); i++)
{
if (s[i] >= 'a' && s[i] <= 'z')
{
cout << s[i] << endl;
s[i] = s[i] - 'a' + 'A';
}
}
};
int main()
{
String s("test");
s.upper();
cout << s.len() << endl;
cout << s.s << endl;
system("pause");
}
It's because of:
String s("test");
What this does is to pass the const char * "test" to your constructor which then simply stores the address of that string.
Later, when you try to modify the memory that the pointer points to, that's undefined behaviour.
Typically, string literals will be stored in read-only memory to allow certain optimisations to take place, and any attempt to modify them will result in a access violation.
If you were to change:
String s("test");
into:
char cp[] = "test";
String s(cp);
you may well find it will work.
However, your class should really be making a copy of the string for its own purposes - a mere pointer is unsafe, since the code that passed you that pointer can change the contents of it as well.
Things you should change in your code to make it safer:
s should be a private member, not a public one.
your constructor should make its own copy of the string:s = new char[strlen(x)+1];strcpy (s,x);.
add a destructor to take care of that as well:String::~String() { delete[] s; }.
consider having your constructor receive a const char * (since you're not changing it).
consider using toupper(ch) instead of ch - 'a' + 'A'. While your formula works for ASCII, I don't believe it's guaranteed by the standard.
cout stuff should be handled by the class rather then code outside of it (this will be mandatory once you make s private.
consider having a no-argument constructor so that string arrays will work okay.
String literals are constant (you're exploiting a deprecated automatic conversion to char *), and you're trying to modify one inside your class, which is undefined behavior.
In practice, the access violation happens because newer versions of VC++ put string literals in a section of the executable which is mapped in memory as read-only (which is definitely a good thing), and any attempt to write it results (correctly) in an access violation.
Solution: copy the string passed to the constructor (which, by the way, should take a const char *) in a buffer local to your class, probably dynamically allocated. In this last case, if you don't want to implement a copy constructor and an assignment operator, make them private thus avoiding that the default ones are executed, otherwise you'll get troubles (double frees and other nasty stuff) if you create copies of a String object.
Better solution: in real projects, don't reinvent the wheel and use a good pre-made string class like std::string/CString/wxString/whatever the framework you're using provides you.
String::String(char*x)
{
s = x;
}
You shouldn't copy string literals address just like above. Behavior is undefined.
you need to allocate memory and copy it.
size_t len = strlen(x);
s = new char[len+1];
strcpy(s,x);
Make sure to delete it in destructor of your String class.
You tried to assign to a string literal. They are not char*, they are const char*. Attempting to modify a string literal is undefined behaviour.
"test" is a const string, you cannot write to it.
Instead of
s = x;
try doing strcpy, so that s will have a non-const copy of x, rather than the const original.
You cannot modify "test" string by accessing with [].
The error is s[i] = something.
Infact, char* is only a pointer to an IMMUTABLE string.
In the constructor you must allocate space internally for handle "test" string literal and then you can modify single character accessing with [] operator.
Example to solve (with basic copyng):
String::String(char *original)
{
size_t len = strlen(original) + 1;
s = new char[len];
for ( size_t i = 0; i < len; ++i )
{
s[i] = original[i];
}
}