2

我正在浏览一些文件,其中指出

第一个案例

char * p_var="Sack";     

将创建一个常量字符串文字。

因此像这样的代码

  p_var[1]="u";             

将因为该属性而失败。

第二种情况

还提到的是,这仅适用于字符文字,而不适用于通过指针的其他数据类型。所以像这样的代码

float *p="3.14"; 

将失败,导致编译器错误。

但是当我尝试它时,我没有得到编译器错误,尽管访问它给了我0.000000f(在 Ubuntu 上使用 gcc)。

因此,关于上述内容,我有三个疑问:

  1. 为什么在First Case中创建的字符串文字是只读的?

  2. 为什么只允许创建字符串文字而不允许创建其他常量,例如通过指针浮动?

3. 为什么Second Case没有给我编译器错误?

更新

请放弃第三个问题和第二个案例。我通过添加引号对其进行了测试。

谢谢

4

4 回答 4

5

前提是错误的:指针不会创建任何字符串文字,既不是只读的也不是可写的。

创建只读字符串文字的是文字本身:是只读"foo"字符串文字。如果将它分配给一个指针,那么该指针指向一个只读内存位置。

有了这个,让我们转向你的问题:

为什么在 First Case 中创建的字符串文字是只读的?

The real question is: why not? In most cases, you won’t want to change the value of a string literal later on so the default assumption makes sense. Furthermore, you can create writeable strings in C via other means.

Why are only string literals allowed to be created and not other constants like float?

Again, wrong assumption. You can create other constants:

float f = 1.23f;

Here, the 1.23f literal is read-only. You can also assign it to a constant variable:

const float f = 1.23f; 

Why is Second Case not giving me compiler errors?

Because the compiler cannot check in general whether your pointer points to read-only memory or to writeable memory. Consider this:

char* p = "Hello";
char str[] = "world"; // `str` is a writeable string!

p = &str[0];

p[1] = 'x';

Here, p[1] = 'x' is entirely legal – if we hadn’t re-assigned p beforehand, it would have been illegal. Checking this cannot be generally done at compile-time.

于 2012-11-18T14:47:40.370 回答
1

Regarding your question:

  • Why are string literals created in First Case read-only?

char *p_var="Sack";

Well, the p_var is assigned with the starting address of the memory allocated to the string "Sack". p_var content is not read-only, since you haven't put the const keyword anywhere in C constructs. Although manipulating the p_var contents like strcpy or strcat may cause undefined behavior.

Quote C ISO 9899:

The declaration
char s[] = "abc", t[3] = "abc";
defines plain char array objects s and t whose elements are initialized with character string literals.
This declaration is identical to:
char s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' };
The contents of the arrays are modifiable. On the other hand, the declaration:
char *p = "abc";
defines p with type pointer to char and initializes it to point to an object with type array of char with length 4 whose elements are initialized with a character string literal. If an attempt is made to use p to modify the contents of the array, the behavior is undefined.

An explanation of why it could be read-only per your platform and compiler:

Commonly string literals will be put in "read-only-data" section which gets mapped into the process space as read-only (which is why you seem to not being allowed to change it).

But some platforms do allow, the data segment to be writable.

  • Why are only string literals allowed to be created and not other constants like float? and the third question.

To create a float constant you should use: const float f=1.5f;

Now, when you are doing: float *p="3.14"; you are basically assigning the string literal's address to a float pointer.

Try compiling with -Wall -Werror -Wextra. You will find out what is happening. It works because, in practice, there's no difference between a char * and a float * under the hood.

Its as if you are writing this:
float *p=(float*) "3.14";

This is a well-defined behaviour, unless the memory alignment requirements of float and char differ, in which case it results in undefined behaviour (Reference: C99, 6.3.2.3 p7).

于 2012-11-18T15:05:04.813 回答
0
  1. 效率
  2. 他们是
  3. 这是一个字符串介意引号
于 2012-11-18T14:47:32.593 回答
0
float *p="3.14"; 

This is also a string literal !

  Why are string literals created in First Case read-only?

No, both "sack" and "3.14" are string literals and both are read-only.


Why are only string literals allowed to be created and not other constants like float?

If you want to create a float const then do:

const float p=3.14;

Why is Second Case not giving me compiler errors? 

You are making the pointer p point to a string literal. When you dereference p, it expects to read a float value. So there's nothing wrong as far as the compiler can see.

于 2012-11-18T14:49:19.267 回答