Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 指针创建常量字符串文字,为什么?_C_Pointers_Constants - Fatal编程技术网

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很公平。这个问题的答案有点复杂,但简单的版本是:因为它毫无用处。为什么要这样做?只是想知道前两个问题“不能通过指针创建其他数据类型的常量”是否有与编译器/优化相关的答案