Wskaźnik ze zmianą typu zmiennej

Wskaźnik ze zmianą typu zmiennej
Marcin Kosela
  • Rejestracja:około 4 lata
  • Ostatnio:6 miesięcy
  • Postów:36
0

Witam.

mam jakiś dziwny problem ze wskaźnikiem. Próbuje na wszystkie sposoby lecz niestety mi nie wychodzi. Musze użyć funkcji, która jako argument przyjmuje wskaźnik na zmienna double. Niestety wskaźnik który mam do dyspozycji wskazuje na zmienna typu uint16_t. Potrzebuje wiec przekonwertować typ zmiennej i przekazać ja do funkcji. Napisałem przykładowy kod. Niestety zwraca 0.

Kopiuj
uint16_t punkt1;
uint16_t *wskaznik;

double oblicz(double *liczba){
    return *liczba;
}

int main()
{
    wskaznik = &punkt1;
    punkt1 = 123;
    double wynik = oblicz((double*) wskaznik);
    printf("> %f", wynik);

    return 0;
}

Podpowiedzcie proszę gdzie robię błąd.

Od razu dodam, ze ani funkcji ani zmiennej nie mogę zmienić.

edytowany 3x, ostatnio: Riddle
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:6 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
3

Z tego co mi wiadomo to konwersja wskaźnika nie konwertuje wartości na którą wskazuje ten wskaźnik.


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
edytowany 1x, ostatnio: KamilAdam
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:mniej niż minuta
3

To mi wygląda na problem XY.
Nie pisz jak coś próbujesz osiągnąć, ale napisz co chcesz osiągnąć. Co ten kod ma zrobić? Co użytkownik ma zobaczyć?


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 2x, ostatnio: MarekR22
Marcin Kosela
  • Rejestracja:około 4 lata
  • Ostatnio:6 miesięcy
  • Postów:36
0

@MarekR22: sprobuje wyjasnic. Najpierw najwazniejsze. To program na mikroprocesor.
Mam zadeklarowana strukture ktorej uzywaja rozne urzadzenia. Potrzebuje pobrac z tej struktury zmienna uint16_t (poprzez wskaznik) i przekazac go jako zmienna double do funkcji regulatora PID. Musi sie to odbyc w jak najmniejszej ilosci krokow assemblerowych.

MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:mniej niż minuta
2

Już lepiej, ale nie rozumiem czemu chcesz angażować w obliczania wskaźnik. Standardowa konwersja int -> double powinna być ok (przynajmniej według obecnego opisu). Jednak bardziej stawiam na to, że nadal pominąłeś ważne szczegóły.

Kopiuj
uint16_t punkt1;
uint16_t *wskaznik;

double oblicz(double liczba){
    // jakieś obliczania .....
    return liczba;
}


int main()
{
    wskaznik = &punkt1;
    punkt1 = 123;
    double wynik = oblicz(*wskaznik);
    printf("> %lf", wynik); // naprawiona literówka w napisie formatujacym

    return 0;
}

Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 2x, ostatnio: MarekR22
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:6 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
4

Jeśli naprawdę potrzebujesz wskaźnika to to działa, ale możesz spróbować uprościć:

Kopiuj
int punkt1;
int *wskaznik;

double oblicz(double *liczba){
    return *liczba;
}

double wrapped(int * pointer) {
    double value = (double)(*pointer);
    return oblicz(&value);
}


int main()
{
    wskaznik = &punkt1;
    punkt1 = 123;
    
    double wynik = wrapped(wskaznik);
    printf("> %f", wynik);

    return 0;
}

zamieniłem uint16_t na int żeby odpalało się w kompilatorze online


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
MarekR22
#include <stdint.h> i masz uint16_t
Marcin Kosela
  • Rejestracja:około 4 lata
  • Ostatnio:6 miesięcy
  • Postów:36
0

