将结构内部的指针初始化为编译时常量

Initialize pointer inside struct as compile-time constant

我想知道定义常量 struct 的合法方法是什么,该常量将指针作为其元素之一。 看着这个 post (Initializer element is not constant in C) 我可以看到以下内容:

6.6 Constant expressions

(7) More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following:

— an arithmetic constant expression,

— a null pointer constant,

— an address constant, or

— an address constant for an object type plus or minus an integer constant expression.

(8) An arithmetic constant expression shall have an arithmetic type and shall only have operands that are integer constants, floating constants, enumeration constants, character constants, and sizeof expressions. Cast operators in an arithmetic constant expression shall only convert arithmetic types to arithmetic types, except as part of an operand to a sizeof operator whose result is an integer constant.

我的问题是,根据(C89 和 C99 的交集)标准,是否正确定义了以下内容。 test.h的内容:

#ifndef TEST_H
#define TEST_H

typedef struct _poly {
    unsigned long int degree;
    signed long int *coeffs;
} poly;

extern const poly my_poly;
extern void print_poly(poly p);

#endif

test.c 的内容:

#include <stdio.h>
#include "test.h"

static signed long int coeffs[3] = {1L, 2L, 3L};
const poly my_poly = {2UL, coeffs};

void print_poly(poly p)
{
    /* Irrelevant mumbo-jumbo goes here. */
}

main.c 的内容:

#include "test.h"

int main(void)
{
    print_poly(my_poly);
    return 0;
}

在 Debian 11 上编译 gcc(并启用 -Wall -Wextra -Wpedantic -std=c89),clang(启用 -Weverything -std=c89),tcc-Wall -std=c89 启用)和 pcc(启用 -std=c89)不会产生警告和错误,并按预期运行。是码:

static signed long int coeffs[3] = {1L, 2L, 3L};
const poly my_poly = {2UL, coeffs};

初始化常量结构的正确方法,该常量结构将指针作为其成员之一,以便它成为编译器时常量?好像是遵循地址常量的规则,但是我不确定。

如问题所述,初始值设定项可以是地址常量。

C 2018 6.6 9 说“地址常量 是一个空指针,一个指向指定静态存储持续时间对象的左值的指针,或者一个指向函数指示符的指针;它应使用一元 & 运算符或转换为指针类型的整数常量显式创建,或通过使用数组或函数类型的表达式隐式创建……”

const poly my_poly = {2UL, coeffs};中,coeffs是一个静态存储持续时间的数组,它被隐式转换为指向其第一个元素的指针(根据C 2018 6.3.2.1 3)。因此,转换的结果实际上是 &coeffs[0],是一个地址常量,可以用作初始值设定项。