array of char and pointer to char in c++ - c++

The following two programs are really confusing me. In the first program I use const char* and I can reassign the string. In the second example I use a const char[] and now I can no longer reassign the string. Could someone please explain why this is?
#include <iostream>
using namespace std;
const char* x {"one"};
void callthis(const char t[]);
int main()
{
callthis("two");
return 0;
}
void callthis(const char t[]){
t=x; // OK
// OR
// x=t; // OK
}
Second:
#include <iostream>
using namespace std;
const char x[] {"three"};
void callthis(const char* t);
int main(){
callthis("four");
return 0;
}
void callthis(const char* t){
x=t; // error: assignment of read-only variable 'x';
// error : incompatible types in assignment of
// 'const char*' to 'const char [6]'
}

An array is not a pointer. Lets cover that again: An array is not a pointer
Arrays cannot be assigned to. Once the are declared if the are not initialized at that time the only way to set the value of the array is to iterate to each element and set its contents. The const on the array is a red hearing, if we were to use
char x[] {"three"};
//...
void callthis(const char* t){
x=t;
}
We would still get an error like:
error: array type 'char [6]' is not assignable
The reason the first example works is that pointers can be assigned to and a const char * is not a constant pointer but a pointer to a constant char. Since the pointer is not const where can change what the pointer points to. If you were to use
const char * const x {"one"};
Then you have received an error along the lines of
error: cannot assign to variable 'x' with const-qualified type 'const char *const'
I also noticed you are using using namespace std; in you code. In small examples it doesn't really hurt anything but you should get into the habit of not using it. For more information on why see: Why is “using namespace std” in C++ considered bad practice?

Related

Pass non const char * in to const char *& argument of a function

I want to pass strings to a function but save the cost of
copying the pointer on the function's stack to improve performance.
I am aware of the multithreading hazards of manipulating const-ness.
One thing is to use &arr[idx] (char array) as a pointer to pass to
void func( const char*& charArrItemRef).
Compiler complains it can't bind the reference to function arg.
how can I manipulate the build to allow it?
I tried to first forcefully cast a char* to const char*, store it in a variable and then pass that variable to your func. Note that it has to be stored in a variable since you are passing the pointer as a reference. Hope this is what you were looking for:
#include <iostream>
using namespace std;
void func(const char* &charArrItemRef)
{
cout << charArrItemRef << endl;
}
int main()
{
char* a[5] = {(char*)"abc", (char*)"def", (char*)"sss", (char*)"dasds", (char*)"aad"};
const char* c = reinterpret_cast<const char*>(a[0]);
func(c);
// EDIT:
char b[10] = "abcdefghi";
const char* d = &b[3];
func(d);
return 0;
}

How do I create an array of pointers of type char C++?

I'm not very familiar with pointers, but I have an assignment that requires me to create an array of pointers of type char. I just can't seem to get the code running.
#include <iostream>
using namespace std;
int main() {
int n = 0;
char *seasons[] = { "Winter",
"Spring",
"Summer",
"Fall"};
cout << seasons[n] << endl;
return 0;
}
I copied and pasted this code from the textbook, but I keep getting errors for the strings that are in the array.
The error is E0144: a value of type "const char *" cannot be used to initialize an entity of type "char *"
I wonder if your textbook-maker did a quick-and-dirty conversion of existing C code to C++. In C, string literals are arrays of type char (even though they are immutable), but in C++ they are arrays of type const char.
The solution here is to change the type of seasons to be const char *[] to make an array of pointers to these const char arrays:
const char *seasons[] = { "Winter",
"Spring",
"Summer",
"Fall"};
As an aside, I am also not a fan of your book doing using namespace std;. It pollutes the global namespace with the entirety of the std namespace which can (and in my experience has) lead to conflicts that will break code.

unable to typecast from float* to char*

error while pointer typecasting
without typecasting the float* to char*, the code runs fine, but when I tyepcast it, it gives the error "cannot convert ‘float*’ to ‘char*’ in initialization", even though the float* and char* will be of same size, i just wanted to try it.
#include <stdio.h>
#include <iostream>
using namespace std;
int processing_block(char*,short*,short*,short*,char*,bool*,bool*);
#define monitor_w 640
#define monitor_h 480
int main()
{
short w=monitor_w/1.05, h=monitor_h/1.05;
short x=monitor_w/2, y=monitor_h/2;
float zoomer=0.5f;
bool resume = false;
bool fix1 = false;
float *pfz= &zoomer;
short *psx= &x;
pfz=(char*)pfz;
char *pcz= pfz;
psx=(char*)psx;
char *pcx= psx;
processing_block(psx,&y,&w,&h,pcz,&resume,&fix1);
cout<<"\nx-\t"<<x<<"\ny-\t"<<y<<"\nw-\t"<<w<<"\nh-\t"<<h<<"\nzoomer-\t"<<zoomer<<"\nresume-\t"<<resume<<"\nfix1-\t"<<fix1<<endl;
return 0;
}
int processing_block(short* px,short* ya,short* wa,short* ha,char* pzoom,bool* resume,bool* fix1)
{
*pzoom=0.02+(*pzoom);
if((*px)-(*ya)>25)
*resume = true;
else{
*fix1= true;
*pzoom=10.0f;
}
}
Your compiler is correct. char* is not implicitly convertible to float* and vice versa.
All data pointers can however be explicitly converted (reinterpreted) to all other data pointer types, so following would be well-formed:
char *pcz = reinterpret_cast<char*>(pfz);
Note that although reinterpretation is well formed, another matter is whether indirection through the reinterpreted pointer has well defined behaviour. If the original type and the new type are not pointer-interconvertible, then the behaviour would be undefined.
char, unsigned char, and std::byte are exceptional in that indirection through a pointer to them is well defined even if the pointer was reinterpreted from any other type as long as the pointed object exists - although, remember that behaviour is undefined if you read an indeterminate value.
Instead of:
pfz=(char*)pfz; // Does nothing, maybe give an error (assigning char* to float*)
char *pcz= pfz; // Tries to assign pfz (float*) to pcz (char*)
psx=(char*)psx; // Same
char *pcx= psx; // Same
You should do:
char *pcz= (char*) pfz;
char *pcx= (char*) psx;