@MarekR22: Ta funkcja oblicz ktora tu napisalem odwzorowuje funkcje inicjalizujaca obliczanie regulatora PID. To zewnetrzna biblioteka ktora jako argument przyjmuje wskaznik, nie zmienna. Po inicjalizacji tego regulatora nastepuje cykliczna regulacja i ona korzysta z aktualnej zmiennej podanej tym wskaznikiem. Struktury rowniez nie moge zmienic poniewaz obliczanie liczb zmiennoprzecinkowych trwa zbyt dlugo, a ja nie mam na to czasu.

@KamilAdam: sprawdze to ale chyba zajmie to sporo czasu. Nie chcialem tworzyc dodatkowych zmiennych. Czy nie powinno dac sie przekazac tego w ten sposob?

Kopiuj
int * pointer

oblicz((double)(*pointer));
edytowany 3x, ostatnio: Marcin Kosela
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:mniej niż minuta
0
Marcin Kosela napisał(a):

@MarekR22: Ta funkcja oblicz ktora tu napisalem odwzorowuje funkcje inicjalizujaca obliczanie regulatora PID. To zewnetrzna biblioteka ktora jako argument przyjmuje wskaznik, nie zmienna. Po inicjalizacji tego regulatora nastepuje cykliczna regulacja i ona korzysta z aktualnej zmiennej podanej tym wskaznikiem. Struktury rowniez nie moge zmienic poniewaz obliczanie liczb zmiennoprzecinkowych trwa zbyt dlugo, a ja nie mam na to czasu.

No to pominąłeś bardzo dużo istotnych szczegółów. Coś mi się wydaje, że bez przeczytania dokumentacji tej biblioteki i twojego urządzenia trudno będzie ci pomóc.

Pamiętaj, że nie siedzimy w twojej głowie nie znamy twojego projektu. przykład PID otwiera mi w głowie Process ID co w tym przypadku jest bezsensu.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 3x, ostatnio: MarekR22
Marcin Kosela
  • Rejestracja:około 4 lata
  • Ostatnio:6 miesięcy
  • Postów:36
0

@MarekR22: nie trzeba wcale siedziec w mojej glowie. Zagadnienie nie jest chyba tak skomplikowane zebym musial przeprowadzac Was przez meandry calej biblioteki i calego projektu. Na poczatek podalem zalozenia i problem do rozwiazania. Wydaje mi sie, ze jest wszystko co potrzebne do znalezienia rozywiazania. Nie ma tu duzego pola do popisu. Wystarczy jedno proste rozwiazanie.
To ktore podal @KamilAdam zadzala ale chcialem pomianac tworzenie kolejnej zmiennej ze wzgledu na duza czestotliwosc jej aktualizacji. To bedzie kosztowalo sporo czasu.

SE
  • Rejestracja:prawie 6 lat
  • Ostatnio:6 dni
  • Postów:321
0

Ja rowniez nie rozumiem o co Ci chodzi, jezeli chcesz po prostu wyjac wartosc, na ktora wskazuje int* i scastowac na double w jednej linijce to mozesz to zrobic tak:

Kopiuj
int main()
{
    int val = 10;
    int* pointer = &val;
    double temp = (double)(*pointer);
    printf("Hello World %f", temp);

    return 0;
}
Marcin Kosela
  • Rejestracja:około 4 lata
  • Ostatnio:6 miesięcy
  • Postów:36
0

@Seken: W pierwszym poscie napisalem "musze uzyc funkcji" i wystarczy jak uzyjemy funkcji oblicz ktora umiescilem w kodzie (tej funkcji nie mozna zmienic). W tym przykladzie utworztyles kolejna zmienna, tak jak kolega @KamilAdam, a to chcialbym pominac.

SE
  • Rejestracja:prawie 6 lat
  • Ostatnio:6 dni
  • Postów:321
1

