Error initializer element is not a compile time constant

When compiling this code, I get the error "initializer element is not a compile-time constant". Can anyone explain why? #import "PreferencesController.h" @implementation PreferencesController - ...

When compiling this code, I get the error «initializer element is not a compile-time constant». Can anyone explain why?

#import "PreferencesController.h"

@implementation PreferencesController

- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
    }

    return self;
}


NSImage* imageSegment = [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];//error here

jscs's user avatar

jscs

63.5k13 gold badges151 silver badges194 bronze badges

asked May 26, 2011 at 18:07

Nick's user avatar

When you define a variable outside the scope of a function, that variable’s value is actually written into your executable file. This means you can only use a constant value. Since you don’t know everything about the runtime environment at compile time (which classes are available, what is their structure, etc.), you cannot create objective c objects until runtime, with the exception of constant strings, which are given a specific structure and guaranteed to stay that way. What you should do is initialize the variable to nil and use +initialize to create your image. initialize is a class method which will be called before any other method is called on your class.

Example:

NSImage *imageSegment = nil;
+ (void)initialize {
    if(!imageSegment)
        imageSegment = [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];
}
- (id)init {
    self = [super init];
    if (self) {
        // Initialization code here.
    }

    return self;
}

answered May 26, 2011 at 18:22

ughoavgfhw's user avatar

ughoavgfhwughoavgfhw

39.6k6 gold badges100 silver badges121 bronze badges

6

A global variable has to be initialized to a constant value, like 4 or 0.0 or @"constant string" or nil. A object constructor, such as init, does not return a constant value.

If you want to have a global variable, you should initialize it to nil and then return it using a class method:

NSImage *segment = nil;

+ (NSImage *)imageSegment
{
    if (segment == nil) segment = [[NSImage alloc] initWithContentsOfFile:@"/user/asd.jpg"];
    return segment;
}

answered May 26, 2011 at 18:14

mipadi's user avatar

mipadimipadi

392k89 gold badges519 silver badges477 bronze badges

2

Because you are asking the compiler to initialize a static variable with code that is inherently dynamic.

answered May 26, 2011 at 18:14

bbum's user avatar

bbumbbum

162k23 gold badges271 silver badges359 bronze badges

The reason is that your are defining your imageSegment outside of a function in your source code (static variable).

In such cases, the initialization cannot include execution of code, like calling a function or allocation a class. Initializer must be a constant whose value is known at compile time.

You can then initialize your static variable inside of your init method (if you postpone its declaration to init).

answered May 26, 2011 at 18:15

sergio's user avatar

sergiosergio

68.7k11 gold badges101 silver badges122 bronze badges

2

You can certainly #define a macro as shown below. The compiler will replace «IMAGE_SEGMENT» with its value before compilation. While you will achieve defining a global lookup for your array, it is not the same as a global variable. When the macro is expanded, it works just like inline code and so a new image is created each time. So if you are careful in where you use the macro, then you would have effectively achieved creating a global variable.

#define IMAGE_SEGMENT [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];

Then use it where you need it as shown below. Each time the below code is executed, a new object is created with a new memory pointer.

imageSegment = IMAGE_SEGMENT

answered Jun 2, 2015 at 15:38

Kris Subramanian's user avatar

You can use the static singleton approach with dispatch_once:

#define STATIC_VAR(type, code) ^type() { 
    static type object; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
        object = code; 
    }); 
    return object; 
};

#define let __auto_type const

let imageSegment = STATIC_VAR(UIImage*, [[UIImage alloc] initWithContentsOfFile:@"image.jpg"]);
let imageRect = STATIC_VAR(CGRect, CGRectMake(0, 0, 100, 100));

// How to use:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.imageView.image = imageSegment();
    self.imageView.frame = imageRect();
}

It is thread safe, works lazily with any type and makes only a single instance.

answered Aug 12, 2021 at 10:10

iUrii's user avatar

iUriiiUrii

9,6951 gold badge28 silver badges40 bronze badges

I got this error while practicing C language, my code that I was trying to run was this

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

typedef struct
{
    char *name;
    int age;
} person;

person *p = (person *)malloc(sizeof(person));

and I realized while reading answers, that in C, I should have main function, which I forgot to use, so put the person code in main function, thus removing the error as follows

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

typedef struct
{
    char *name;
    int age;
} person;

int main()
{

    person *p = (person *)malloc(sizeof(person));
    return 0;
}

answered Mar 18, 2022 at 7:48

Akshay Vijay Jain's user avatar

