Kirjautuminen

Haku

Tehtävät

Koodit: C++: Taulukon koko funktiokutsussa

Kirjoittaja: koo

Kirjoitettu: 19.03.2008 – 19.03.2008

Tagit: koodi näytille, vinkki

Yksi C-kielen erityispiirre on, että taulukkoparametri välitetään funktiokutsussa osoittimena taulukon ensimmäiseen alkioon. Vaikka kääntäjällä voikin ohjelman käännösaikana olla tieto taulukon koosta, tämä tieto häviää, kun taulukkoparametri ikään kuin rappeutuu osoittimeksi. Kutsutussa funktiossa taulukon alkuperäistä kokoa ei voi mitenkään varmuudella tietää. Yleensä tämä ratkaistaan siten, että taulukon alkioiden lukumäärä välitetään erillisessä parametrissa, jolloin tiedon oikeellisuus on käyttäjän vastuulla.

Yhteensopivuussyistä sama käytäntö on periytynyt myös C++:aan. C++:ssa on kuitenkin piirteitä, joita C:ssä ei ole ja joiden suhteen C++:n kehittäjät ovat voineet valita toisen lähestymistavan.

Yksi tällainen alue on templatet eli kaavaimet. Funktiokaavain ei ole varsinainen funktiototeutus vaan eräänlainen malli, jonka mukaan funktio tarvittaessa luodaan. Kaavaimen parametreja voivat olla tyypit ja kokonaislukuvakiot ja ne annetaan funktion esittelyn template<...> -osassa. Nämä parametrit määräävät esimerkiksi, mitä tietotyyppejä varten kaavaimen rungosta luodaan funktiototeutus.

Kun kääntäjä päättelee, millaisen funktion se kaavaimesta luo, se ottaa huomioon funktiokutsun parametrien tyypit ja sovittaa ne kaavainparametrimäärittelyihin. Pointti on siinä, että tässä päättelyprosessissa esimerkiksi taulukkoparametrin tyyppi vielä sisältää tiedon taulukon alkioiden määrästä.

C++:n kaavaimissa tällaista tietoa voi käyttää hyväkseen. Olen laatinut yksinkertaisen strkcpy-funktion (ekan listauksen alku). Funktio on pohjimmiltaan ihan sama kuin standardikirjaston strncpy-funktio, mutta varmistaa, että kopioitu merkkijono päättyy aina nul-merkkiin. Funktio toimii aivan perinteiseen tyyliin eikä sen toimintaa liene tarpeen ihmeemmin selitellä. Tällaisella funktiolla tokan listauksen eka kohta saadaan toimimaan yllätyksettä.

Jännä juttu sen sijaan on tuo määritelty strkcpy-funktiokaavain (ekan listauksen loppu). Siinä funktiolle ei erikseen välitetä tietoa taulukon koosta, sillä kutsussa on vain kaksi parametria. Koko meneekin mukana ensimmäisessä parametrissa, joka on pohjimmiltaan viite taulukkoon. Kun kaavainfunktiota kutsutaan erikokoisilla taulukoilla, jokainen kutsu on periaatteessa eri funktion kutsu. Kaavaimen koodi ikään kuin laventuu tai instantioituu kutsukohtaan eri tavoin sen mukaan, mikä taulukon alkioiden lukumäärä N on. Koska funktio kuitenkin on lyhyt ja käyttää hyväkseen tuota tavallista strkcpy-funktiota, mitään erityistä tehottomuutta ei pitäisi aiheutua. Tällä kaavaimella saadaan tokan listauksen toka ja kolmas kohta toimimaan kaikkien riemuksi.

Jos tieto alkuperäisen taulukon koosta on kadotettu esimerkiksi käyttämällä osoitinta, funktiokaavaimen käyttö ei onnistu, eli kommentit poistamalla tokan listauksen neljäs kohta antaa virheilmoituksen.

Kaavaimet ovat hyvin monipuolisia, joten niiden avulla vastaava toiminnallisuus voitaisiin toteuttaa toisinkin. Perusperiaate on kuitenkin sama.

strkcpy.hpp

#ifndef STRKCPY_HPP
#define STRKCPY_HPP

#include <cstring>


inline char *strkcpy(char *t, char const *s, std::size_t n)
{
        if (n != 0)
        {
                std::strncpy(t, s, --n);
                t[n] = '\0';
        }
        return t;
}


template<std::size_t N> char *strkcpy(char (&t)[N], char const *s)
{
        return strkcpy(t, s, N);
}


#endif

main.cpp

#include <iostream>
#include <ostream>
#include "strkcpy.hpp"

int main()
{
        char arr[10];

        strkcpy(arr, "eka-eka-eka-eka-eka", sizeof(arr));
        std::cout << "\"" << arr << "\"\n";

        strkcpy(arr, "toka");
        std::cout << "\"" << arr << "\"\n";

        strkcpy(arr, "kolmas-kolmas-kolmas");
        std::cout << "\"" << arr << "\"\n";

        char *ptr = arr;

//      strkcpy(ptr, "-neljas");
        strkcpy(ptr, "+neljas", sizeof(arr));
        std::cout << "\"" << ptr << "\"\n";

}

Kommentit

Metabolix [20.03.2008 22:17:51]

#

Mainio vinkki, kaavainten tämä puoli jää usein vähemmälle käsittelylle.

Kirjoita kommentti

Muista lukea kirjoitusohjeet.
Tietoa sivustosta