Error c2078 слишком много инициализаторов

error C2078: слишком много инициализаторов при создании массива C++ Решение и ответ на вопрос 785400

Фантомас

1 / 1 / 0

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

Сообщений: 18

1

13.02.2013, 13:37. Показов 7316. Ответов 4

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


Создаю текстовый массив. Выдает ошибку «error C2078: слишком много инициализаторов». При создании Int массива все нормально, а при создании екстового валит ошибку ( error C2078: слишком много инициализаторов ):

C++
1
char students[3] = {"a", "b", "c"};

Что я наделал?)

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Issues

433 / 368 / 149

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

Сообщений: 961

13.02.2013, 13:40

2

C++
1
char students[3] = {'a', 'b', 'c'};



1



1 / 1 / 0

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

Сообщений: 18

13.02.2013, 13:45

 [ТС]

3

КАК, БЛИН? О_о



0



3985 / 3255 / 909

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

Сообщений: 12,102

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

13.02.2013, 13:49

4

что не ясно?
‘a’ — это char
«a»- это char*
«aaaa» это char*



1



1 / 1 / 0

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

Сообщений: 18

13.02.2013, 16:37

 [ТС]

5

Та ясно, просто после детального изучения рнр строгий синтаксис смотрится устарашающе….



1



Добрый день! Подскажите, пожалуйста, почему не получается определить массив? Объявляю массив таким образом:

char arr[]={"a", "b"};

Получаю такую ошибку:

error C2078: too many initializers

Suvitruf - Andrei Apanasik's user avatar

задан 1 апр 2013 в 18:50

Golden's user avatar

Ошибка в том, что вы пытаетесь инициализировать элементы массива char[], которые имеют тип char, строковыми литералами «a» и «b», каждый из которых имеет тип char[]. Правильно для инициализации использовать символьные литералы:

char arr[] = {'a', 'b'};

На всякий случай, cледует заметить, что arr не будет являться валидной C-строкой, т.к. строка должна оканчиваться нулем. Поэтому если вы хотите получить строку, то следует добавить нулевой символ в конец:

char arr[] = {'a', 'b', ''};

или коротко:

char arr[] = "ab";

ответ дан 1 апр 2013 в 19:09

dzhioev's user avatar

dzhioevdzhioev

11.6k23 серебряных знака38 бронзовых знаков

0

Доброго времени суток! Определитесь с тем, что хотите получить:
Массив символов:

char arr[] = { 'a', 'b' }; // кавычки одинарные!

Или массив строк:

char *arr[] = { "a", "b" }; // кавычки двойные!

ответ дан 1 апр 2013 в 19:03

progzdeveloper's user avatar

progzdeveloperprogzdeveloper

1,3338 серебряных знаков15 бронзовых знаков

0

description title ms.date f1_keywords helpviewer_keywords ms.assetid

Learn more about: Compiler Error C2078

Compiler Error C2078

11/04/2016

C2078

C2078

9bead850-4123-46cf-a634-5c77ba974b2b

Compiler Error C2078

too many initializers

The number of initializers exceeds the number of objects to be initialized.

The compiler can deduce the correct assignment of initializers to objects and inner objects when inner braces are elided from the initializer list. Complete bracing also eliminates ambiguity and results in correct assignment. Partial bracing can cause C2078 because of ambiguity in the assignment of initializers to objects.

The following sample generates C2078 and shows how to fix it:

// C2078.cpp
// Compile by using: cl /c /W4 C2078.cpp
struct S {
   struct {
      int x, y;
   } z[2];
};

int main() {
   int d[2] = {1, 2, 3};   // C2078
   int e[2] = {1, 2};      // OK

   char a[] = {"a", "b"};  // C2078
   char *b[] = {"a", "b"}; // OK
   char c[] = {'a', 'b'};  // OK

   S s1{1, 2, 3, 4};       // OK
   S s2{{1, 2}, {3, 4}};   // C2078
   S s3{{1, 2, 3, 4}};     // OK
   S s4{{{1, 2}, {3, 4}}}; // OK
}
description title ms.date f1_keywords helpviewer_keywords ms.assetid

