C 指针创建常量字符串文字,为什么?
我在看一些文件,上面说 第一例C 指针创建常量字符串文字,为什么?,c,pointers,constants,C,Pointers,Constants,我在看一些文件,上面说 第一例 char * p_var="Sack"; 将创建一个常量字符串文字 因此代码类似于 p_var[1]="u"; float *p="3.14"; 将因为该属性而失败 第二种情况 char * p_var="Sack"; 还提到的是,这仅适用于字符文本,而不适用于通过指针的其他数据类型。所以代码像 p_var[1]="u"; float *p="3.14"; 将失败,导
char * p_var="Sack";
将创建一个常量字符串文字
因此代码类似于
p_var[1]="u";
float *p="3.14";
将因为该属性而失败
第二种情况
char * p_var="Sack";
还提到的是,这仅适用于字符文本,而不适用于通过指针的其他数据类型。所以代码像
p_var[1]="u";
float *p="3.14";
将失败,导致编译器错误
但是当我尝试它时,我没有发现编译器错误,尽管访问它会给我0.000000f
(在Ubuntu上使用gcc)
因此,关于上述问题,我有三个疑问:
char * p_var="Sack";
请放弃第三个问题和第二个案例。我通过添加引号来测试它
谢谢
前提是错误的:指针不创建任何字符串文本,既不是只读的,也不是可写的 创建只读字符串文字的是文字本身:
“foo”
是只读字符串文字。如果将其分配给指针,则该指针指向只读内存位置
有了这些,我们来谈谈你的问题:
为什么在第一种情况下创建的字符串文本是只读的
真正的问题是:为什么不呢?在大多数情况下,您不希望以后更改字符串文本的值,因此默认假设是有意义的。此外,还可以通过其他方式在C中创建可写字符串
为什么只允许创建字符串文本,而不允许创建其他常量(如float)
再一次,错误的假设。您可以创建其他常量:
float f = 1.23f;
这里,1.23f
文本是只读的。也可以将其指定给常量变量:
const float f = 1.23f;
为什么第二个案例没有给我编译器错误
因为编译器通常无法检查指针是指向只读内存还是指向可写内存。考虑这一点:
char* p = "Hello";
char str[] = "world"; // `str` is a writeable string!
p = &str[0];
p[1] = 'x';
在这里,p[1]='x'
是完全合法的——如果我们事先没有重新分配p
,这将是非法的。检查这一点通常不能在编译时完成
float *p="3.14";
这也是一个字符串文字
Why are string literals created in First Case read-only?
否,“sack”
和“3.14”
都是字符串文本,并且都是只读的
为什么只允许创建字符串文本,而不允许创建其他常量(如float) 如果要创建浮点常量,请执行以下操作:
const float p=3.14;
您正在使指针
p
指向字符串文字。当您取消引用p
时,它希望读取一个浮点值。因此,就编译器所见,没有什么错误。关于您的问题:
- 为什么在第一种情况下创建的字符串文本是只读的
char*p_var=“Sack”代码>
好的,p_var
被分配了分配给字符串“Sack”
的内存的起始地址p_var
内容不是只读的,因为您没有将const
关键字放在C构造中的任何位置。尽管操纵strcpy或strcat等p\u var
内容可能会导致未定义的行为
引用C ISO 9899:
声明
chars[]=“abc”,t[3]=“abc”代码>
定义纯字符数组对象s
和t
,其元素用字符串文字初始化。
此声明与:
char s[]={'a','b','c','\0'},
t[]={a',b',c'}代码>
数组的内容是可修改的。另一方面,声明:
char*p=“abc”代码>
使用指向char的类型指针定义p
,并将其初始化为指向具有长度为4的char类型数组的对象,该数组的元素由字符串文本初始化。如果试图使用p
修改数组的内容,则行为未定义
解释为什么每个平台和编译器都可以是只读的:
通常,字符串文本将放在“只读数据”部分,该部分以只读形式映射到进程空间(这就是为什么您似乎不被允许更改它)
但有些平台确实允许数据段可写
- 为什么只允许创建字符串文本,而不允许创建其他常量(如float)?第三个问题
要创建浮点常量,您应使用:
const float f=1.5f代码>
现在,当您执行以下操作时:
float*p=“3.14”代码>
您基本上是将字符串文本的地址分配给浮点指针
尝试使用-Wall-Werror-Wextra
编译。你会发现发生了什么。
它之所以有效,是因为实际上,引擎盖下的char*
和float*
之间没有区别
就好像你在写这个:
float*p=(float*)“3.14”代码>
这是一种定义良好的行为,除非float和char的内存对齐要求不同,否则会导致未定义的行为(参考:C99,6.3.2.3 p7)。我不是说不能创建其他数据类型的常量,而是说不能通过指针创建其他数据类型的常量。很抱歉,如果你是unclear@DesertIce很公平。这个问题的答案有点复杂,但简单的版本是:因为它毫无用处。为什么要这样做?只是想知道前两个问题“不能通过指针创建其他数据类型的常量”是否有与编译器/优化相关的答案