28

When I wrote the following code and executed it, the compiler said

deprecated conversion from string constant to char*

int main()  
{  
  char *p;  
  p=new char[5];  
  p="how are you";  
  cout<< p;  
  return 0;  
}  

It means that I should have written const char *.

But when we pass arguments into main using char* argv[] we don't write const char* argv[].

Why?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Frustrated Coder
  • 4,417
  • 10
  • 31
  • 34
  • Ok but why is it required for char* to be constant while assigning it to a string? – Frustrated Coder Apr 27 '11 at 18:23
  • 11
    Your question is interesting, but the code leading up to it is irrelevant. Whether you're allowed to assign string literals to non-cost pointers has nothing to do with the parameter type of `main`. (Also, your code leaks memory.) – Rob Kennedy Apr 27 '11 at 18:27
  • 4
    Something else you've overlooked: *We* don't pass arguments into `main`. It's illegal to call `main` from within your program. Calling `main` is something your compiler sets up for you; you're not allowed to do it yourself. – Rob Kennedy Apr 27 '11 at 18:31
  • Also, I believe you are just wasting memory with the `new` call. The string gathers it's own memory from the stack. – Kyle Apr 27 '11 at 18:35
  • @Rob You do pass parameters to main. Just not directly. But they are the same parameters you pass to `execve` and similar functions. – Šimon Tóth Apr 27 '11 at 18:35
  • Hey thanks guys, ya we pass parameters to main from the terminal right? – Frustrated Coder Apr 27 '11 at 18:36
  • 1
    But you're not passing a `const char*`, you're passing a series of characters. Even if the platform passes the parameters to the program in read-only memory, a lot of steps happen before your program enters `main`, one of which can easily be "copy the parameters somewhere I can write to them." – Dennis Zickefoose Apr 27 '11 at 19:29
  • There's a memory leak in your example – Vanuan Feb 23 '12 at 19:49

5 Answers5

12

Because ... argv[] isn't const. And it certainly isn't a (static) string literal since it's being created at runtime.

You're declaring a char * pointer then assigning a string literal to it, which is by definition constant; the actual data is in read-only memory.

int main(int argc, char **argv)  {
    // Yes, I know I'm not checking anything - just a demo
    argv[1][0] = 'f';
    std::cout << argv[1] << std::endl;
}

Input:

g++ -o test test.cc

./test hoo

Output:

foo

This is not a comment on why you'd want to change argv, but it certainly is possible.

Community
  • 1
  • 1
Brian Roach
  • 76,169
  • 12
  • 136
  • 161
  • 4
    You would want to change `argv` if you are accepting any sensitive data as program parameters. – Šimon Tóth Apr 27 '11 at 18:43
  • 1
    @Let_Me_Be - There's any number of reasons, I just didn't feel they were relevant to the discussion which is why I said I wasn't commenting on that aspect. – Brian Roach Apr 27 '11 at 18:47
11

Historical reasons. Changing the signature of main() would break too much existing code. And it is possible that some implementations allow you to change the parameters to main from your code. However code like this:

char * p = "helllo";
* p = 'x';

is always illegal, because you are not allowed to mess with string literals like that, so the pointer should be to a const char.

  • Your reasoning for `main()` is wrong. `main()` simply can't be invoked using string constants, therefore there is no reason for the parameters to be `const`. See my answer. – Šimon Tóth Apr 27 '11 at 18:33
  • 1
    @Let_ My point (and I think what the OP was asking) is that the standard could be changed to make them const, but won't be. –  Apr 27 '11 at 18:37
  • 4
    But that's not the reason. Rewriting `argv[]` is a common technique. It is actually required if you accept any sensitive data as parameters. Therefore the reason isn't historical, it just wouldn't make any sense if you couldn't do it. – Šimon Tóth Apr 27 '11 at 18:40
  • @Let_ What I said: allow you to change the parameters to main from your code. –  Apr 27 '11 at 18:45
  • lol changing main would break literally every general purpose program ever written – MarcusJ Jul 22 '15 at 21:02
  • @Let_Me_Be Is rewriting `argv` guaranteed to prevent the original from being visible through procfs or some other mechanism? – Greg Nisbet Nov 09 '16 at 01:27
2

why is it required for char* to be constant while assigning it to a string

Because such literal strings (like "hi", "hello what's going on", etc), are stored in the read-only segment of your exe. As such, the pointers that point to them need to point to constant characters (eg, can't change them).

Xeo
  • 129,499
  • 52
  • 291
  • 397
1

You are assigning a string constant (const char*) to a pointer to a non-constant string (char *p). This would allow you to modify the string constant, e.g. by doing p[0] = 'n'.

Anyway, why don't you use std::string instead ? (you seem to be using C++).

Andre Holzner
  • 18,333
  • 6
  • 54
  • 63
1

If you look at execution functions like execve, you will see that they actually don't accept const char* as parameters, but do indeed require char*, therefore you can't use a string constant to invoke main.

Šimon Tóth
  • 35,456
  • 20
  • 106
  • 151
  • 4
    You can't invoke `main` at all. – Lightness Races in Orbit Sep 02 '11 at 15:42
  • 9
    The current [exec(3) man page for linux](http://man7.org/linux/man-pages/man3/exec.3.html) actually *has* those arguments as `const`. Which is no trouble, since the memory of the executing process is distinct from that of the executed one, so things will have to get copied in any case. – MvG Nov 14 '13 at 21:05