Learn more about: Compiler Error C2078

Compiler Error C2078

11/04/2016

C2078

C2078

9bead850-4123-46cf-a634-5c77ba974b2b

Compiler Error C2078

too many initializers

The number of initializers exceeds the number of objects to be initialized.

The compiler can deduce the correct assignment of initializers to objects and inner objects when inner braces are elided from the initializer list. Complete bracing also eliminates ambiguity and results in correct assignment. Partial bracing can cause C2078 because of ambiguity in the assignment of initializers to objects.

The following sample generates C2078 and shows how to fix it:

// C2078.cpp
// Compile by using: cl /c /W4 C2078.cpp
struct S {
   struct {
      int x, y;
   } z[2];
};

int main() {
   int d[2] = {1, 2, 3};   // C2078
   int e[2] = {1, 2};      // OK

   char a[] = {"a", "b"};  // C2078
   char *b[] = {"a", "b"}; // OK
   char c[] = {'a', 'b'};  // OK

   S s1{1, 2, 3, 4};       // OK
   S s2{{1, 2}, {3, 4}};   // C2078
   S s3{{1, 2, 3, 4}};     // OK
   S s4{{{1, 2}, {3, 4}}}; // OK
}

Почему этот код не работает? Моя IDE — это Visual Studio 2013.

#include <stdio.h>
float tempatureGuide(float F, float C);
#define FREEZING_PT 32.0f
#define SCALE_FACTOR (5.0f/9.0f)
int main(void)
{
float fahrenheit = 0.0;
float celsius = 0.0 ;
int convertTemp;
printf ("Enter 0 to calculate Celsius or 1 to calculate Fahrenheit:            ");
scanf ("%d", &convertTemp);

if (convertTemp == 0)
{
// compute Celsius
printf("Enter Fahrenheit temperture: ");
scanf("%f", &fahrenheit);
celsius = ((fahrenheit - FREEZING_PT) * SCALE_FACTOR);
printf("Fahrenheit = %f  and Celsius = %fn", fahrenheit, celsius);
float tempatureGuide(fahrenheit, celsius);  // Error here
}
else
{
// compute fahrenheit
printf("Enter the temperature in degrees fahrenheitnn");
scanf("%f", &fahrenheit);
celsius = (SCALE_FACTOR)* (fahrenheit - FREEZING_PT);
printf("The converted temperature is %f", celsius);
float tempatureGuide(fahrenheit, celsius);    // and here

}
return (0);
}

float tempatureGuide(float F, float C){
if (F < 32 || C < 0)
printf("It is freezing!");
else if (F <= 60 || C <= 16)
printf("It is cold");
else if (F >= 70 || C >= 21)
printf("It is just right");
else if (F >= 82 || C >= 28)
printf("It is warm");
else if (F > 95 || C > 35)
printf("It is hot");
else
printf("Please enter a number!");
return (0);
}

Цель состоит в том, чтобы добавить к проекту преобразования температуры, который я делал ранее, и добавить if else Функция заявления к нему, что комментирует темп. Я получаю ошибку

Error   3   error C2078: too many initializes

на обеих линиях, где я вызываю свою функцию. Я искал ответ, но не мог найти.

0

Решение

Эта строка выглядит как попытка инициализации C ++ float с одним слишком много аргументов (следовательно, «слишком много инициализаторов«ошибка), а не как вызов функции.

float tempatureGuide(fahrenheit, celsius);

Предположительно, вы хотите вызвать функцию и сохранить результат в переменной:

float temp = tempatureGuide(fahrenheit, celsius);

Или просто вызовите функцию и проигнорируйте возвращаемое значение:

tempatureGuide(fahrenheit, celsius);