I have been looking for answers but could not find anything to make this code run. I get av[1] highlighted by the compiler in the main function when declaring:

static char const *str = av[1];

Here is the code I tried to run with gcc:

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

char    *ft_strjoin(char const *s1, char const *s2);

void    fct(char **av)
{
    static char const *str = av[1];
    str = ft_strjoin(av[1], av[1]);
    printf("%sn", str);
}

int main(int ac, char **av)
{
    fct(&av[1]);
    fct(&av[1]);
    fct(&av[1]);
    fct(&av[1]);
    fct(&av[1]);
    fct(&av[1]);
}

I found this interesting but I still don’t get it and don’t know how to run this code.

Sourav Ghosh's user avatar

Sourav Ghosh

132k16 gold badges184 silver badges258 bronze badges

asked Dec 24, 2015 at 9:09

ziKmouT's user avatar

3

Quoting C11, §6.7.9, Initialization

All the expressions in an initializer for an object that has static or thread storage duration
shall be constant expressions or string literals.

In your code,

static char const *str = av[1];

av[1] is not a compile time constant value (i.e., not a constant expression). Hence the error.

You need to remove static from str to avoid the issue.

fuz's user avatar

fuz

86.7k24 gold badges193 silver badges345 bronze badges

answered Dec 24, 2015 at 9:20

Sourav Ghosh's user avatar

Sourav GhoshSourav Ghosh

132k16 gold badges184 silver badges258 bronze badges

static variables need to be initialised with a compile time constants (constant literals). av[1] will be calculated at runtime and that’s why you are getting the error message.

answered Dec 24, 2015 at 9:15

haccks's user avatar

hacckshaccks

103k25 gold badges170 silver badges260 bronze badges

You could simulate that behaviour by writing:

static const char *str;
static bool already;
if ( !already )
{
    str = av[1];
    ++already;
}

However this would be redundant compared to the solution of:

const char *str;

because you immediately overwrite that value anyway with the return value of your function.

(Also you pass the same argument in every call, so even if you used str, it still doesn’t need to be static).

answered Dec 24, 2015 at 9:34

M.M's user avatar

M.MM.M

137k21 gold badges201 silver badges349 bronze badges

lowercase

213 / 202 / 85

Регистрация: 09.05.2012

Сообщений: 494

1

23.09.2013, 18:40. Показов 12449. Ответов 36

Метки нет (Все метки)


Здравствуйте. Наткнулся(ладно, каюсь — сам написал) на вот такой код:

C
1
2
3
4
5
6
7
8
9
#include <stdio.h>
 
static const int x = 23;
static const double y = 1.0 / (double)x;
 
int main() {
    printf("x = %d, y = %lfn", x, y);
    return 0;
}

он не компилируется в связи с тем что:

Bash
1
2
3
4
gcc -O0 -g3 -Wall -c -fmessage-length=0 -o test.o ..test.c
..test.c:4:1: error: initializer element is not constant
 const double y = 1.0 / (double)x;
 ^

я несколько непонимаю почему так? ведь x — константа, а 1.0 разделить на константу — тоже константа. то есть, я какбы константу инициализирую константой, однако gcc имеет инное мнение по этому поводу. полагаю дело в static, т.к. если убрать спецификатор const, то ошибка остается. а вот так работает:

C
1
2
3
4
5
6
7
8
9
#include <stdio.h>
 
int main() {
    const int x = 23;
    const double y = 1.0 / (double)x;
 
    printf("x = %d, y = %lfn", x, y);
    return 0;
}

гугление выдает только информацию, касательно того как static, действует на область видимости переменной.



0



castaway

Эксперт С++

4978 / 3085 / 456

Регистрация: 10.11.2010

Сообщений: 11,164

Записей в блоге: 10

23.09.2013, 18:47

2

Мой GCC 4.7.3 жуёт без предупреждений и ошибок с флагом -pedantic

C++
1
2
3
4
5
6
7
8
9
#include <iostream>
 
static const int    a = 123;
static const double b = 1. / a;
 
int main()
{
    return 0;
}



0



213 / 202 / 85

Регистрация: 09.05.2012

Сообщений: 494

23.09.2013, 18:48

 [ТС]

3

я конечно обошелся и без статичности, сделав #define, однако интересно узнать почему static const не срабатывает



0



Эксперт С++

4978 / 3085 / 456

Регистрация: 10.11.2010

Сообщений: 11,164

Записей в блоге: 10

23.09.2013, 18:55

4

Тьфу блин… это ж Си..



0



213 / 202 / 85

Регистрация: 09.05.2012

