Function argument, const char **, Temp Variable - c++

I want to pass an argument to a function, which takes a const char **
#include<iostream>
using namespace std;
void testFunc(const char **test){}
string testString = "This is a test string";
int main()
{
const char *tempC = testString.c_str();
testFunc(&tempC);
return 0;
}
This code works fine, But I dont want to go through the temporary variable tempC. I want to pass testString.c_str() directly. Like the following,
int main()
{
testFunc(&testString.c_str());
return 0;
}
But, it shows error,
error C2102: '&' requires l-value
Is it possible to do it without using the temp variable.

I want to pass testString.c_str() directly.
You can't. std::string::c_str() returns a const char *. In order to make a pointer to a string, you have to put it in a variable and take its address.
That being said, I'm far more concerned about what function you're trying to pass this to. In general, a function that takes a const char ** does so for two reasons:
1: It takes an array of strings. You are passing a single string. Usually, C-style functions that take an array need a second parameter that says how many elements are in the array. I hope you're putting a 1 in there.
2: It is returning a string. In which case what you're doing is not helpful at all. You should create a const char * as a variable, initialize it to NULL, and then pass a pointer to it as the parameter. It's value will be filled in by the function.

You're going to need two temp variables to call glShaderSource, so you might as well wrap them up in one function that takes the string directly.
#include <gl.h>
#include <string>
void setShaderFromString(std::string &instr, GLuint shader)
{
const GLchar *str[1]; // room for one const GLchar *
GLint len[1]; // make this an array, for symmetry
str[0] = instr.c_str();
len[0] = instr.length();
glShaderSource(shader, 1, str, len);
}

Simply - no.
(filling up some space)

You can also do type-casting:
int main()
{
testFunc((const char **)&testString);
return 0;
}

Related

Convert to std::string and get const char * in one line

