当指针指向使用malloc()获得的内存位置时,编译器如何处理CONST限定符?

Mic*_*chi 2 c malloc gcc linux-mint

我真的不知道如何提出更好的头衔,所以请耐心等待我并怜悯.

我知道的.

当我做这样的事情时:

#include <stdio.h>

int main ( void ){
    const char *arr = "Hello";

    arr[0] = 'B';
    printf( "Arr = %s\n", arr );
}
Run Code Online (Sandbox Code Playgroud)

我不会得到一个segfault因为应用那个const限定符我向编译器做了一个承诺,我不会触及arr指向的那个值.

至少在我的系统上(Linux模板18.3与GCC 7.2.0)我得到:

program.c:6:16: error: assignment of read-only location ‘*arr’
         arr[0] = 'B';
                ^
Run Code Online (Sandbox Code Playgroud)

下一个

当我做:

const char *const arr = "Hello";
Run Code Online (Sandbox Code Playgroud)

如下面的程序:

#include <stdio.h>

int main ( void ){
    const char *const arr = "Hello";

    while ( *arr != '\0' ){
        arr++;
    }
    printf( "Arr = %s\n", arr );
}
Run Code Online (Sandbox Code Playgroud)

编译器也知道我保证不会增加指针,它会看到它:

program.c:7:16: error: increment of read-only variable ‘arr’
             arr++;
                ^~
Run Code Online (Sandbox Code Playgroud)

我不明白的是.

编译器究竟如何处理这样的情况:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ( void ){
    const char *const arr = calloc( 256 * sizeof( *arr ), sizeof( *arr ) );

    strcpy ( (char*)arr , "Hello" );
    printf( "Arr = %s\n", arr );

    free ( (char*)arr );
}
Run Code Online (Sandbox Code Playgroud)

在这里,我不得不投arr的时候我打电话strcpy(),并同为free().
但是为什么编译器没有看到(忽略)这样一个事实:即使我做了一个"承诺",我也不会尝试修改该变量而忽略了const限定符?

而且,当我做以下事情时:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ( void ){
    const char *const arr;

    while ( *arr != '\0' ){
        arr++;
    }

    free ( (char*)arr );
}
Run Code Online (Sandbox Code Playgroud)

编译器看到我正在尝试增加指针:

program.c:9:16: error: increment of read-only variable ‘arr’
             arr++;
                ^~
Run Code Online (Sandbox Code Playgroud)

但忽略了这样一个事实,即我承诺不会修改该值.

malloc这里涉及的事实是否对编译器有某种意义,它需要忽略所有那些const限定符?......
或者我错过了一些重要的东西?

Eri*_*hil 7

const如果它不是const最初的,你可以从指针中删除.

calloc返回一个void *.当您将其分配给a时const char *,您可以添加const.但是C的规则允许您const临时添加并在以后删除它.您可能希望这样做,例如,当某些例程创建数据时,然后将数据提供给应该只读取数据的其他一些例程,但是,稍后,指针将被传回以释放或进一步更改,在这种情况下const必须删除.

简而言之,const对于想要遵守规则的软件来说是一种便利.当您意外尝试使用const指针编写时,它会要求编译器通知您.它必然会阻止你通过const不恰当地删除来故意违反规则.

(更准确地说一下开头的句子:C对指针转换非常灵活.只要满足对齐要求,你就可以在很大程度上转换不同类型的指针.它实际上是使用指针来访问在错误地完成时遇到麻烦的内存.)