Сообщений: 494

23.09.2013, 18:56

 [ТС]

5

результат на

лицо

консоль:

Миниатюры

Ошибка компиляции "initializer element is not constant"
 



0



Z3JheSBoYXQ=

342 / 237 / 83

Регистрация: 08.07.2012

Сообщений: 577

23.09.2013, 20:42

6

Потому что static дает указание компилятору резервировать сегмент памяти в течении процесса выполнения программы под переменную. Мкроподстановки к таковым не относятся.



1



213 / 202 / 85

Регистрация: 09.05.2012

Сообщений: 494

23.09.2013, 20:46

 [ТС]

7

fanatdebian, не совсем понятно. ининциализация static-переменных происходит на этапе выполнения, я правильно понял?



0



Z3JheSBoYXQ=

342 / 237 / 83

Регистрация: 08.07.2012

Сообщений: 577

23.09.2013, 20:49

8

Цитата
Сообщение от lowercase
Посмотреть сообщение

fanatdebian, таким образом инициализация static переменных происходит на этапе выполнения, я правильно понял?

ofc.



1



213 / 202 / 85

Регистрация: 09.05.2012

Сообщений: 494

23.09.2013, 20:53

 [ТС]

9

чудненько. спасибо



0



Эксперт С++

4978 / 3085 / 456

Регистрация: 10.11.2010

Сообщений: 11,164

Записей в блоге: 10

23.09.2013, 20:56

10

Да ну при чем тут static .. это всего-лишь издержки стандарта языка Си.



0



Z3JheSBoYXQ=

342 / 237 / 83

Регистрация: 08.07.2012

Сообщений: 577

24.09.2013, 00:31

11

Цитата
Сообщение от castaway
Посмотреть сообщение

Да ну при чем тут static .. это всего-лишь издержки стандарта языка Си.

В чем издержки?. Все логично и правильно на самом деле. С какой стати компилятор должен для макроподстановок резервировать память. Это всего лишь конструкция-форма, определяющая короткую запись для обработки конкретных данных размещенных в памяти.



0



Эксперт С++

4978 / 3085 / 456

Регистрация: 10.11.2010

Сообщений: 11,164

Записей в блоге: 10

24.09.2013, 00:36

12

Цитата
Сообщение от fanatdebian
Посмотреть сообщение

С какой стати компилятор должен для макроподстановок резервировать память.

Тут же нет макроопределений. Ты о чем?



0



fanatdebian

Z3JheSBoYXQ=

342 / 237 / 83

Регистрация: 08.07.2012

Сообщений: 577

24.09.2013, 08:59

13

Цитата
Сообщение от castaway
Посмотреть сообщение

Тут же нет макроопределений. Ты о чем?

Прямых нет, косвенные есть.

C
1
static const double y = 1.0 / (double)x;

Такая конструкция у компилятора вызывает диссонанс по причине отсутствия в момент прохода выделенной памяти под y для завершения остаточной конструкции / (double)x;

Не может лошадь везти телегу задом наперед.



0



Модератор

Эксперт С++

12641 / 10135 / 6102

Регистрация: 18.12.2011

Сообщений: 27,170

24.09.2013, 09:00

14

Некоторые рассуждения.
1. Глобальные переменные по определению имеют свойство static.
2. Константа, она и в Африке константа. Не могу придумать, как на нее может влиять static.



0



1259 / 650 / 44

Регистрация: 06.02.2011

Сообщений: 1,654

24.09.2013, 10:20

15

Константы (вещественные/целые числа и символы) и квалификатор типа (const/restrict/…) суть разные вещи.



0



Эксперт CАвтор FAQ

21264 / 8280 / 637

Регистрация: 30.03.2009

Сообщений: 22,635

Записей в блоге: 30

24.09.2013, 10:26

16

Цитата
Сообщение от lowercase
Посмотреть сообщение

я несколько непонимаю почему так?

Проблема в том, что в правой части присваивания находится выражение плавающего типа. Любое плавающее выражение обладает побочными эффектами в виде изменения состояния плавающих статусных регистров процессора, которые при определённых установленных масках должны вызывать аппаратное прерывание.

Другими словами, когда мы имеем динамическую инициализацию, то в процессе её вычисления может случиться прерывание и программа попадёт в обработчик прерываний. В случае статической инициализации такое сделать невозможно: компилятор не знает, взведены ли биты, отвечающие за прерывания, не знает, есть ли вообще обработчик прерывания. И может получиться так, что программа со статической и динамической инициализацией будет вести себя по разному. Поэтому запретили плавающие выражения в качестве статических инициализаторов