Тем более что ваша функция всегда возвращает 0Таким образом, можно задаться вопросом о необходимости не пустого типа возврата.

3

Другие решения

Вам нужно вызвать функцию

float tempatureGuide(float fahrenheit, float celsius) { //...}

как

float retval = tempatureGuide(fahrenheit, celsius);

или хотя бы

tempatureGuide(fahrenheit, celsius);  // not need to use return value

Только.

1

Это просто простая ошибка. Пожалуйста, измените 2 строки кода, где вы вызываете tempatureGuide (по Фаренгейту, Цельсию); функционировать следующим образом.

float tempatureGuide(fahrenheit, celsius); --> float ret = tempatureGuide(fahrenheit, celsius);

Я протестировал то же самое в моем VS2013, так как вы используете то же самое с упомянутыми изменениями. Я могу скомпилировать и запустить его успешно. Смотрите вложение.
введите описание изображения здесь

0

The extra braces are needed because std::array is an aggregate and POD, unlike other containers in the standard library. std::array doesn’t have a user-defined constructor. Its first data member is an array of size N (which you pass as a template argument), and this member is directly initialized with an initializer. The extra braces are needed for the internal array which is being directly initialized.

The situation is same as:

//define this aggregate - no user-defined constructor
struct Aarray
{
   A data[2];  //data is an internal array
};

How would you initialize this? If you do this:

Aarray a1 =
{
   {0, 0.1},
   {2, 3.4}
};

it gives a compilation error:

error: too many initializers for ‘Aarray’

This is the same error which you get in the case of a std::array (if you use GCC).

So the correct thing to do is to use braces as follows:

Aarray a1 =
{
  {  //<--this tells the compiler that initialization of `data` starts

        { //<-- initialization of `data[0]` starts

           0, 0.1

        }, //<-- initialization of `data[0]` ends

       {2, 3.4}  //initialization of data[1] starts and ends, as above

  } //<--this tells the compiler that initialization of `data` ends
};

which compiles fine. Once again, the extra braces are needed because you’re initializing the internal array.

Now the question is why are extra braces not needed in case of double?

It is because double is not an aggregate, while A is. In other words, std::array<double, 2> is an aggregate of aggregate, while std::array<A, 2> is an aggregate of aggregate of aggregate1.

1. I think that extra braces are still needed in the case of double also (like this), to be completely conformant to the Standard, but the code works without them. It seems I need to dig through the spec again!.

More on braces and extra braces

I dug through the spec. This section (§8.5.1/11 from C++11) is interesting and applies to this case:

In a declaration of the form

T x = { a };

braces can be elided in an initializer-list as follows. If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the members of a subaggregate; it is erroneous for there to be more initializer-clauses than members. If, however, the initializer-list for a subaggregate
does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the members of the subaggregate; any remaining initializer-clauses are left to initialize the next member of the aggregate of which the current subaggregate is a member. [ Example:

float y[4][3] = {
{ 1, 3, 5 },
{ 2, 4, 6 },
{ 3, 5, 7 },
};

is a completely-braced initialization: 1, 3, and 5 initialize the first row of the array y[0], namely y[0][0], y[0][1], and y[0][2]. Likewise the next two lines initialize y[1] and y[2]. The initializer ends early and therefore y[3]s elements are initialized as if explicitly initialized with an expression of the form float(), that is, are initialized with 0.0. In the following example, braces in the initializer-list are elided; however the initializer-list has the same effect as the completely-braced initializer-list of the above example,

float y[4][3] = {
1, 3, 5, 2, 4, 6, 3, 5, 7
};

The initializer for y begins with a left brace, but the one for y[0] does not, therefore three elements from the list are used. Likewise the next three are taken successively for y[1] and y[2]. —end example ]

Based on what I understood from the above quote, I can say that the following should be allowed:

//OKAY. Braces are completely elided for the inner-aggregate
std::array<A, 2> X =   
{
  0, 0.1,
  2, 3.4
};

//OKAY. Completely-braced initialization
std::array<A, 2> Y = 
{{
   {0, 0.1},
   {2, 3.4}
}};

In the first one, braces for the inner-aggregate are completely elided, while the second has fully-braced initialization. In your case (the case of double), the initialization uses the first approach (braces are completely elided for the inner aggregate).

But this should be disallowed:

//ILL-FORMED : neither braces-elided, nor fully-braced
std::array<A, 2> Z = 
{
  {0, 0.1},
  {2, 3.4}
};

It is neither braces-elided, nor are there enough braces to be completely-braced initialization. Therefore, it is ill-formed.

The extra braces are needed because std::array is an aggregate and POD, unlike other containers in the standard library. std::array doesn’t have a user-defined constructor. Its first data member is an array of size N (which you pass as a template argument), and this member is directly initialized with an initializer. The extra braces are needed for the internal array which is being directly initialized.

The situation is same as:

//define this aggregate - no user-defined constructor
struct Aarray
{
   A data[2];  //data is an internal array
};

How would you initialize this? If you do this:

Aarray a1 =
{
   {0, 0.1},
   {2, 3.4}
};

it gives a compilation error:

error: too many initializers for ‘Aarray’

This is the same error which you get in the case of a std::array (if you use GCC).

So the correct thing to do is to use braces as follows:

Aarray a1 =
{
  {  //<--this tells the compiler that initialization of `data` starts

        { //<-- initialization of `data[0]` starts

           0, 0.1

        }, //<-- initialization of `data[0]` ends

       {2, 3.4}  //initialization of data[1] starts and ends, as above

  } //<--this tells the compiler that initialization of `data` ends
};

which compiles fine. Once again, the extra braces are needed because you’re initializing the internal array.

Now the question is why are extra braces not needed in case of double?

It is because double is not an aggregate, while A is. In other words, std::array<double, 2> is an aggregate of aggregate, while std::array<A, 2> is an aggregate of aggregate of aggregate1.

1. I think that extra braces are still needed in the case of double also (like this), to be completely conformant to the Standard, but the code works without them. It seems I need to dig through the spec again!.

More on braces and extra braces

I dug through the spec. This section (§8.5.1/11 from C++11) is interesting and applies to this case:

In a declaration of the form

T x = { a };

braces can be elided in an initializer-list as follows. If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the members of a subaggregate; it is erroneous for there to be more initializer-clauses than members. If, however, the initializer-list for a subaggregate
does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the members of the subaggregate; any remaining initializer-clauses are left to initialize the next member of the aggregate of which the current subaggregate is a member. [ Example:

float y[4][3] = {
{ 1, 3, 5 },
{ 2, 4, 6 },
{ 3, 5, 7 },
};

is a completely-braced initialization: 1, 3, and 5 initialize the first row of the array y[0], namely y[0][0], y[0][1], and y[0][2]. Likewise the next two lines initialize y[1] and y[2]. The initializer ends early and therefore y[3]s elements are initialized as if explicitly initialized with an expression of the form float(), that is, are initialized with 0.0. In the following example, braces in the initializer-list are elided; however the initializer-list has the same effect as the completely-braced initializer-list of the above example,

float y[4][3] = {
1, 3, 5, 2, 4, 6, 3, 5, 7
};

The initializer for y begins with a left brace, but the one for y[0] does not, therefore three elements from the list are used. Likewise the next three are taken successively for y[1] and y[2]. —end example ]

Based on what I understood from the above quote, I can say that the following should be allowed:

//OKAY. Braces are completely elided for the inner-aggregate
std::array<A, 2> X =   
{
  0, 0.1,
  2, 3.4
};

//OKAY. Completely-braced initialization
std::array<A, 2> Y = 
{{
   {0, 0.1},
   {2, 3.4}
}};

In the first one, braces for the inner-aggregate are completely elided, while the second has fully-braced initialization. In your case (the case of double), the initialization uses the first approach (braces are completely elided for the inner aggregate).

But this should be disallowed:

//ILL-FORMED : neither braces-elided, nor fully-braced
std::array<A, 2> Z = 
{
  {0, 0.1},
  {2, 3.4}
};

It is neither braces-elided, nor are there enough braces to be completely-braced initialization. Therefore, it is ill-formed.


Форум программистов Vingrad

Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы
Создание опроса
> error C2078: слишком много инициализаторов, Выдает ошибку, помогите исправить 

:(

   

Опции темы

olegarh
Дата 20.11.2010, 15:28 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Шустрый
*

Профиль
Группа: Участник
Сообщений: 50
Регистрация: 6.2.2010

Репутация: нет
Всего: нет

Добрый день, есть функция которая находит 1 максимальный элемент в массиве и выводит его индекс 

Код

int mymax(int *arrmax, int p){
    int max = arrmax [0];
    int indx;
    for (int i=1; i<p; ++i)
        if (max<arrmax[i]){
            max = arrmax[i];
            indx=i;
        }
    return indx;
}

функция вызывается из main.cpp

Код

#include <iostream>
using namespace std;
int main(){
    int n;
    cin>>n;
    int *arr;
    arr = new int[n];
    for (int i=0; i<n; ++i)
        cin>>arr[i];
    int mymax (*arr, n);
    return 0;
}

при компиляции выдает ошибку: error C2078: слишком много инициализаторов
как исправить?

Это сообщение отредактировал(а) olegarh — 20.11.2010, 15:36

PM MAIL   Вверх
SVN74
Дата 20.11.2010, 15:42 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Опытный
**

Профиль
Группа: Участник
Сообщений: 739
Регистрация: 5.5.2008
Где: Комсомольск на Дн епре

Репутация: 1
Всего: 18

Код

#include <iostream>
using namespace std;

      int mymax (*arr, n);
int main()
{
    int n;
    cin>>n;
    int *arr;
    arr = new int[n];
    for (int i=0; i<n; ++i)
        cin>>arr[i];
    cout << mymax (arr, n);
    delete arr;
    return 0;
}

Это сообщение отредактировал(а) SVN74 — 20.11.2010, 15:43

PM MAIL WWW   Вверх
sQu1rr
Дата 20.11.2010, 15:43 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Опытный
**

Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: 3
Всего: 13

Код

int var = mymax ( arr, n );

в var сохраниться результат функции
arr передаем по указателю, но так как он и так является указателем, нужно БЕЗ *

Добавлено через 40 секунд
Ой, опаздал,

Цитата(SVN74 @  20.11.2010,  15:42 Найти цитируемый пост)
delete arr;

Код

delete [] arr;

PM MAIL Skype GTalk   Вверх
SVN74
Дата 20.11.2010, 15:47 (ссылка)
|    (голосов:1)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Опытный
**

Профиль
Группа: Участник
Сообщений: 739
Регистрация: 5.5.2008
Где: Комсомольск на Дн епре

Репутация: 1
Всего: 18

delete [] arr;
точно, провтыкал…
Так там и функция нерабочая…

Это сообщение отредактировал(а) SVN74 — 20.11.2010, 15:48

PM MAIL WWW   Вверх
olegarh
Дата 20.11.2010, 15:53 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Шустрый
*

Профиль
Группа: Участник
Сообщений: 50
Регистрация: 6.2.2010

Репутация: нет
Всего: нет

Функция рабочая)) все уже работает спасибо)))
в функции только 

