EDIT: (edited the question so I can be as precise as possible) I am trying to gain a fundamental understanding for what happens with the statement below. it would appear, as you can see in the comments, that programmers/software-engineers within the S.O. community are in disagreement about this.
The statement is simple, and is as follows:
char* str = "Hello world";
According to my CS Professor, in reference to the statement above, he says...
"This is dangerous (and officially deprecated in the C standard) because you haven't allocated memory for str1 to point at."
First off, I understand that it's deprecated, and that I should not use it — that is all very clear.
The problem I am having, is that I clearly do not understand how memory allocation takes place in the statement above, or maybe it would be more accurate to state, "I don't understand WHERE memory allocation is taking place". It would seem that memory from the heap is not being allocated, and the stack should work as a LIFO-conceptual type of memory, which means you wouldn't store a string inside of the stack, and this is where I get lost. If "Hello World"
is not stored on the heap, or in the stack, where does it exist? And where does the str
pointer point to, if it doesn't point to the heap? See, I am fundamentally missing something.
"I don't know how to be more clear than that."
CodePudding user response:
[Disclaimer: I wrote this answer when the question was tagged both [c] and [c ]. The answer is definitely different for C versus C . I am leaning somewhat towards C in this answer.]
char* str = "Hello world";
This is perfectly fine in C.
According to my CS Professor, in reference to the statement above, he says...
"This is dangerous (and officially deprecated in the C standard) because you haven't allocated memory for
str
to point at."
Either you misunderstood, or your professor is very badly confused.
The code is deprecated in C because you neglected to declare str
as being a pointer to unmodifiable (i.e. const
) characters. But there is nothing, absolutely nothing, wrong with the allocation of the pointed-to string.
When you write
char *str = "Hello world";
the compiler takes care of allocating memory for str
to point to.
The compiler behaves more or less exactly as if you had written
static char __hidden_string[] = "Hello world";
char *str = __hidden_string;
or maybe
static const char __hidden_string[] = "Hello world";
char *str = (char *)__hidden_string;
Now, where is that __hidden_string
array allocated? Certainly not on the stack (you'll notice it's declared static
), and certainly not on the heap, either.
Once upon a time, the __hidden_string
array was typically allocated in the "initialized data" segment, along with (most of) the rest of your global variables. That meant you could get away with modifying it, if you wanted to.
These days, some/many/most compilers allocate __hidden_string
in a nonwritable segment, perhaps even the code segment. In that case, if you try to modify the string, you'll get a bus error or the equivalent.
For backwards compatibility reasons, C compilers cannot treat a string constant as if it were of type const char []
. If they did, you'd get a warning when you wrote
char *str = "Hello world";
and to some extent that warning would be a good thing, because it would force you to write
const char *str = "Hello world";
making it explicit that str
points to a string that you're not allowed to modify.
But C did not adopt this rule, because there's too much old code it would have broken.
C , on the other hand, has or is in the process of adopting some version of this rule. When I try char *str = "Hello world";
under two different C compilers, I get warning: conversion from string literal to 'char *' is deprecated
. It's likely this is what your professor was trying to get at.
CodePudding user response:
Summary:
"any strings in double quotes"
areconst lvalue string literals
, stored somewhere in compiled program.You can't modify such string, but you can store pointer to this string (of course const) and use it without modifying:
const char *str = "some string"
For example:
int my_strcmp(const char *str1, const char *str2) { ... } int main() { ... const char *rule2_str= "rule2"; // compare some strings if (my_strcmp(my_string, "rule1") == 0) std::cout << "Execute rule1" << std::endl; else if (my_strcmp(my_string, rule2_str) == 0) std::cout << "Execute rule2" << std::endl; ... }
If you want to modify string, you can copy string literal to your own array:
char array[] = "12323"
, then your array will ititialize as string with terminate zero at the end:Actually
char array[] = "123"
is same aschar array[] = {'1', '2', '3', '\0'}
.For example:
int main() { char my_string[] = "12345"; my_string[0] = 5; // correct! std::cout << my_string << std::endl; // 52345 }
Remember that then your array will be static, so you can't change it's size, for "dynamic sized" strings use
std::string
.
CodePudding user response:
The problem is in lvalue
and rvalue
. lvalue
defines locator value and it means that it has a specified place in memory and you can easily take it. rvalue
has undefined place in memory. For example, any int a = 5
has 5
as rvalue
. So you cannot take the address of an rvalue. When you try to access the memory for char* str = "Hello World"
with something like str[0] = 'x'
you will get an error Segmentation fault
which means you tried to get unaviable memory. Btw operators *
and &
are forbidden for rvalues
, it throws compile time error, if you try to use them.
The lvalue
of "Hello World"
is stored at the programms segment of memory. But it is specified so, as the programm can't modify it directly.