No, ale to sam nie umiesz skleic 2 malych fragmentow kodu? Ja Ci bardzo chetnie pomoge, ale musisz sie wykazac jakakolwiek inicjatywa i powiedziec czego nie rozumiesz, a nie oczekiwac gotowca.

Marcin Kosela
  • Rejestracja:około 4 lata
  • Ostatnio:6 miesięcy
  • Postów:36
0

@Seken: jakiej inicjatywy ode mnie oczekujesz? Zapytalem o to jak przekazac wskaznik ze zmiana typu zmiennej. Napisalem caly kod reprezentujacy to zagadnienie. Co mialbym sam wiecej tutaj zrobic? Co masz na mysli, w tym wypadku, piszac gotowiec? 2 linie kodu? Jesli tak to wlasnie tego oczekuje. Ewentualnie informacji gdzie znajde odpowiedz na moje pytanie.
Mysle ze to wcale nie jest to gotowiec. Gotowiec to bardziej cala funkcja czy czesc programu. O gotowcu moznaby mowic gdybym wrzucil tu caly projekt i zapytal jak to zrobic.

SE
  • Rejestracja:prawie 6 lat
  • Ostatnio:6 dni
  • Postów:321
0

Mozliwe, ze my sie po prostu nie rozumiemy, jezeli tak to przepraszam.
Chodzi Ci o to, ze @KamilAdam robi tam po drodze double value = (double)(*pointer); ? Nie da sie tego obejsc, poniewaz jak chcesz zwrocic adres pamieci rvalue? Innymi slowy nie mozesz miec wskaznika na wartosc np. 11, tylko na zmienna ktora przechowuje wartosc 11.
Teoretycznie gdyby to byl C++ to daloby sie to zalatwic za sprawa rvalue reference, ale w C nie slyszalem o niczym takim.

kq
Moderator C/C++
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 8 godzin
  • Lokalizacja:Szczecin
2
Marcin Kosela napisał(a):

Czy nie powinno dac sie przekazac tego w ten sposob?

Kopiuj
int * pointer

oblicz((double)(*pointer));

@Marcin Kosela: da się, nawet ten cast będzie zbędny, bo nastąpi automatyczna konwersja. Ale zakładając, że nie masz kompilatora z 1980, to co robisz jest kompletnie bez sensu. Dowolny optymalizujący kompilator z tego tysiąclecia wyeliminuje taką zmienną, a z tego co wiem większość kompilatorów na mikroprocki bazuje na gcc 4 lub nowszym, co pod to podchodzi.

Porównaj sobie wygenerowany kod funkcji i znajdź różnice:
https://godbolt.org/z/b5vhsKcPn

Kopiuj
void sink(double);

void func1(int* ptr)
{
    sink(*ptr);
}

void func2(int* ptr)
{
    double var = *ptr;
    sink(var);
}
Kopiuj
func1(int*):
        pxor    xmm0, xmm0
        cvtsi2sd        xmm0, DWORD PTR [rdi]
        jmp     sink(double)
func2(int*):
        pxor    xmm0, xmm0
        cvtsi2sd        xmm0, DWORD PTR [rdi]
        jmp     sink(double)

Marcin Kosela
  • Rejestracja:około 4 lata
  • Ostatnio:6 miesięcy
  • Postów:36
0

@Seken: Nie ma problemu.
Tak. Wlasnie o to mi chodzi. W tym wypadku odswiezenie tej dodatkowej zmiennej 10000 razy na sekunde robi roznice.

@kq: przyjrze sie temu, skompiluje i przemysle to jeszcze raz na spokojnie, bo juz mi sie wszystko pomieszalo. Wydaje mi sie, ze u mnie to nie dzalalalo

edytowany 1x, ostatnio: Marcin Kosela
ZD
  • Rejestracja:około 3 lata
  • Ostatnio:ponad rok
  • Postów:2310
1
Marcin Kosela napisał(a):

To ktore podal @KamilAdam zadzala ale chcialem pomianac tworzenie kolejnej zmiennej ze wzgledu na duza czestotliwosc jej aktualizacji. To bedzie kosztowalo sporo czasu.

