• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Zapętlanie się include cpp.

Object Storage Arubacloud
0 głosów
390 wizyt
pytanie zadane 31 grudnia 2020 w C i C++ przez kubekszklany Gaduła (3,190 p.)
Witam. Mam taki problem, mianowicie chciałem podzielić kod do arduino na kilka mniejszych plików, jednak nijak nie mogę ich ze sobą połączyć. Mianowicie, mam plik main, w którym jest trochę zmiennych, a także #include <display.h> (do używania wyświetlacza) i #include <gui.h> (do uruchomiania gui). W gui.cpp mam #include <main.h> (żeby mieć dostęp do pewnych zmiennych z main) a także #include <display.h> (do używania wyświetlacza). Plik display.cpp też ma #include <main.h> (żeby mieć dostęp do pewnych zmiennych z main).

Reasumując, mam 3 pliki, każdy z nich ma #include do dwóch pozostałych, przez co tworzy mi się taka jakby pętla i dostaję błędy o nieskończonych include'ach czy powtórzonych deklaracjach. Jak to rozwiązać, żeby z każdego pliku mieć dostęp do każdego innego?

Gdybym źle wytłumaczył to proszę pytać, na co dzień programuję w c# a tam nie ma z tym problemu, wystarczy NazwaPliku.NazwaFunkcji(); i działa, stąd moje pytanie.

1 odpowiedź

0 głosów
odpowiedź 31 grudnia 2020 przez Mateusz1223 Bywalec (2,440 p.)

Dodaj na początku każdego pliku .h 

#pragma once

Ewentualnie poczytaj o czymś takim jak include guard.

Mam nadzieję, że pomogłem :)

komentarz 31 grudnia 2020 przez Mateusz1223 Bywalec (2,440 p.)

Tutaj możesz poczytać o include guard: https://en.wikipedia.org/wiki/Include_guard. Jednak #pragma once powinna wystarczyć.

komentarz 31 grudnia 2020 przez tkz Nałogowiec (42,000 p.)
#pragma once również jest strażnikiem, ale nie jest zgodna z standardem.
komentarz 31 grudnia 2020 przez Mateusz1223 Bywalec (2,440 p.)
To prawda, nie jest standardem, ale na przykład jest "standardem" na kompilatorze microsoftu, gcc/g++ też wspiera i z tego co się orientuję Arduino IDE też to wspiera wiec nie będzie z tym problemu.
komentarz 31 grudnia 2020 przez tkz Nałogowiec (42,000 p.)
Problemem nie jest to, który kompilator to wspiera, a który nie. Kwestią wiodącą jest to, że nie ma tego w standardzie. O czym warto pamiętać.
komentarz 31 grudnia 2020 przez edwardkraweznik Dyskutant (9,930 p.)

a

#ifndef plik_h
#define plik_h
...
#endif

?

komentarz 31 grudnia 2020 przez tkz Nałogowiec (42,000 p.)
A to jest zgodne z standardem.
komentarz 31 grudnia 2020 przez kubekszklany Gaduła (3,190 p.)

Dobra, a byłby mi ktoś to w stanie rozpisać, gdzie tego użyć? Przykładowo:

// main.cpp:
#include <main.h>
#include <lib_a.h>
#include <lib_b.h>

// main.h:
int number = 0;

//--------------------------------

// lib_a.cpp:
#include <main.h>
#include <lib_a.h>
#include <lib_b.h>

// lib_a.h:
int number_a = 0;

//--------------------------------

// lib_b.cpp:
#include <main.h>
#include <lib_a.h>
#include <lib_b.h>

// lib_b.h:
int number_b = 0;

Gzie dokładnie te ifndef wstawić? Do cpp czy h? 

komentarz 31 grudnia 2020 przez tkz Nałogowiec (42,000 p.)

W plikach nagłówkowych. 

#ifndef plik_h //nazwa musi być unikatowa
#define plik_h
//cały kod tutaj
#endif

Poza tym zapoznaj się z różnicą przy #include <> vs ""

komentarz 31 grudnia 2020 przez j23 Mędrzec (194,920 p.)
#ifndef plik_h
#define plik_h

/* cała zawartość pliku plik.h */

#endif

W plikach nagłówkowych nie definiuje się zmiennych, jedynie deklaracje z extern. Definicje powinny być w plikach źródłowych.

