Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Why does assigning literal strings to mutable character arrays like
char * p = "Hello World!\n";
result in a warning while passing literal string to a function argument like
void function foo(char* p) {
//do stuff
}
int main() {
foo("Hello World!\n");
}
does not result in a warning
I come from ruby land where all of this was done for me lol its a bold new world for me thanks for helping me understand
If I compile your program, I get the warning two times which is what I expect. The pointer assignment and the direct function call with string literal gives:
warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
And actual this warnings should be treated as errors, because you are not able to change the content of what the pointer points to. If you try to modify the content in foo() you run
void foo(char* p)
{
p[0]='n';
}
results into an exception which is what we expect!
The problem is not the function foo but the init to a const array.
If you change your code to:
void foo(char* p) {
p[0]='n';
}
int main() {
char * from = "Hello World!\n";
char * to = new char[100]; // enough space to put the string here
strcpy( to, from );
foo( to );
foo( from );
cout << to << endl;
}
and run this in a debugger, your program crash in line foo( from );
What you should always do:
If your function will not modify the content of that what the pointer points to, make the pointer to a const pointer.
If your program have to modify the content of that what the pointer points to, you have to use memory which you can write on.
A simple change can do the job:
int main() {
char from[]= "Hello World!\n";
//char* from= "Hello World!\n";
foo( from );
cout << from << endl;
}
The difference here is:
from is now an array on the stack, local to your function main. And you can modify your own array inside the function foo().
My hint: if you see a warning of passing a const value to a non const pointer, treat this always as error and not only as a warning. This is only a warning while tons of old code will not compile anymore. But remember: A write access to a const value is always undefined behavior and normally a crash.
Related
In C++11:
#include <string>
#include <iostream>
const char*Inner() {
std::string content;
content = "const characters are returned.";
return content.c_str();
}
const char* Outer() {
return Inner();
}
int main(){
std::cout << "result " << Outer() <<"\n"; // <- Spot 1
return 0;
}
I am kind of understand the explanation in const char* Return Type. The string object is destroyed when the stack is gone. But I think that should happen when the Spot 1 completed execution. After that, the Inner stack is popped? But in this case, the Spot 1 is still executing but the stacks are destroyed. Could anyone explain when the stack gets destroyed?
Another question related the context is: if I change the function to
const char*Inner() {
std::string content;
content = "const characters are returned.";
const char* ptr = content.c_str()
return ptr;
}
In this case, The string content is destroyed. Is that because the return is a pointer, so the value of the pointer(address) is returned but the content the pointer pointed to is recycled?
content destructs when Inner exits, right after returning the pointer. The pointer returned by Inner is therefore a dangling pointer from the moment it's returned.
The same is true for the second version of Inner you've written here. content goes out of scope at the end of Inner, and Inner returns a dangling pointer.
So the pointer is invalid long before the cout statement finishes executing.
The function Outer here is basically irrelevant.
That said, if you run this program, you may still print out the expected value in the cout statement, because the memory that the dangling pointer points to might still contain the value it contained before. But there's no guarantee of this, and the optimizer in particular may realize that there's no way the value of content can legitimately affect anything and respond by never initializing it in the first place.
in C++, if a method is accepting left reference + pointer only,
it seems it suffices if we only have a template method with T& as its parameter, why we usually overload with test(T* ) as well ?
proof of concept: left reference method can take pointer argument.
#include <iostream>
using namespace std;
template<class T>
void test(T& arg) {
T value = arg;
cout << *value << endl;
}
int main() {
int b = 4;
int* a = &b;
test(a); // compiles and runs without issue.
return 0;
}
Why [do] we usually overload with test(T* ) as well?
I am not sure that we usually do anything of the sort, but if one were to overload for a pointer, it would be because pointers behave differently than object types. Remember, a pointer in fact is not an object but an address to an object.
The reason that test(a) compiles and runs without issue is because it is accepting a reference to a pointer to an object as its parameter. Thus, when the line cout << *value << endl; executes, the pointer is dereferenced back to an object and we see 4 printed to standard out.
As #HolyBlackCat mentioned, we usually want do different things for T& and T*.
As indicated in the example, for test(T&) we usually need to manually do dereference, this would result in the difference in the behavior, so it makes sense to have a overload like this.
If I have a code for example like this:
#include <iostream>
using namespace std;
void swap(void** a) {
int tmp = 5;
void* b = &tmp;
a = &b;
}
int main()
{
int x=11;
void* y=&x;
void** z=&y;
swap(z);
void* a = *z;
cout << *(int*)a << endl;
return 0;
}
The code above prints 11, but I want to update the value of z (its address) to point to a place so I can print 5 (I mean update it). What should I do so that when I send z to the function and get back to main I can receive 5 instead of 11.
I'm just not that good with pointers.
EDIT: I must send to swap an argument with void**
You can't update the value of a void** (i.e. what it points to) by passing it to a function that takes a void**. That only allows to modify the pointed-to memory, not what address the pointer you pass to the function points to.
To update what it points to, the parameter should be a void**& or a void***.
Regardless of what solution you choose, the code you posted is extremely error prone and a hell to maintain. You should totally avoid it.
Also, note that &tmp becomes invalid as long as you exit the function, because the local variable tmp gets destroyed.
Im new to c++ and right now going through a course.
Im coding a bulls and cows guess my word game.
I finished the code, but it didnt work the way i wanted.
It fails when i try to pass variables between two functions.
thats the code:
#include <iostream>
#include <string>
using namespace std;
void PrintIntro(); <-- the function that passes the variable
void PlayGame(); <-- the function trying to get the vriable
string PlayersGuess();
int main()
{
// Printing the Intro and Instrations of the game
PrintIntro();
// Function to play our game
PlayGame();
return 0; // exits the application
}
void PrintIntro()
{
// introduce the game
constexpr int WORD_LENGTH = 5;
cout << "Welcome to Bulls and Cows" << endl;
cout << "Can you guess the " << WORD_LENGTH << " letter word I'm thinking of?" << endl;
cout << endl;
PlayGame(WORD_LENGTH); <-- Taking the variable
return;
}
string PlayersGuess()
{
// get a guess from the player
cout << "Enter your guess: ";
string Guess = "";
getline(cin, Guess);
cout << endl;
return Guess;
}
void PlayGame(const int &passed) <-- passing through here
{
// Game Intro
for (int i = 0; i < passed; i++) <-- to here
{
// Players Guess
string Guess = PlayersGuess();
cout << "Your guess is: " << PlayersGuess() << endl;
cout << endl;
}
}
The result is a fail and it says "Function does not take 1 argument"
What is the right way to pass it?
Change the declaration :
void PlayGame()
To:
void PlayGame(const int &passed)
The declaration void PlayGame(); in the beginning does not accept parameter. Change the declaration to accept parameter of the required type. Declaration and definition must match. Hope this helps.
If you want a function to take an argument, you have to tell the compiler it takes an argument.
The function prototype declaration
void PlayGame();
tells the compiler that the PlayGame function takes no arguments, and return no value. If you then try to call it using an argument that doesn't match the declaration and you will get an error.
On the other hand, if you declare it like your definition:
void PlayGame(const int &passed);
then you tell the compiler that the function must take an argument (a reference to a constant int), and you can not call the function without argument.
If you want different behavior depending on the argument (or lack thereof) passed, then you have two solutions: Function overloading, or default arguments.
For example, you can have two different functions with the same name, but different signature (basically different arguments), so you can have e.g.
void PlayGame() { ... }
void PlayGame(int passed) { ... }
Then (with the right forward declarations) you can call it with either no arguments in which case the first function will be called, or with an integer value in which case the second function will be called.
Using default arguments you can do something like
void PlayGame(int passed = 0) { ... }
Then if you call the function with an argument that argument will be passed, if you pass it without any argument the default value (0 in my example) will be used.
Also note that I removed the constant reference part, that's not really needed for simple int values.
All of this should be clearly explained in any good book.
Signatures of functions' declaration and definition must match each other. You need to declare functions like this:
void PlayGame(const int &passed);
In your code you have two different functions with name PlayGame. In the moment when PlayGame() is called with a parameter a compiler hasn't met the appropriate function yet so it gives the error.
I coded in Borland C++ ages ago, and now I'm trying to understand the "new"(to me) C+11 (I know, we're in 2015, there's a c+14 ... but I'm working on an C++11 project)
Now I have several ways to assign a value to a string.
#include <iostream>
#include <string>
int main ()
{
std::string test1;
std::string test2;
test1 = "Hello World";
test2.assign("Hello again");
std::cout << test1 << std::endl << test2;
return 0;
}
They both work. I learned from http://www.cplusplus.com/reference/string/string/assign/ that there are another ways to use assign . But for simple string assignment, which one is better? I have to fill 100+ structs with 8 std:string each, and I'm looking for the fastest mechanism (I don't care about memory, unless there's a big difference)
Both are equally fast, but = "..." is clearer.
If you really want fast though, use assign and specify the size:
test2.assign("Hello again", sizeof("Hello again") - 1); // don't copy the null terminator!
// or
test2.assign("Hello again", 11);
That way, only one allocation is needed. (You could also .reserve() enough memory beforehand to get the same effect.)
I tried benchmarking both the ways.
static void string_assign_method(benchmark::State& state) {
std::string str;
std::string base="123456789";
// Code inside this loop is measured repeatedly
for (auto _ : state) {
str.assign(base, 9);
}
}
// Register the function as a benchmark
BENCHMARK(string_assign_method);
static void string_assign_operator(benchmark::State& state) {
std::string str;
std::string base="123456789";
// Code before the loop is not measured
for (auto _ : state) {
str = base;
}
}
BENCHMARK(string_assign_operator);
Here is the graphical comparitive solution. It seems like both the methods are equally faster. The assignment operator has better results.
Use string::assign only if a specific position from the base string has to be assigned.