You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GCC 11.2.0与Apple Clang 13.0.0对VLA参数const修饰的判定谁正确?

GCC与Clang对const修饰变长数组(VLA)参数的兼容性判定差异

测试代码

#include <stdio.h>

static void print_matrix(size_t rows, size_t cols, const int data[rows][cols])
{
    for (size_t r = 0; r < rows; r++)
    {
        const char *pad = "";
        for (size_t c = 0; c < cols; c++)
        {
            printf("%s%3d", pad, data[r][c]);
            pad = "  ";
        }
        putchar('\n');
    }
}

int main(void)
{
    /* Created by: gen_matrix -r 3 -c 5 -L 0 -H 999 -n matrix -E -w 3 -S 0x08C777A9 -i */
    /* Random seed: 0x08C777A9 */
    int matrix[3][5] = 
    {
        { 984, 843, 464, 599,  17, },
        { 876, 173, 647,  61, 387, },
        { 138, 245, 718, 981, 629, },
    };
    enum { MATRIX_ROWS = 3, MATRIX_COLS = 5 };

    print_matrix(MATRIX_ROWS, MATRIX_COLS, matrix);

    return 0;
}

编译用Makefile

# Makefile to demonstrate inconsistency between GCC 11.2.0 and Apple Clang 13.0.0.

CC = gcc

OFLAGS = -O3
GFLAGS = -g
WFLAG1 = -Werror
WFLAG2 = -Wall
WFLAG3 = -Wextra
WFLAG4 = -pedantic
WFLAG5 = -pedantic-errors
UFLAGS = # Set on command line

WFLAGS = ${WFLAG1} ${WFLAG2} ${WFLAG3} ${WFLAG4} ${WFLAG5}
CFLAGS = ${OFLAGS} ${GFLAGS} ${WFLAGS} ${UFLAGS}

PROG1 = gcc23
FILE.c = ${PROG1}.c

PROGRAMS = ${PROG1}

all: ${PROGRAMS}

${PROG1}:
    ${CC} ${CFLAGS} ${FILE.c} -o $@

环境中的编译器版本

$ gcc --version
gcc (GCC) 11.2.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ clang --version
Apple clang version 13.0.0 (clang-1300.0.29.30)
Target: x86_64-apple-darwin20.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
$

编译结果

$ rm -f gcc23
$ make CC=gcc 
gcc -O3 -g -Werror -Wall -Wextra -pedantic -pedantic-errors  gcc23.c -o gcc23
gcc23.c: In function ‘main’:
gcc23.c:29:44: error: pointers to arrays with different qualifiers are incompatible in ISO C [-Wpedantic]
   29 |     print_matrix(MATRIX_ROWS, MATRIX_COLS, matrix);
      |                                            ^~~~~~
make: *** [gcc23] Error 1
$ rm -f gcc23
$ make CC=clang
clang -O3 -g -Werror -Wall -Wextra -pedantic -pedantic-errors  gcc23.c -o gcc23
$ rm -f gcc23
$ make CC=clang UFLAGS=-Weverything
clang -O3 -g -Werror -Wall -Wextra -pedantic -pedantic-errors -Weverything gcc23.c -o gcc23
error: include location '/usr/local/include' is unsafe for cross-compilation [-Werror,-Wpoison-system-directories]
gcc23.c:3:73: error: variable length array used [-Werror,-Wvla]
static void print_matrix(size_t rows, size_t cols, const int data[rows][cols])
                                                                        ^~~~
gcc23.c:3:67: error: variable length array used [-Werror,-Wvla]
static void print_matrix(size_t rows, size_t cols, const int data[rows][cols])
                                                                  ^~~~
3 errors generated.
make: *** [gcc23] Error 1
$

添加-std=c99、-std=c11或-std=c18选项不改变编译错误情况;Clang启用-Weverything时的错误与const修饰无关,添加-Wno-vla后可正常编译。

核心问题与解答

哪个编译器的判定符合C语言标准?

Clang的行为符合C语言标准,GCC的报错属于过度严格的判定。

原因

  1. 参数类型调整规则:C标准规定,函数参数中的数组类型会被调整为指向数组首元素的指针。对于const int data[rows][cols](VLA参数),会被调整为const int (*data)[cols]——即指向cols个const int元素的数组的指针。
  2. 实参类型退化:主函数中的matrix是int[3][5]类型,传递给函数时会退化为int (*)[5]——指向5个int元素的数组的指针。
  3. 限定转换规则:C标准允许将非限定类型的指针转换为指向底层类型兼容的const限定类型的指针。这里int (*)[5]和const int (*)[5]的底层类型兼容,只是后者指向的数组元素被添加了const限定,属于合法的限定转换(qualification conversion),完全符合标准要求。

GCC的错误在于,它错误地将这种元素层面的const限定判定为指针指向的数组类型的限定不匹配,但实际上标准明确允许这种为元素添加const限定的转换操作。

内容的提问来源于stack exchange,提问作者Jonathan Leffler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 13:09:29