0



1259 / 650 / 44

Регистрация: 06.02.2011

Сообщений: 1,654

24.09.2013, 10:48

17

Цитата
Сообщение от Evg
Посмотреть сообщение

Проблема в том, что в правой части присваивания находится выражение плавающего типа

Вы о чем? как на счет int a = 1; int b = a + 1; ???



0



fanatdebian

Z3JheSBoYXQ=

342 / 237 / 83

Регистрация: 08.07.2012

Сообщений: 577

24.09.2013, 11:24

18

Цитата
Сообщение от g_u_e_s_t
Посмотреть сообщение

Вы о чем? как на счет int a = 1; int b = a + 1; ???

Тут линейное присваивание. Сложностей для компилятора не видать.
Аналогично

C
1
2
int a = 1; 
int b = a + 1;

память выделена и и известны значения по этим сегментам памяти, поэтому такое присваивание и происходит без проблем.
А когда плавающая форма-конструкция как в примере у ТС, возникают казусы.



0



1259 / 650 / 44

Регистрация: 06.02.2011

Сообщений: 1,654

24.09.2013, 11:38

19

Цитата
Сообщение от fanatdebian
Посмотреть сообщение

Тут линейное присваивание.

Забавно. Какой-то новый стандарт языка вышел? Можно ссылку на определение термина «линейное присваивание»? Причем тут память?

Цитата
Сообщение от fanatdebian
Посмотреть сообщение

поэтому такое присваивание и происходит без проблем.

покажите где такое сработает?
Впрочем, можете не отвечать. Мой вопрос был к человеку который хотя бы понимает о чем пишет.



0



Эксперт CАвтор FAQ

21264 / 8280 / 637

Регистрация: 30.03.2009

Сообщений: 22,635

Записей в блоге: 30

24.09.2013, 12:34

20

Цитата
Сообщение от Evg
Посмотреть сообщение

Проблема в том, что в правой части присваивания находится выражение плавающего типа. Любое плавающее выражение обладает побочными эффектами в виде изменения состояния плавающих статусных регистров процессора, которые при определённых установленных масках должны вызывать аппаратное прерывание.

Другими словами, когда мы имеем динамическую инициализацию, то в процессе её вычисления может случиться прерывание и программа попадёт в обработчик прерываний. В случае статической инициализации такое сделать невозможно: компилятор не знает, взведены ли биты, отвечающие за прерывания, не знает, есть ли вообще обработчик прерывания. И может получиться так, что программа со статической и динамической инициализацией будет вести себя по разному. Поэтому запретили плавающие выражения в качестве статических инициализаторов

Чота я по ходу глупость сморозил, в очередной раз невнимательно посмотрев на тест. Тут речь вообще шла о языке Си. В языке Си в качестве инициализатора может быть только константное выражение. В исходном примере в правой части использовалась переменная, а потому с точки зрения языка Си выражение не является константным (хотя в Си++ такое допустимо и будет работать). Правда в printf’е нужно использовать %f, а не %lf, но это мелочи.

Сейчас попытаюсь сообразить, к каким же случаям применяется то, чего я понаписал

Добавлено через 7 минут

Цитата
Сообщение от Evg
Посмотреть сообщение

Сейчас попытаюсь сообразить, к каким же случаям применяется то, чего я понаписал

Из всего того, что пришло в голову, ничего под это не попадает. По ходу дела я что-то с чем-то спутал. Каюсь



1



1. First, solve the problem of error reporting as shown in the title;

Take a look at the following code:

#include <stdio.h>  
int a = 1;  
int b = 2;  
int c = a+b;  
  
int main() {  
    printf("c is %dn", c);  
    return 0;  
}  

Error during compilation of GCC-O test test.c: Initializer Element is not Constant

Reason: the value of the global variable C cannot be determined at compile time; it must be determined at run time. Why is that?Because this is the standard:
C language standard: Initializers of external variables and static variables must be constant expressions [1].
So the solution:

#include <stdio.h>  
int a = 1;  
int b = 2;  
int c; 
  
int main() {  
    c = a + b; 
    printf("c is %dn", c);  
    return 0;  
}

———-
Similarly, the following code does not compile, and the error message is the same as above: [4]

char * p1 = (char *) malloc(10);  
int main(void)
{
。。。   
}

2. Do GCC and g++ compile according to the suffix name of the file?

If you change the source file name *.c to *.cc, and then compile with g++, no error will be reported. Even if you just change the file name to *.cc, the compiler will also compile with GCC, which can also compile the past. What is the reason?