Код

indx=i;

надо заменить на 

Код

indx=i+1;

PM MAIL   Вверх
sQu1rr
Дата 20.11.2010, 16:02 (ссылка)
| (нет голосов)
Загрузка ... Загрузка …




Быстрая цитата

Цитата

Опытный
**

Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: 3
Всего: 13

Цитата(olegarh @  20.11.2010,  15:53 Найти цитируемый пост)
Функция рабочая)) все уже работает спасибо)))

Но кривая до ужаса

Код

int mymax(int *arrmax, int p){
    int max = arrmax [0]; // Понятно начинаем с нуля
    int indx = 1; // Индекс... ОО
    for (int i=1; i<p; ++i){ // Ну ладно
        if (max<arrmax[i]){ // Понятно
            max = arrmax[i]; // Тоже понятно
            indx++; // ОО чем i не нравиться
        }
        else indx++; // ОО... просто... ладно
    }
    return indx; // Возвращяем index последнего элемента ( == return p )
}

Во первых это все можно записать так

Код

int mymax(int *arrmax, int p){
    int max = arrmax[0];
    int i;
    for ( i = 1; i < p; ++i ) if ( max < arrmax[i] ) max = arrmax[i];
    return i;
}

Но зачем max сохранять если он не используется…
Может нужно гдето сохранить index?
Тогда може так?