Pointers and recurency - I'm trying to save memory

I'm trying to write program that create squere for string. Squere has to be larger then string.length(). If there is word 'C++' I need 2x2 array to fill it inside.
So I have written code
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
int pole(int &a,const int* l);
int main(){
string code;
cin >> code;
int wall=1;
pole(wall,code.length());
cout << wall;
system("PAUSE");
return 0;
}
int pole(int &a,const int* l){
if (a*a > l) return a;
else {
a+=1;
pole(a,l);
}
}
I bet that using pointer with recunrency save a lot of memory but I can't compile it. I'm trying to understand compilers error but is 2 hard for me ;/
Here is compiler list of errors
> in main()
11 25 Error] invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int (*)(int&, const int*)'
6 5> [Error] in passing argument 1 of 'int pole(int&, const int*)'
in pole() 17 12
>[Error] ISO C++ forbids comparison between pointer and
> integer [-fpermissive]
Here:
pole(pole, code.length());
You are passing as the second variable the result of length(), which is of type std::string::size_type, which the function pole accepts a pointer to int. Those two types are incompatible.
The second problem is that one branch of your if statement inside pole does not contain a return statement, thus giving your program Undefined Behavior.
You may want to change your function pole this way:
int pole(int &a, std::string::size_type l) {
// ^^^^^^^^^^^^^^^^^^^^^^
// Also, passing by reference is unnecessary here
if (a*a > static_cast<int>(l)) return a;
// ^^^^^^^^^^^^^^^^
// Just to communicate that you are aware of the
// signed-to-unsigned comparison here
else {
a+=1;
return pole(a,l);
// ^^^^^^
// Do not forget this, or your program will have Undefined Behavior!
}
}
Here you can see your modified program compile and run.
You are trying to use an unsigned integer (coming from std::string::length) as a pointer in:
pole(wall,code.length());
Change your pole declarations to:
int pole(int a, int l);
Saving memory on int is just nonsense there. Pointers are sometimes even more memory expensive than simple integers.
You should learn to save memory with huge objects instead.
int pole(int &a,const int* l){
if (a*a > l) return a;
else {
a+=1;
pole(a,l);
}
}
first, you cannot initialize int* l with size_t argument.
Also you do later comparison between address, not value pointed too.
Is this what you wanted?

Compilation error while passing double pointer in cpp

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
void f(char **x)
{
(*x)++;
**x = 'a';
}
int main()
{
char str[]="hello";
f(&str);
cout << str << endl;
return 0;
}
Please tell me why this program is giving compilation Error.I am using the g++ compiler
Error :temp1.cpp:16:8: error: cannot convert ‘char (*)[6]’ to ‘char**’ for
argument ‘1’ to ‘void f(char**)’
Arrays can be implicitly converted to pointers, but that doesn't mean that the implicit "pointer equivalent" already exists.
You are hoping that f(&str); will implicitly create both a pointer to str and a pointer to that pointer.
This small (working) change illustrates this point:
int main()
{
char str[]="hello";
char *pstr = str; // Now the pointer extists...
f(&pstr); // ...and can have an address
cout << str << endl;
return 0;
}
You are passing pointer of constant char to the function but in function you are taking it as pointer of pointers. That is the problem. I commented out below where the problem lies.
[Off topic but N. B. : Arrays and pointers are different concept.]
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
void f(char **x) //**x is pointer of pointer
{
(*x)++;
**x = 'a';
}
int main()
{
char str[]="hello";
f(&str); //You are passing pointer of constant char.
cout << str << endl;
return 0;
}
You're going to run into a serious problem with your function f since &str and &str[0] both evaluate to the same value ... as other posters have pointed out, these operations point to different types, but the actual pointer r-value will be the same. Thus in f when you attempt to double-dereference the char** pointer x, you're going to get a segfault even if you attempted something like a cast to massage the type differences and allow compilation to happen with errors. This is because you are never getting a pointer-to-pointer ... the fact that &str and &str[0] evaluate to the same pointer value means that a double-dereference acually attempts to use the char value in str[0] as a pointer value, which won't work.
Your problem is that you're treating arrays as pointers, when they're not. Arrays decay into pointers, and in this case, it doesn't. What you're passing in is a char (*)[6] when it expects a char **. Those are obviously not the same.
Change your parameter to char (*x)[6] (or use a template with a size parameter):
template <std::size_t N>
void f(char (*x)[N])
Once inside, you try to increment what x is pointing to. You can't increment an array, so use an actual pointer instead:
char *p = *x;
p++;
*p = 'a';
All put together, (sample)
template <std::size_t N>
void f(char(*x)[N])
{
if (N < 2) //so we don't run out of bounds
return;
char *p = *x;
p++;
*p = 'a';
}