————–
Principle:
GCC started out as GNU C Compiler, which is, as you know, a C Compiler. But later, as the project integrated more compilers in different languages, GCC stood for the GNU Compiler Collection, thus representing a Collection of compilers.
So instead of calling GCC when you compile your code, it’s more like a driver that calls the c compiler or the c++ compiler (g++) based on the suffix of your code. For example, if your code suffix is *.c, it will call the C compiler and linker to link to C’s library. If your code suffix is CPP, it will call the g++ compiler, and of course the library call will also use the c++ version (however, the GCC command does not automatically link to the library used by c++ programs, you must follow the parameter gcc-lstdc ++)

—————–
Here’s a piece of code:

#include <iostream>

using namespace std;

int a = 1;
int b = a;

int main()
{
cout << b << endl;

}

The Initializer Element is not constant because GCC identifies the code as C, and C specifies that initializing global variables must be a constant expression.
If $GCC test.cc, undefined reference to ‘STD ::cout’… Wait… Error: ld returned 1 exit status. Although GCC recognized c++ code at this time, it would not automatically link c++ code base, so ld link error appeared. At this point only need to manually specify and C ++ library link C: $GCC test.cc-LSTDC ++, at this point you can smoothly through the compilation link.

———————
G++ is the c++ compiler for GCC. At compile time, g++ calls GCC, so for c++ code, the two are equivalent. But since the GCC command does not automatically associate with the library used by c++ programs, it is common to use g++ for linking, so for the sake of uniformity, compile/link all use g++, giving the illusion that c++ programs can only use g++.
So you can understand it this way: you can compile with GCC /g++, and you can link with either g++ or gcc-lstdc ++. Because GCC commands do not automatically join with libraries used by C++ programs, g++ is usually used to complete the join. But at compile time, g++ automatically calls GCC, which is equivalent.
For the above code, just $g++ test.c will compile because g++ identifies *.c files as c++ files [2].