Ciężko komercyjne prace robić ze znacznymi lukami w znajomości języka.

TYM BARDZIEJ się dziwię, że optymalizujesz w assemblerze.
Nie wyobrażam sobie inaczej dziubać w assemblerze, niż mieć "o trzeciej w nocy" perfekyjne rozumienie czym jest wskaźnik, CZYM NIE JEST itd.
Powtórzę, dedukując imiennie do Ciebie: rozumieć, czym wskaźnik NIE JEST.

Twój temat, tak jak go stawiasz, jest mrzonką. NIE MA takiego rzutowania(whatwver) wskaźnika na niekompatybilnych typach, które by nie polegało na rzutowaniu (wskazywanej) wartości. Natomiast sam fakt istnienia zmiennej w C kosztuje bardzo mało / nic.

BTW jak mamy 10tys aktualizacji na sekundę, jak piszesz, to ja wątpię, czy te dane są konsumowane w tym tempie, czy są przepisywane "na wiwat" bo się nie chciało komuś przyjrzeć procesowi


If you put a million monkeys at a million keyboards, one of them will eventually write a Java program - the rest of them will write Perl
ZD
Na marginesie, co to jest wskaźnik a co nie jest, bardzo pomaga głęboko przetrawić w zupełnie innym języku, np zarządzane referencje w Javie / C# vs unsafe wskazniki. w tych językach, w stosownych fragmentach. Takie ćwiczenie na elastyczność mózgu.
Marcin Kosela
  • Rejestracja:około 4 lata
  • Ostatnio:6 miesięcy
  • Postów:36
0

@ZrobieDobrze: Człowieku... Skąd tyle jadu?! Dziwne jest to, że musze się tutaj opowiadać o sobie i udowadniać co sobą reprezentuję. Jeśli kolega jest taki wnikliwy to proponuję zajrzeć choćby na mój profil facebookowy, bo przedstawiam się tu imieniem i nazwiskiem. Jak już kolega dojdzie do tego, że ani nie jestem zawodowym programistą, ani nie tworzę komercyjnych projektów to może się kolega zastanowi nad podejściem do ludzi na forum. Ja nikogo do niczego nie zmuszam. Jeśli ktoś nie chce, nie musi ani czytać ani odpowiadać na moje posty.
Uważam, że włożyłem pracę i trud w znalezienie rozwiązania i po tym podjąłem próbę znalezienia pomocy tutaj na forum. Nie pierwszy raz spotykam osobę, która tworzy piękne opowieści i udowadnia innym, że g**no się znają ale sama rozwiązania nie potrafi znaleźć, więc nie robi mi różnicy co tu napisałeś. Twój post nic tu nie wnosi. Zaśmiecasz forum.

Odpowiem na zarzuty ze względu na szacunek do innych z tego forum:

  • nie "dziubie" w assemblerze, bo go po prostu nie znam
  • rozumiem czym jest wskaźnik, wiem też czym mógłby nie być albo być. Czy to jakieś dywagacje egzystencjalne?
  • tematu nie stawiam. Szukam rozwiazania
  • fakt istnienia zmiennej DOUBLE kosztuje 4 bajty danych
  • to powątpiewanie w 10k aktualizacji czym jest spowodowane? Dla obliczenia mocy dla 3xPWM dla silnika krecącego sie z predkością 100 obr na minutę może być, na przykład, spowodowane...
edytowany 1x, ostatnio: Marcin Kosela
ZD
Ja bym popracował - o ile rzeczywiście zachodzi potrzeba optymalizacji, bo "niezupełnie" ci wierzę - nad konwewrsją int - float "co jakis czas", cokolwiek by to miało znaczyć. BTW 100/min to wnioskuję kobyła, która się we wtorek rozpędza i w środę hamuje.
Marcin Kosela
nie, to kilka watów. Nie musisz mi w nic wierzyć. Takie rozwiązanie z dodatkową zmienną i przepisywaniem jest oczywiste ale to nadal nie rozwiązuje problemu
kq
Moderator C/C++
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 8 godzin
  • Lokalizacja:Szczecin