I have a number that I need to convert to a const char * (an API I'm using them requires const char * as input to many of its functions). The following works:
int num = 5;
std::string s = std::to_string(5);
const char * p = s.c_str();
as suggested by answers like those in how to convert from int to char*?, but it involves creating the seemingly unnecessary variable s, so I tried the following, but it doesn't work (p points to an empty string afterwards):
int num = 5;
const char * p = std::to_string(num).c_str();
Is there a clean way I can accomplish this? Why doesn't the second example work? The behavior is very similar to what happens if I made this obvious mistake:
const char * p;
{
std::string tempStr( "hi" );
p = tempStr.c_str( );
// p points to "hi" string.
}
// now p points to "" string.
Which makes me suspect that the issue std::to_string(num) immediately goes out of scope or something similar because it's not used to directly initialize anything.
std::string encapsulates managing dynamic memory (created with new[] and delete[]). Let's break it down.
const char * p = std::to_string(num).c_str();
Create a std::string (with a human-readable representation of num).
Get the new[]ly allocated const char* to the string.
Assign that value to p.
Destroy the std::string → delete[] the allocated const char*.
p points to... deallocated data
If you are using a pointer, the data that the pointer points to must exist throughout the lifetime of that pointer.
So, no, there is no way around this other than new[]ing a copy of the string, which you will have to explicitly delete[] later. And at that point, you've thrown the baby out with the bath and have no need to use std::string.
Create a string that lives at least as long as you want to refer to its internal data.
Just use std::string it does everything you want and everything that you would have to do manually if you don't use it.
When you need to pass a const char* to a const char* function simply use std::string::c_str() like this:
some_api_function(mystring.c_str()); // passes a const char*
What you need is a function which returns a char* which holds your value and can be used to manage its lifetime. The problematic version is broken because the char* points to memory which it does not manage.
For example:
std::unique_ptr<char[]> str(int32_t x)
{
std::unique_ptr<char[]> res(new char[12]);
snprintf(res.get(), 12, "%d", x);
return res;
}
Usestd::string everywhere and don't use const char* when not nessecary. They are basically the same thing. I use const char* only when I'm using a file-path.
Use std::string everywhere and your program should work.

return char array from function that passes parameters

I'm working with a piece of C++ code that reads lines from a txt file and then assign each line to to an array called lines. Then it calls a function that converts each element in the lines array to a char array and then return the resulted char array. This step is where I stuck. How could I return a char array from the function toChar and assign the returned array to another array so I can use it as I need? (the rest of the code should use each returned char array to write it in a pipe, this not important right now but just to clarify why I need to learn to return an array from a function)
Here is the code I'm using:
#include <fstream>
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <cstdlib>
using namespace std;
char * toChar(string line);
int main()
{
string lines[0] = "line1";
char* a = toChar(lines[0]);
return 0;
}
char * toChar(string line)
{
char a[1024];
strcpy(a, line.c_str());
return a;
}
Please note that in this code I'm trying to shrink the code so I'm assigning a simple string value to the array
when I try to compile this code, the error below appears:
warning: address of local variable 'a' returned
any help or suggestion is greatly appreciated..
First use a const & in passing the string to the function to avoid the unnecessary copying, and be able to use temporaries, e.g. toChar("I am temp");
The are the following alternatives:
(1) Return std::string
std::string toChar(std::string const & line)
{
char a[1024];
strcpy(a, line.c_str());
return a;
}
Of course it is assumed that line is smaller than 1024 chars with the null termination symbol
(2) Return an allocated array the
char * toChar(std::string const & line)
{
char * a = new char[1024];
strcpy(a, line.c_str());
return a;
}
but you will have to actually manage it and delete it later.
(3) Allocate the array and pass it to the function
void toChar(string const & line, char a[])
{
strcpy(a, line.c_str());
}
I imagine that you actually want to extract a C-string from an std::string , or some part of it. The proper way to do it is (3).
The warning is correct and practically is an error. You're declaring the char array locally so it will be deleted after going out of scope of that function and its address will be no more valid.
Since you're using c++ avoid char array and use a std::string.
If you want to access to the internal storage of your string you can call line.c_str() which returns a const char *.
Hence you won't need you function toChar that creates a local array that will go out of scope at the end of your function.
You could simply do :
int main()
{
string lines[0] = "line1";
const char* a = lines[0].c_str();
return 0;
}
But I advise you to keep manipulating std::string as they will handle string better than a simple char *.
And if you want a copy, just do it : std::string mycopy = lines[0].

Why is it wrong to pass a pointer to a function taking a pointer?

#include<iostream.h>
#include<conio.h>
void print(char *str){
cout<<str;
}
int main(){
clrscr();
char str[]="abcdef";
print(&str);
getch();
return 0;
}
Error
1. Cannot convert 'char[7]' to 'char *'
2.Type mismatch in parameter 'str' in call to print(char *)
Since the parameter list of function print consists of a pointer, then passing &str in function call should be correct
Also if I remove the '&' the program runs fine (even though the print function requires a character reference).
Since the parameter list of function print consists of a pointer, then passing &str in function call should be correct
That's not exactly true: it is not sufficient to pass just any pointer, it needs to be of the correct type. &str is a pointer to an array, while you need a pointer to a single array element.
Since arrays in C++ "decay" to pointers when you pass them to functions, all you need to do is removing the ampersand:
print(str);
if I remove the & the program runs fine (even though the print function requires a character reference)
That's right! An array name (in this case, str) is implicitly converted to a pointer, which is equal to the pointer to array's initial element. In other words, it's the same as writing
print(&str[0]);
print(&str);
is wrong since the type of &str is char (*)[7] while the expected argument type is char*.
To illustrate the difference between the two types:
char str[]="abcdef";
char (*ptr1)[7] = &str; // Take the address of the array.
char* ptr2 = str; // Use the array variable. It decays to a pointer
*ptr2 = 'A'; // OK.
*ptr1 = 'A'; // Not OK.
(*ptr1)[0] = 'A'; // OK
Just pass str directly to print() like so:
// this already provides std::cout
#include<iostream.h>
// this is unnecessary
//#include<conio.h>
// you could do this to avoid std:: everywhere:
//using namespace std;
void print(char *str){
// don't forget the namespace:
std::cout<<str;
}
int main(){
clrscr();
char str [] = "abcdef";
// no "&", just pass str
print (str);
getch();
return 0;
}
Arrays in C/C++ are just pointers to the first element of the array.
http://www.cplusplus.com/forum/articles/9/
Function print is declared as having a parameter of type char *
void print(char *str){
cout<<str;
}
Within the main it is called with an argument of type char ( * )[7] because it is this type that expression &str has.
char str[]="abcdef";
//...
print(&str);
You should call the function simply like
print( str );
In this case the array is converted to pointer to its first character and expression str has type char *
When you have an array of type T as for example
T a[10];
then the array used in expressions is converted to pointer to its first element. For example this
T *ptr = a;
is a correct declaration.
On the other hand if you are using expression &a then the correct declaration for a pointer will look like
T ( *ptr )[10] = &a;
That is in this case ptr is a pointer to an object of type T[10]
And I advice to use a more modern compiler.:)

Passing non-const char array to function as const char array is possible?