The compiler is through the program suffix name to determine the language is C or C ++. Specifically, if the suffix is.c, GCC treats it like a c program, and g++ treats it like a c++ program; CPP suffix, both are considered as c++ programs, note that although c++ is a superset of c, but the syntax requirements of the two are different [2], for c language and c++ language suffix name problem, see [7]
(3) for 1 is the C language standard, not C++, for C++, global variables and static variables do not have to follow the initialization must be constant expression such requirements, so, if the compiler to identify the above code into C++ code, then it can be successfully compiled in the past. (And the program USES the same libraries as the C language, so it’s ok not to add -LSTDC ++ parameter.

Therefore, since the suffix name of the file is changed to *.cc, I guess that whether GCC or g++, this file is identified as c++ file, so it is clear that since it is identified as c++ file, of course not to report an error.

3, compiler strong and weak symbols

In C, global variables default to 0 if they are not initialized, that is, in the global space:
int x =0; With the int x; The effect looks the same. The difference is very big, but here it is strongly recommended that you all global variables
to initialization, the main difference between them is as follows:

the compiler when compiling for both conditions can produce two kind of symbols in the symbol table of the target file, for initialization, called
symbol, an uninitialized, called weak symbols.

if the connector encounters two duplicate symbols while connecting to the target file, it will have the following processing rule:
if there are strong symbols with multiple duplicate names, it will report an error.
if there is a strong symbol and more than one weak symbol, the strong symbol shall prevail.
if there is no strong symbol, but there are more than one weak symbol with the same name, then choose any weak symbol.

————-
So here’s a piece of code:

#include<stdio.h>
int i;
i =1;
int main()
{
printf("%dn", i);
}

GCC test. C
Can be compiled, but with warning: Data Definition has no type or Storage class
What does that mean?I =1, the definition of an I variable has no type;
So the code looks like this:

#include<stdio.h>
#include<stdlib.h>
 
int i;
j=1;
 
int main()
{
printf( "%dn", j);
printf( "%dn", i);
system( "pause" );
return 0;
}

gcc test.c
This code also has warning; data definition has no type or storage class
So for I =1; The compiler takes it as the definition + initialization of a variable.
and the int I before; Because I is equal to 1; So int I is weak, it doesn’t work; [3]

However, the above two pieces of code, if using g++ compiler, that is, according to the rules of c++ compiler, will be directly error:
“J does not name a type” because c++ is a mandatory language, can not be so casual!
It is worth noting that the first paragraph of the above two code also reports an error in g++ : “I does not name a type”. It is understandable that j compilation should not pass, because j is not defined at all. Int I = 1; int I = 1; Int j = 2; int c = a+b; G++ is passable. What’s the problem?See section 4 of this article.

————–
Here’s another piece of code:

#include <stdio.h>
struct stu
{
   long number;
};

struct stu  student; 
student.number = 1;  

int main(int argc, char * argv[])
{
 printf("%dn", student.number);
}

Why is that?
The assignment statement should be placed in the function body!
Initialization can be outside the body of the function… But the assignment must be inside the body of the function…
Moreover, not only are structures assigned, but most statements (other than declarations and definitions of functions and variables) do not allow…
So understand the difference between initialization and assignment;
(This applies to C and C ++)
**** It should also be noted that in C language, struct is required when defining structural variables, while in C ++, it is not required. Stu Student = {1}; You can, but with struct you can compile it, you can run it.

4. Why is it specified that the initial values of global and static variables must be constant expressions?
Now that we’ve solved the problem, and we’ve analyzed why we did it, we can go deeper. Why do global variables and static variables have to be initialized as constant expressions?
Global (static) storage: Divided into DATA segments and BSS segments. The DATA section (global initialization section) holds initialized global and static variables; The BSS section (global uninitialized area) holds uninitialized global and static variables as well as initialized to zero global and static variables (see here). Automatic release at the end of the program. The BBS section is automatically cleared by the system before the program execution, so uninitialized global variables and static variables are already 0 before the program execution. – The program is released by the system after completion. [5]
——-
A comparison, for the statement:

int i = 3
int main()
{
    int j = i;
    ...
}

Instead of determining the value of the local variable J at compile time, the value of I is read at run time to assign to J. The compiled connected executable does not contain the value of J, only the code for the corresponding assignment statement. In contrast, since I is a global variable and is stored in static storage, its value needs to be determined at compile time. Space will be allocated in the target file to store the value of I. There will be no assignment statement to assign the value of I at run time, and there is no corresponding code.

for the statement:

int i = 3;
int j = i;

Because J is a global variable and is stored in static storage, its value also needs to be determined at compile time. I is a variable, not a constant, and the value of I cannot be determined at compile time, which means that the value of J cannot be determined at compile time, so C will report an error.
Instead, C++ simply puts j as an uninitialized global variable in the.bss area at compile time, with the default value of 0, and then adds a statement to assign j at run time, ensuring that this statement is executed before the main function begins. So the initialization of j is actually done at run time. [6]

So, we can now answer the question raised in red in section 3:
1. For int I = 1; int j = 2; int c = a+b; This sentence, in g + + through because the statement is the c at compile time as a variable declaration, because the front of the variable c has keyword int, then the compiler will be additional add a statement c = a + b, and ensure that the statement before the main function, g + + this way to make this statement to the right by compiling.
2. For int I; I = 1; G++ does not compile. The reason is that an assignment statement like I = 1, which is different from an int c = a+b, requires a value at run time; I =1 cannot be regarded as a declaration of a variable (I variable has no type in front of it),,,,,,, etc

Tip: GCC compiler plus the -v parameter, displays compile-time details, compiler version, compilation process, etc.

Read More:

Sometimes during complex programing, there are chances we make some mistakes during hurry to write and complete the program so that we can test the features, in somewhat similar occasion, we faced an error during compilation as, “error: initializer element is not constant” , now as mentioned, if we have written multiple lines during coding and before compilation, it becomes difficult to remember we initialized which variable and where..?

So, lets recreate similar error, with a very basic C program as below,

 $ vim helloerror.c 
#include <stdio.h>
#include <stdlib.h>

int *var = (int *)malloc(sizeof(int));

int main(int argc, char **argv) {
        *var = 10;
        printf("var is %dn", *var);
        return 0;
}
 $ gcc -o helloerror helloerror.c 
$ ./helloerror
helloerror.c:4:12: error: initializer element is not constant
 int *var = (int *)malloc(sizeof(int));
            ^

so, we got the mentioned error and during compilation, if the compiler is latest, it also shown the line of error.

Now, if we relooked at the code, we have a global integer pointer “var” and we are assigning a memory to it by calling malloc, ideally this looks OK, but the catch is this is a “GLOBAL” variable, outside all the functions, so the program execution only initialises these variables once, so these are expected to be constants and not changing like we have done an assigned of it to memory returned by malloc.

SO, to avoid this error, always make sure all global variables are assigned with constants.

Now, lets rewrite this program to make sure error is gone,

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

int *var = NULL;

int main(int argc, char **argv) {
        var = (int *)malloc(sizeof(int));
        *var = 10;
        printf("var is %dn", *var);
        return 0;
}

Changes are done in “int *var = NULL;” and moving malloc statement inside main.


Description


felix-gcc



2016-02-25 16:08:12 UTC

This is the code:

#define TOLOWER(x) (x&~0x20)
#define Word(s) 
  s[1] ? s[2] ? s[3] ? 
    (TOLOWER(s[0]) << 24) + (TOLOWER(s[1]) << 16) + (TOLOWER(s[2]) << 8) + TOLOWER(s[3]) : 
    (TOLOWER(s[0]) << 16) + (TOLOWER(s[1]) << 8) + TOLOWER(s[2]) : 
    (TOLOWER(s[0]) << 8) + TOLOWER(s[1]) : 
    TOLOWER(s[0])

const unsigned int _the = Word("the");



When compiling, this happens:

test.c:9:32: error: initializer element is not constant
 const unsigned int _the = Word("the");
                                ^
test.c:3:3: note: in definition of macro ‘Word’
   s[1] ? s[2] ? s[3] ? 
   ^


How is this not constant? clang thinks it is constant.


Comment 1


Marek Polacek



2016-02-25 16:13:22 UTC

(In reply to felix-gcc from comment #0)
> How is this not constant? clang thinks it is constant.

Not in C:

$ clang q.c -c
q.c:9:27: error: initializer element is not a compile-time constant


Comment 2


felix-gcc



2016-02-25 17:39:21 UTC

uh, yes in C.

$ cat test.c
#define TOLOWER(x) (x&~0x20)
#define Word(s) 
  s[1] ? s[2] ? s[3] ? 
    (TOLOWER(s[0]) << 24) + (TOLOWER(s[1]) << 16) + (TOLOWER(s[2]) << 8) + TOLOWER(s[3]) : 
    (TOLOWER(s[0]) << 16) + (TOLOWER(s[1]) << 8) + TOLOWER(s[2]) : 
    (TOLOWER(s[0]) << 8) + TOLOWER(s[1]) : 
    TOLOWER(s[0])

const unsigned int _the = Word("the");
$ clang -c test.c
$ clang --version
clang version 3.9.0 (trunk 261746)


Comment 3


Jonathan Wakely



2016-02-25 18:33:37 UTC

The C standard says it's not a constant, but clang accepts it as an extension. That doesn't make it valid C though.


Comment 4


felix-gcc



2016-02-25 18:46:29 UTC

So which part of it is not constant, you would say?

It all looks constant to me. It only operates on constants.
If 3+4 is constant, why should this not be constant?


Comment 5


Marek Polacek



2016-03-01 09:16:26 UTC

This is basically about
  char t = "f"[0];
at the file scope.  clang probably started to accept this in 3.8 or in 3.9.


Comment 6


Bernd Schmidt



2016-03-02 15:00:45 UTC

I'm also curious why this wouldn't be considered constant. I only have an old draft C standard, but I see no language forbidding this, and it can be evaluated at compile-time.

We even have a fold_read_from_constant_string, but for whatever reason it's not called when folding an ARRAY_REF.


Comment 7


Bernd Schmidt



2016-03-02 15:01:30 UTC

Cc'ing Jonathan in the hope he can answer the question.


Comment 8


Marek Polacek



2016-03-02 15:12:54 UTC

I don't think it is forbidden.  The C standard allows some latitude for constant expressions in initializers, so I think we could accept code as in Comment 5, i.e. evaluate it to an arithmetic constant expression.


Comment 9


Martin Sebor



2016-03-02 15:41:00 UTC

I also agree that accepting it would be a useful extension (perhaps when diagnosed in pedantic mode to aid portability since other compilers reject it).

As to where C11 rules it out, I believe it's in 6.6 which says that "constant expressions in initializers ... 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 a complete object type plus or minus an integer constant expression."

An /arithmetic constant expression/ shall have arithmetic type and shall only have operands that are integer constants, floating constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and _Alignof expressions.

"f"[0] is none of the above expressions.

C also says that "An implementation may accept other forms of constant expressions" so accepting it wouldn't be out of line with the requirements.


Comment 10


Jonathan Wakely



2016-03-02 15:57:06 UTC

Martin said almost exactly what I was going to say :-)

Compilers are allowed to accept this, as Clang does, but they are not required to.


Comment 11


Martin Sebor



2016-04-15 19:14:49 UTC

Seems like there is agreement that this would be a useful enhancement so I'll mark this enhancement request as accepted by changing its Status to New (and its Severity to Enhancement).


Comment 12


Martin Sebor



2016-04-15 19:20:06 UTC

*** Bug 54823 has been marked as a duplicate of this bug. ***


Comment 13


Bernd Schmidt



2016-04-15 20:46:24 UTC

I actually tried this a few weeks ago, it's slightly less trivial than it seems since you don't want to fold away the inside of &("fish"[0]).


Comment 14


Jakub Jelinek



2017-05-11 10:56:33 UTC

C++ FE's constexpr.c has bool lval argument to many recursive functions, so it can differentiate between cases where you don't want to fold "str"[0] to 's' and cases where you can do that.  It is among other cases set when processing ADDR_EXPR's operand.  But c_fully_fold_internal doesn't have anything like that, so that would need to be introduced there.


Comment 15


Jakub Jelinek



2017-05-11 11:02:11 UTC

(In reply to Jakub Jelinek from comment #14)
> C++ FE's constexpr.c has bool lval argument to many recursive functions, so
> it can differentiate between cases where you don't want to fold "str"[0] to
> 's' and cases where you can do that.  It is among other cases set when
> processing ADDR_EXPR's operand.  But c_fully_fold_internal doesn't have
> anything like that, so that would need to be introduced there.

From the related PR66618, it seems that if we had such an argument properly propagated, we could as well use decl_constant_value_for_optimization during c_fully_fold_internal (if not pedantic?) centrally for VAR_DECLs, rather then
just using it on selected operands where we basically know for sure we don't need an lvalue.

Without such changes, a hack could be to add the ARRAY_REF of STRING_CST with constant index folding into decl_constant_value_for_optimization.


Comment 16


Marek Polacek



2017-10-24 09:39:10 UTC

*** Bug 82695 has been marked as a duplicate of this bug. ***


Comment 17


Jakub Jelinek



2017-11-19 17:17:34 UTC

Author: jakub
Date: Sun Nov 19 17:17:01 2017
New Revision: 254930

URL: https://gcc.gnu.org/viewcvs?rev=254930&root=gcc&view=rev
Log:
	PR c/66618
	PR c/69960
c-family/
	* c-common.h (c_fully_fold): Add LVAL argument defaulted to false.
c/
	* c-parser.c (c_parser_omp_atomic): Pass true as LVAL to c_fully_fold
	where needed.
	* c-typeck.c (build_unary_op, build_modify_expr, build_asm_expr,
	handle_omp_array_sections): Likewise.
	(digest_init): Don't call decl_constant_value_for_optimization.
	* c-tree.h (decl_constant_value_for_optimization): Removed.
	* c-fold.c (c_fold_array_ref): New function.
	(c_fully_fold_internal): Add LVAL argument, propagate it through
	recursive calls.  For VAR_P call decl_constant_value and
	unshare if not LVAL and either optimizing or IN_INIT.  Remove
	decl_constant_value_for_optimization calls.  If IN_INIT and not LVAL,
	fold ARRAY_REF with STRING_CST and INTEGER_CST operands.
	(c_fully_fold): Add LVAL argument, pass it through to
	c_fully_fold_internal.
	(decl_constant_value_for_optimization): Removed.
cp/
	* cp-gimplify.c (c_fully_fold): Add LVAL argument, call
	cp_fold_maybe_rvalue instead of cp_fold_rvalue and pass it !LVAL.
testsuite/
	* gcc.dg/pr69960.c: New test.
	* gcc.dg/pr66618.c: New test.
	* gcc.dg/pr66618-2.c: New test.

Added:
    trunk/gcc/testsuite/gcc.dg/pr66618-2.c
    trunk/gcc/testsuite/gcc.dg/pr66618.c
    trunk/gcc/testsuite/gcc.dg/pr69960.c
Modified:
    trunk/gcc/c-family/ChangeLog
    trunk/gcc/c-family/c-common.h
    trunk/gcc/c/ChangeLog
    trunk/gcc/c/c-fold.c
    trunk/gcc/c/c-parser.c
    trunk/gcc/c/c-tree.h
    trunk/gcc/c/c-typeck.c
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/cp-gimplify.c
    trunk/gcc/testsuite/ChangeLog


Comment 18


Jakub Jelinek



2017-12-01 08:41:50 UTC

Fixed for 8.1+.

Понравилась статья? Поделить с друзьями:
  • Error initialize scatter file failed
  • Error initialize libfreshclam init failed
  • Error initialization video mode 640x480 fallout 2
  • Error init webgl failed
  • Error init render что это