2

fakt istnienia zmiennej kosztuje 4 bajty danych

No właśnie niekoniecznie, jak widać na przykładzie, który zamieściłem wyżej.


Marcin Kosela
  • Rejestracja:około 4 lata
  • Ostatnio:6 miesięcy
  • Postów:36
0

@kq: poprawiłem

kq
Moderator C/C++
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 8 godzin
  • Lokalizacja:Szczecin
1

Przecież w moim przykładzie mam zmienną double, która znika w asemblerze, bo kompilator ją optymalizuje.


Marcin Kosela
  • Rejestracja:około 4 lata
  • Ostatnio:6 miesięcy
  • Postów:36
0

@kq: ja chyba czegoś nie rozumiem. U Ciebie zmienna jest tworzona okresowo w funkcji dlatego kompilator pomija ją, przepisując od razu do wyniku ale u mnie to tak nie działa.

Ja mam strukturę:

Kopiuj
struct BLDCMotorSt{
	uint32_t pwmU;
	uint32_t pwmV;
	uint32_t pwmW;
	int16_t fieldPosition;  //ustawiona pozycja pola magnetycznego dla kompletnego obrotu - 4095 pozycji
	uint16_t expectedPosition; // oczekiwana pozycja silnika
	uint8_t direction; // kierunek 0-L 1-R
	double distance; // dystans od punktu oczekiwanego do aktualnego
	float powerAcceleration;
	int16_t expectedPower;
	int16_t actualPower;
};

Ta struktura przechowuje aktualny stan urządzenia.

Teraz do sterowania actualPower chcę użyć tej biblioteki: link

Więc wychodzi mi coś w tym stylu:

Kopiuj
main{
/...
PID(&TPID, &bldcMotor.distance, &bldcMotor.actualPower, &TempSetpoint, 2, 5, 1, _PID_P_ON_E, _PID_CD_DIRECT);

PID_SetMode(&TPID, _PID_MODE_AUTOMATIC);
PID_SetSampleTime(&TPID, 500);
PID_SetOutputLimits(&TPID, 1, 30);
.../
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
	if (htim->Instance == TIM2) {
		if (initPhase == 0) {
			bldcHaptickMode();
		}
	}

	if (htim->Instance == TIM3) {
		bldcEncoder.status = as5600_ReadPosition(&hi2c2, &bldcEncoder.angle);
		bldcEncoder.magnetStatus = as5600_StatusMagnet(&hi2c2);

		if (initPhase == 0) {
			bldcMotor.fieldPosition = bldcEncoder.calculatedAngle;
			bldcCalc();
			PID_Compute(&TPID);  //tutaj nastepuje okresowa aktualizacja PID
		}
	}
}

problem jest z inicjalizacją PID ponieważ w bibliotece zmienne są typu double. Nie chcę przerabiać biblioteki, bo nie jest to moja praca i szanuje to co ktoś zobił, ale również dlatego, że to trochę pracy. Myślałem, że będzie to proste i ogarnę w miarę szybko.
Widzę, że chyba jednak tak nie będzie. Może spróbuję dostać się bezpośrednio do pamięci

kq
Moderator C/C++
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 8 godzin
  • Lokalizacja:Szczecin
2

No to masz następujące opcje:

  1. Modyfikacja po swojej stronie, tak abyś używał double tam gdzie biblioteka chce double
  2. Modyfikacja biblioteki
  3. Konwersja (nie rzutowanie!) na double tam, gdzie ma być double. int->double dzieje się automatycznie, więc de facto przekazujesz wartość całkowitą i się nie przejmujesz. Jeśli biblioteka wymaga wskaźnika na double to nie obędzie się bez utworzenia zmiennej (może być lokalna), na którą będziesz wskazywał. Albo opcja 1. lub 2.