I was working with the strcmp function in C, then i saw the function as arguments gets:
strcmp(_const char *s1, const char *s2)_;
And actually i passed normal char array and it worked. Any ideas why this happening?
If you have for example the following code
char c = 'A';
char *p = &c;
const char *cp = &c;
then it means that you can change variable c using pointer p but you may not change it using pointer cp
For example
*p = 'B'; // valid assignment
*cp = 'B'; // compilation error
Thus function declaration
int strcmp(const char *s1, const char *s2);
means that inside the function the strings pointed to by s1 and s2 will not be changed.
There are two ways to use const key word to a pointer:
int my_int = 3;
const int* pt = &my_int; //prevent to modify the value that pointer pt points to
int* const ps = &my_int; //prevent to modify the value of pointer ps:
//it means the pointer is a const pointer, you can't modify the value of the pointer
//The value of the pointer ps is a memory address, so you can't change the memory address
//It means you can't reallocate the pointer(point the pointer to another variable)
int new_int = 5;
*pt = &new_int; //valid
*pt = 10; //invalid
*ps = &new_int; //invalid
*ps = 10; //valid
In strcmp function, the two arguments are pointer points to a const value, it means when you pass two char arrays or char pointers to the strcmp function, the function can use the value of those two pointers point to, but the function can't modify the value that you pass to it. That's why it works.
The const reference works in a similar way.
This worked, because passing non-const in place of const is allowed. It is the other way around that is prohibited:
char *hello = new char[20];
char *world= new char[20];
strcpy(hello, "hello");
strcpy(world, "world");
if (!strcmp(hello, world)) {
...
}
The const in the declaration is meant to tell the users of the API that the function will not modify the content of the string. In C++ this is important, because string literals are const. Without the const in the API, this call would have been prohibited:
if (!strcmp(someString, "expected")) { // <<== This would not compile without const
...
}
I think you intend to ask the mechanism of how the variable can compare the array.
if that's the case,
The pointer that has been declared in your example stores the initial address of the array's first element and
the ending point of the string can be determined by the detection null character that which in turn is the ending address of the array.
With that said the strcmp when called the pointer points to the strings or the character passed that is, the command would be assumed as follows strcmp("string1","string2");
and thus the comparison takes place as usual.
hmm i guess by this and with other examples posted around you can get a better picture for your answer.

C++ passing char array to function

I would rather just use a string, but we aren't supposed to as the teacher hates them and wants us to figure out ways to avoid them. So I looked into using a struct, but we aren't that far in the book and she hates it when I skip ahead. So I was thinking of doing this:
#include <iomanip>
#include <iostream>
#include <stdio.h>
using namespace std;
void myfunc(char& );
int main()
{
char myname[12];
cout<<"enter a name ";
cin>>myname;
cout<<"myname is "<<myname;
cout<<"myname is " << myfunc(myname);
getchar();
getchar();
return 0;
}
void myfunc(char &myname1)
{
myname1 = "Billy"
}
But this doesn't work and I don't know why.
One way is to do it like this:
void myfunc(char *myname1)
{
strcpy(myname1,"Billy");
}
You will also need to change your main to:
myfunc(myname);
cout<<"myname is " << myname;
However you have to be careful not to overflow your initial buffer.
The reason why your original code doesn't work is because you can't assign strings to char pointers. Instead you must copy the string to the char*.
This line of code is wrong:
cout<<"myname is " << myfunc(myname);
myfunc() doesn't return anything, its return type is void.
Try using:
char* myfunc(char *myname1)
{
strcpy(myname1,"Billy");
return myname;
}
Or
myfunc(myname);
cout<<"myname is " << myname;
Arrays devolve into pointers when passed as parameters.
So the simple way that you want is:
char* myfunc(char* myname1)
{
return myname1;
}
If you were going to show off you can pass the array by reference.
But if you can't read ahead you will not be able to use this.
char* myfunc(char (&myname1)[12]) // Note you can only pass arrays of size 12
{ // to this function so it is limited in use.
return myname1;
}
TO make it more useful though you could template it:
template<int SIZE>
char* myfunc(char (&myname1)[SIZE])
{
return myname1;
}
myname1 = "Billy" doesn't copy a string it copies a pointer to the constant local memory containing "Billy"
Take a look at strncpy() or memcpy()
Pass it as a char* instead of a char&. You're passing a reference to a single character instead of a pointer to a character array in this code.
Also use strncpy (google it) to set the value of tr char* once you're in the function.
void myfunc(char& ); is the problem it should take in a char * and not a char reference which is what you did.
and in the function use strcpy(char * destination, char *source);