komentarz 31 grudnia 2020 przez kubekszklany Gaduła (3,190 p.)
edycja 31 grudnia 2020 przez kubekszklany

Próbowałem na różne sposoby, nadal to samo. Nawet zrobiłem pusty workspace z 4 plikami, wyglądającymi tak jak na zdjęciu, i błąd nadal jest:

Zdjęcie w wyższej rozdzielczości tutaj: https://i.imgur.com/3xkgNkC.png

komentarz 31 grudnia 2020 przez edwardkraweznik Dyskutant (9,930 p.)
poczytaj o tym ---> https://www.tutorialspoint.com/when-to-use-extern-in-c-cplusplus

sprawdź czy nie masz jakiś starych plików .o i czy ich nie linkujesz
komentarz 31 grudnia 2020 przez kubekszklany Gaduła (3,190 p.)
A co to ma wspólnego z moim przykładem?
komentarz 31 grudnia 2020 przez edwardkraweznik Dyskutant (9,930 p.)
masz zdublowaną zmienną, ten screen nie przedstawia programu który ty kompilujesz lub masz jakieś stare pliko .o i je linkujesz nie wiedząc o tym.
komentarz 31 grudnia 2020 przez Mateusz1223 Bywalec (2,440 p.)

@kubekszklany, wywala ci błąd ponieważ te ifndef powinny być po pierwsze tylko w plikach .h, pod drugie jeżeli masz na przykład plik main.h to robisz tak:

#ifndef MAIN_H
#define MAIN_H

// zawartość pliku main.h

#endif

 

komentarz 31 grudnia 2020 przez edwardkraweznik Dyskutant (9,930 p.)
Mateusz1223 to nie ma żadnego znaczenia... może mieć nawet #IFNDEF DOWOLNAZMIENNA

Faktem jest, że w plikach cpp nie stostuje się IFNDEF ale także nie w tym problem.

----------------------------------------------------------------------------

działa to tak:

kompilacja na przykładzie g++:

g++ -c plik1.cpp -o plik1.o <--- tworzy obiekt

g++ -c plik2.cpp -o plik2.o <--- kolejny obiekt

konsolidacja/linkowanie:

g++ *.o -o nazwa_aplikacji

nieraz bywa tak, że jeśli ktoś ma fajowe IDE a nie wie jak działa kompilator to potrafi sobie linkować stare obiekty...

Prawdopodobnie u ciebie jest problem z linkowaniem starych obiektów...
komentarz 31 grudnia 2020 przez edwardkraweznik Dyskutant (9,930 p.)

teraz tak patrze i widzę 2 definicje IFNDEF MAIN_H w plikach main.cpp i plik.h a wewnątrz includujesz main.h ... a w main.h jest int x;

...

cheeky

komentarz 31 grudnia 2020 przez kubekszklany Gaduła (3,190 p.)

 ten screen nie przedstawia programu który ty kompilujesz

To jest dokładnie to co skompilowałem.

teraz tak patrze i widzę 2 definicje IFNDEF MAIN_H w plikach main.cpp i plik.h a wewnątrz includujesz main.h ... a w main.h jest int x;

W takim razie co mam zrobić jeżeli chcę użyć main.h więcej niż 1 raz? Może to być plik_a.cpp i plik_b.cpp, bez znaczenia, jak użyję 2 razy to zawsze mam podwójną deklarację int x.

komentarz 31 grudnia 2020 przez edwardkraweznik Dyskutant (9,930 p.)
komentarz 31 grudnia 2020 przez edwardkraweznik Dyskutant (9,930 p.)
musisz podejść do tego tak, że dyrektywy preprocesora nie mają nic wspólnego z c++em...
komentarz 1 stycznia 2021 przez j23 Mędrzec (194,920 p.)

W takim razie co mam zrobić (...)

#ifndef MAIN_H
#define MAIN_H

extern int x;

#endif
#include "main.h"

int x;

// reszta kodu

 

Podobne pytania

0 głosów
1 odpowiedź 184 wizyt
pytanie zadane 18 października 2015 w C i C++ przez niezalogowany
0 głosów
3 odpowiedzi 511 wizyt
pytanie zadane 20 lipca 2015 w PHP przez Ivan Maniak (60,650 p.)
0 głosów
1 odpowiedź 431 wizyt
pytanie zadane 3 kwietnia 2022 w PHP przez jamie80 Początkujący (320 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...