Marcin Kosela
  • Rejestracja:około 4 lata
  • Ostatnio:6 miesięcy
  • Postów:36
0

@kq: dziękuję za wyczerpującą odpowiedź i zaangażowanie. Spróbuję ustalić co będzię szybsze i taką opcję wybiorę

enedil
  • Rejestracja:ponad 11 lat
  • Ostatnio:4 dni
  • Postów:1027
0

Nie rozumiem tutaj jeszcze jednej kwestii - jak masz zmienna typu int w pamięci, to zakładając że u ciebie jest to tak samo reprezentowane jak na x86_64, nie da się przekazać wskaźnika na double na nic co by miało odpowiednią wartość, ze względu na to, że reprezentacja w pamięci liczb całkowitych i zmiennoprzecinkowych jest zupełnie inna.

edytowany 1x, ostatnio: enedil
Marcin Kosela
  • Rejestracja:około 4 lata
  • Ostatnio:6 miesięcy
  • Postów:36
0

@enedil: właśnie tu leży problem. Oczywiście reprezentacja tych typów w pamięci jest odmienna. Chodziło o przekonwertowanie tej wartości. Myślałem, że możliwe jest obejście tej konwersji zmuszając kompilator do "poradzenia" sobie z tym

_13th_Dragon
Jak kompilator ma sobie poradzić z wartościami takie jak 1E30, NAN?
ZD
  • Rejestracja:około 3 lata
  • Ostatnio:ponad rok
  • Postów:2310
4
Marcin Kosela napisał(a):

@enedil: właśnie tu leży problem. Oczywiście reprezentacja tych typów w pamięci jest odmienna. Chodziło o przekonwertowanie tej wartości. Myślałem, że możliwe jest obejście tej konwersji zmuszając kompilator do "poradzenia" sobie z tym

Nawet jeśli wyobrazimy sobie język o wysokim pozmie abstrakcji, gdzie by to było możliwe i syntax języka to potrafi zapisać - sądzisz że na poziomie kodu maszynowego to jest za darmo? Przecież "samo" się nie skonwertuje. Typy nie są żadną miarą kompatybilne. Powstanie zmienna robocza o takim samym koszcie jak zaprogramowana ręcznie itd ...


If you put a million monkeys at a million keyboards, one of them will eventually write a Java program - the rest of them will write Perl
edytowany 1x, ostatnio: ZrobieDobrze
enedil
to miałem na myśli właśnie
KS
  • Rejestracja:prawie 4 lata
  • Ostatnio:5 dni
  • Postów:581
0

Strict aliasing.

Rób unie. Za coś takiego jest ula w łeb.

  • to się chyba nie zmieści ale złamanie strict aliasing jest gorsze.

  • No raczej na pewno się nie zmieści ;-)

Szczęśliwie odczyt to segfault.

Pzdr! doczytaj o o pierwszym błędzie bo tego kompilator nigdy nie zawarnuje. Szukanie takiego błędu to katorga

edytowany 2x, ostatnio: ksh
Zobacz pozostałe 2 komentarze
Azarien
Post jest zrozumiały. Jest jedna literówka "ula" - powinno być "kula".
enedil
No faktycznie, unia co zawiera double* oraz int* w czymś pomoże xd
Azarien
@enedil: nie double* i int* tylko double i int. czytałem że jest to dozwolone, nie przez standard ale przez kompilatory jako "rozszerzenie składni". sam standard nie daje dobrej metody na type punning.
KS
@Azarien - w nowym std jest _Alignas keyword i to chyba załatwia sprawę. Unia jest uniwersalna, ale nie wiedziałem, że to rozszerzenie kompilatora Post pisałem będąc lekko pijanym, więc mógł być w odczycie enigmatyczny ;-)
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)