Код

int mymax(int *arrmax, int p){
    int max = arrmax[0];
    int i, ret;
    for ( i = 1; i < p; ++i )
     if ( max < arrmax[i] )
     {
         max = arrmax[i];
         ret = i;
     }
    return ret; // Ну или ret+1 как угодно
}

PM MAIL Skype GTalk   Вверх



















Ответ в темуСоздание новой темы
Создание опроса
Правила форума «C/C++: Для новичков»
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь

  • FAQ раздела лежит здесь!

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 

0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »

Заголовок winddk-8.1, который вы связали, arm_neon.h, довольно четко показывает typedef __n128 uint32x4_t; (такую ​​же, как другие ширины элементов для 128-битных векторов), и что базовый тип __n128 сначала определяется как объединение с членом __int64[2].

typedef union __declspec(intrin_type) _ADVSIMD_ALIGN(8) __n128
{
     unsigned __int64   n128_u64[2];
     unsigned __int32   n128_u32[4];
     unsigned __int16   n128_u16[8];
     unsigned __int8    n128_u8[16];
     __int64            n128_i64[2];
     __int32            n128_i32[4];
     __int16            n128_i16[8];
     __int8             n128_i8[16];
     float              n128_f32[4];

    struct
    {
        __n64  low64;
        __n64  high64;
    } DUMMYNEONSTRUCT;

} __n128;

Если вы хотите написать код только для MSVC, который зависит от внутренних компонентов заголовка, вы можете просто объединить пары 32-битных целых чисел в 64-битные целые числа. Для ARM с прямым порядком байтов это означает создание второго 32-битного элемента как 32-битного высокий объединенного 64-битного элемента.

#ifdef _MSC_VER
// MSVC only; will silently compile differently on others
static const uint32x4_t CTRS[3] = {
     // The .n128_u64 field is first in the definition of uint32x4_t
     {1 + (0ULL<<32), 0 + (0ULL<<32)},   // ARM is little-endian
     {2 + (0ULL<<32), 0 + (0ULL<<32)},
     {3 + (0ULL<<32), 0 + (0ULL<<32)},
};

Мы можем завершить это макросом CPP, чтобы сделать его переносимым между компиляторами.

Я сделал один макрос для всего uint32x4_t, а не парный макрос, который вы также могли бы использовать для 64-битных векторов. Это делает фактические объявления менее беспорядочными скобками и именами макросов, потому что мы можем включить внешний {} в этот макрос.

#ifdef _MSC_VER
  // The .n128_u64 field is first.  Combine pairs of 32-bit integers in little-endian order.
#define INITu32x4(w,x,y,z) { ((w) + (unsigned long long(x) << 32)), ((y) + (unsigned long long(z) << 32)) }
#else
#define INITu32x4(w,x,y,z) { (w), (x), (y), (z) }
#endif

static const uint32x4_t CTRS[3] = {
 INITu32x4(1,0,0,0),
 INITu32x4(2,0,0,0),
 INITu32x4(3,0,0,0),
};

Компилируется правильно + эффективно на GCC и MSVC с правильными данными в разделе данных только для чтения (.rodata или .rdata) без инициализации среды выполнения.
Из проводника компилятора Godbolt:

uint32x4_t access(int idx) {
  return CTRS[idx];
}
@ g++5.4 -O3 -Wall -mcpu=cortex-a53 -mfpu=neon -mfloat-abi=hard -std=gnu++11
access(int):
    movw    r3, #:lower16:.LANCHOR0
    movt    r3, #:upper16:.LANCHOR0    @ gcc chooses to construct the address with movw/movt
                                       @ instead of loading from a literal pool when optimizing for cortex-a53
    add     r0, r3, r0, lsl #4
    vld1.64 {d0-d1}, [r0:64]
    bx      lr

    .section        .rodata
    .align  3
    .set    .LANCHOR0,. + 0         @@ equivalent to .LANCHOR0: here. 
            @@ Reference point that could be used for other .rodata objects if needed.
    .type   CTRS, %object
    .size   CTRS, 48
CTRS:
    .word   1
    .word   0
    .word   0
    .word   0
    .word   2
    .word   0
     ...

И MSVC -Ox: я понятия не имею, почему директиве MSVC DCQ все еще требуется 2 аргумента для создания одного 64-битного значения, точно так же, как DCD, если вы создаете массив int. Кажется, это отличается от Директива / псевдо-инструкция DCQ Кейла, где каждый аргумент является, разделенный запятыми, представляет собой 64-битное целое число.

Но, AFAICT, комментарии, добавленные MSVC, являются точным представлением числа для каждой строки.

 ;; ARM msvc19.14 -O2
    .rdata
|__n128 const * const CTRS| DCQ 0x1, 0x0           ;  = 0x0000000000000001 ; CTRS
        DCQ     0x0, 0x0                      ;  = 0x0000000000000000
        DCQ     0x2, 0x0                      ;  = 0x0000000000000002
        DCQ     0x0, 0x0                      ;  = 0x0000000000000000
        DCQ     0x3, 0x0                      ;  = 0x0000000000000003
        DCQ     0x0, 0x0                      ;  = 0x0000000000000000
        EXPORT  |__n128 access(int)|   ; access

.text$mn        SEGMENT

|__n128 access(int)| PROC                        ; access
        movw        r3,|__n128 const * const CTRS|
        movt        r3,|__n128 const * const CTRS|
        add         r3,r3,r0,lsl #4
        vldm        r3,{d0,d1}
|$M4|
        bx          lr

        ENDP  ; |__n128 access(int)|, access

В C (но не C++) MSVC допускает синтаксис назначенного инициализатора

static const uint32x4_t CTRS[3] = { [0].n128_u32 = {1, 0, 0, 0}, [1].n128_u32 = {2, 0, 0, 0}, [2].n128_u32 = {3, 0, 0, 0} };

uint32x4_t access(int idx) {
  return CTRS[idx];
}

Это прекрасно компилируется в режиме C MSVC, но не в C++. Вы можете использовать это для немного более перспективного определения INITu32x4, которое с шумом выйдет из строя, если что-то не так, и не сломается, если MS решит изменить порядок определения объединения.

Godbolt имеет режим языка C. Я обычно никогда не использую его (а просто использую -xc для g ++ / clang ++), потому что переключаться между ними неудобно, но я не знаю параметра командной строки, чтобы заставить MSVC компилироваться как C. В любом случае, это на Godbolt.

Понравилась статья? Поделить с друзьями:
  • Error c2065 undeclared identifier error c2065 undeclared identifier
  • Error c2065 string необъявленный идентификатор
  • Error c2065 null необъявленный идентификатор
  • Error c2065 func undeclared identifier
  • Error c2065 cout необъявленный идентификатор