powered by simpleCommunicator - 2.0.28     © 2024 Programmizd 02
Map
Форумы / C++ [игнор отключен] [закрыт для гостей] / не могу посчитать количество строк в массиве.
25 сообщений из 45, страница 1 из 2
не могу посчитать количество строк в массиве.
    #40082227
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если имеем 3 файла main.cpp , constants.cpp, constants.hpp, то вот это не компилируется :



constants.cpp:
Код: plaintext
1.
2.
#include "constants.hpp"
extern const int arr[][4] = { {13,344,55}, { 13,344,55 }, { 13,344,55 }, { 13,344,55 } };


constants.hpp:
Код: plaintext
1.
2.
3.
4.
#ifndef DATABASE_H
#define DATABASE_H
extern const int arr[][4];
#endif //DATABASE_H



main.cpp :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
#include <iostream>
#include "constants.hpp"
using namespace std;
int main() {	
	int j0 = sizeof(arr); //not OK!
	int j1=sizeof(*arr);  //OK!
	int size = sizeof(arr) / sizeof(*arr); //not OK
} 



но если это сделать в одном файле, то всё ОК:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
#include <iostream>
#include "constants.hpp"
using namespace std;
const int arr1[][4] = { {13,344,55}, { 13,344,55 }, { 13,344,55 }, { 13,344,55 } };
int main() {
	int j0 = sizeof(arr1); //OK!
	int j1 = sizeof(*arr1);  //OK!
	int size = sizeof(arr1) / sizeof(*arr1); //OK
}
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082233
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andron81
constants.hpp:
Код: plaintext
1.
2.
3.
4.
#ifndef DATABASE_H
#define DATABASE_H
extern const int arr[][4];
#endif //DATABASE_H



sizeof() дает размер типа данных, а не размер конкретного экземпляра этого типа в памяти. Ну ты "недоопределил" тип данных массива arr, указав []. Определение для const должно быть тут же, в объявлении, если бы не extern. Но ты указал extern, в итоге, в .hpp имеем лишь указатель на где-то определенные данные, связь с определением в .cpp переложена на момент линковки. Main() ничего не знает об определении, видит только объявление, вот и "ругается".

Определи в .hpp, и всё будет хорошо. Ну, если не забывать возможности повторного объявления (используй inline). :)
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082253
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ъъъъъ
andron81
constants.hpp:
Код: plaintext
1.
2.
3.
4.
#ifndef DATABASE_H
#define DATABASE_H
extern const int arr[][4];
#endif //DATABASE_H



sizeof() дает размер типа данных, а не размер конкретного экземпляра этого типа в памяти. Ну ты "недоопределил" тип данных массива arr, указав []. Определение для const должно быть тут же, в объявлении, если бы не extern. Но ты указал extern, в итоге, в .hpp имеем лишь указатель на где-то определенные данные, связь с определением в .cpp переложена на момент линковки. Main() ничего не знает об определении, видит только объявление, вот и "ругается".

Определи в .hpp, и всё будет хорошо. Ну, если не забывать возможности повторного объявления (используй inline). :)


опредеделять в hpp разве по феншую ? )
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082256
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andron81,

если новая версия компилятора и нужна глобальная переменная - то да, рекомендуют.
Из плюсов: например, меньше вероятность получить облом "повтор имени" на этапе линковки: главное, чтобы имя переменной было уникально лишь в рамках единицы компиляции. Ну и - как у тебя, тип сразу известен.
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082304
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ъъъъъ
andron81
constants.hpp:
Код: plaintext
1.
2.
3.
4.
#ifndef DATABASE_H
#define DATABASE_H
extern const int arr[][4];
#endif //DATABASE_H



sizeof() дает размер типа данных, а не размер конкретного экземпляра этого типа в памяти. Ну ты "недоопределил" тип данных массива arr, указав []. Определение для const должно быть тут же, в объявлении, если бы не extern. Но ты указал extern, в итоге, в .hpp имеем лишь указатель на где-то определенные данные, связь с определением в .cpp переложена на момент линковки. Main() ничего не знает об определении, видит только объявление, вот и "ругается".

Определи в .hpp, и всё будет хорошо. Ну, если не забывать возможности повторного объявления (используй inline). :)


сегодня я это переварил. прихожу к выводу , что лучше писать размер во всех файлах . вот так arr[4][4]
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082320
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andron81,

Ещё можно std::array использовать. В нем есть информация о размере и тапе элемента.
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082332
d7i
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ъъъъъ
Ещё можно std::array использовать.

А ещё лучше std::vector.
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082407
petrav
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ъъъъъ
andron81,

если новая версия компилятора и нужна глобальная переменная - то да, рекомендуют.
Из плюсов: например, меньше вероятность получить облом "повтор имени" на этапе линковки: главное, чтобы имя переменной было уникально лишь в рамках единицы компиляции. Ну и - как у тебя, тип сразу известен.

Т.е. вы хотите сказать, что в новом стандарте С++ переменную определяют в *.h с помощью спецификатора inline?

Мне кажется, вы не слишком ясно выразились.
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082409
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petravТ.е. вы хотите сказать, что в новом стандарте С++ переменную *определяют* в *.h с помощью
спецификатора inline?

Вы не поверите... https://en.cppreference.com/w/cpp/language/inline
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082414
petrav
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

petravТ.е. вы хотите сказать, что в новом стандарте С++ переменную *определяют* в *.h с помощью
спецификатора inline?

Вы не поверите... https://en.cppreference.com/w/cpp/language/inline

Т.е. можно не писать так:
Код: plaintext
1.
2.
3.
4.
// My.h.
extern int Aaa;
// My.cpp.
int Aaa = 0;


А просто написать:

Код: plaintext
1.
2.
// My.h.
inline int Aaa = {};


Я не знал об этом. Нужно поискать статью на Хабре.

Спасибо.
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082421
petrav
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ъъъъъ
andron81,

если новая версия компилятора и нужна глобальная переменная - то да, рекомендуют.

Окей, с этим разобрались. Определяем глобальную переменную как inline в *.h.

ъъъъъ
Из плюсов: например, меньше вероятность получить облом "повтор имени" на этапе линковки: главное, чтобы имя переменной было уникально лишь в рамках единицы компиляции. Ну и - как у тебя, тип сразу известен.

Но тут то, что написано и как это понять? Складывается впечатление, что переменная определённая в *.h как inline становится static (аналог анонимного пространства имён). Но я вижу, что это не так.
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082431
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
petrav,

есть вопрос? Cформулируй. "Как это понять?" - не вопрос.
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082432
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petrav
Но тут то, что написано и как это понять? Складывается впечатление, что переменная определённая в *.h как inline становится static (аналог анонимного пространства имён). Но я вижу, что это не так.

Тут все написано https://en.cppreference.com/w/cpp/language/inline

Из всех копий inline остается только одна глобальная переменная. Так же как и с функциями.

Основное достоинство inline переменных по сравнению с extern - возможность реализации любых header-only библиотек.
Вспомогательная фича - они устраняют во многих случаях так называемый Initialization Order Fiasco , когда порядок инициализации между единицами трансляции не гарантируется.
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082445
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
C extern:
Пусть
a.h
Код: plaintext
1.
extern const int x;


b.h
Код: plaintext
1.
extern const int x;



Тогда:
1. c.cpp
Код: plaintext
1.
const int x  = 123;


- компилируется, но не собирается.
2. c.cpp
Код: plaintext
1.
2.
3.
4.
5.
// ...пофиг на наличие include:
#include "a.h" 
#include "b.h" 
// end-of-пофиг
extern const int x  = 123;


- тоже компилируется и собирается, при линковке все ссылки на x разрешаются объектом в a.obj.
3. c.cpp
Код: plaintext
1.
2.
3.
#include "a.h" 
#include "b.h" // Повтор объявления X, и всё равно всё ОК
const int x  = 123; // Атрибут extern есть в include.


- тоже компилируется и собирается, при линковке все ссылки на x разрешаются объектом в a.obj.
~~~~~~~~~~~~~~~~~~
С inline.

Пусть
a.h
Код: plaintext
1.
inline const int x = 1;


b.h
Код: plaintext
1.
inline const int x = 2;



Тогда:
c.cpp
Код: plaintext
1.
2.
#inclide "a.h"
#inclide "b.h"


- не скомпилируется: повторное определение и многократная инициализация в рамках одной единицы компиляции c.cpp.

Дополнительно.
a.cpp
Код: plaintext
1.
2.
#include "a.h"
int ax() { return x; };


b.cpp
Код: plaintext
1.
2.
#include "b.h"
int bx() { return x; };


c.h
Код: plaintext
1.
2.
int ax();
int bx();



тогда:
c.cpp
Код: plaintext
1.
2.
3.
4.
5.
6.
#include <iostream>
#include "c.h"
...
	std::cout << ax() << std::endl; // Вывод: 1
	std::cout << bx() << std::endl; // Вывод: 2
...


- компилируется и собирается, получаем разные "глобальные" x для единиц компиляции a.cpp и b.cpp.
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082461
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ъъъъъ,

Какая разница что там выводится в результате UB? ))
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082462
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovsky,

а где UB?
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082465
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ъъъъъ
Пусть
a.h
Код: plaintext
1.
inline const int x = 1;



b.h
Код: plaintext
1.
inline const int x = 2;



If an inline function or variable (since C++17) with external linkage is defined differently in different translation units, the behavior is undefined.
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082467
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovsky,

не вижу, откуда тут может взяться "external linkage". Поясни, пожалуйста.
...
Ага, нашел: по умолчанию. Спасибо.
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082468
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ъъъъъ
Anatoly Moskovsky,

не вижу, откуда тут может взяться "external linkage". Поясни, пожалуйста.
...
Ага, нашел: по умолчанию. Спасибо.

А в MSVS вроде как не external linkage, а вполне себе в компайл-тайме.
Или я не разобрался.
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082475
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Начал читать: https://habr.com/ru/company/jugru/blog/506104/ - страшно, нафиг...
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082476
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Удалено
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082516
petrav
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovsky
ъъъъъ,

Какая разница что там выводится в результате UB? ))

Это же должно быть нарушением ODR?
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082531
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
d7i
ъъъъъ
Ещё можно std::array использовать.

А ещё лучше std::vector.



в векторе я не умею хранить объекты класса. только указатели получается.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
#include <iostream>
#include <vector>
class A {
  int i;
public:
  A(int ii):i(ii) {}
  A(const A& a) { i = a.i*10; };

  
};

std::vector <A> AA;

using namespace std;
int main() {
  AA.push_back(); //не компилится
  AA.push_back(); //не компилится
}
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082536
Фотография crutchmaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

Это не массив, а указатель. Ты ходишь по охриненно тонкому льду...
...
Рейтинг: 0 / 0
не могу посчитать количество строк в массиве.
    #40082540
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

Код: plaintext
1.
2.
3.
4.
5.
int main() {
  A elem(42);
  AA.push_back(elem); //компилится
  AA.push_back(elem); //компилится
}


crutchmaster
andron81,

Это не массив, а указатель. Ты ходишь по охриненно тонкому льду...

Чего ?
...
Рейтинг: 0 / 0
25 сообщений из 45, страница 1 из 2
Форумы / C++ [игнор отключен] [закрыт для гостей] / не могу посчитать количество строк в массиве.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]