简体   繁体   中英

Initialize pointer inside struct as compile-time constant

I would like to know what the legal way of defining a constant struct that has a pointer as one of it's elements. Looking at this post ( Initializer element is not constant in C ) I can see the following:

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.

My question is if the following is well defined according to the (intersection of the C89 and C99) standard. The contents of 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

Contents of 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. */
}

Contents of main.c :

#include "test.h"

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

Compiling on Debian 11 with gcc (and -Wall -Wextra -Wpedantic -std=c89 enabled), clang (with -Weverything -std=c89 enabled), tcc (with -Wall -std=c89 enabled), and pcc (with -std=c89 enabled) produces no warnings and no errors and runs as expected. Is the code:

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

the correct way to initialize a constant struct that has a pointer as one of its member so that it is a compiler-time constant? It seems to follow the rule that it be an address constant, but I'm not sure.

As the question notes, an initializer may be an address constant.

C 2018 6.6 9 says “An address constant is a null pointer, a pointer to an lvalue designating an object of static storage duration, or a pointer to a function designator; it shall be created explicitly using the unary & operator or an integer constant cast to pointer type, or implicitly by the use of an expression of array or function type…”

In const poly my_poly = {2UL, coeffs}; , coeffs is an array of static storage duration, and it is implicitly converted to a pointer to its first element (per C 2018 6.3.2.1 3). Therefore, the result of the conversion, effectively &coeffs[0] , is an address constant and may be used as an initializer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM