Кіріспе
C функциясы мәтінді пішімдеу және шығару үшін
printf – мәтінді пішімдеу және стандартты шығысқа жазу үшін C стандартты кітапханасының функциясы. printf атауы – «print formatted» (пішімделген басылым) сөзінің қысқартылған түрі, «print» (басылым) сөзі принтерге шығаруға сілтеме жасайды, бірақ функциялар принтерге шығарумен ғана шектелмейді. Стандартты кітапхана printf сияқты функциялар отбасын құрайтын көптеген басқа да ұқсас функцияларды ұсынады. Бұл функциялар пішім тізбегі параметрін және функция пішім тізбегі бойынша сериалдайтын және шығыс ағынына немесе тізбек буферіне жазатын өзгермелі сандық мән параметрлерін қабылдайды. Пішім тізбегі үлгі тілі ретінде кодталған, ол мәтін мен формат спецификаторларынан тұрады, олардың әрқайсысы мәнді қалай сериалдау керектігін анықтайды. Пішім тізбегі солдан оңға қарай өңделгенде, әрбір табылған формат спецификаторы үшін келесі мән қолданылады. Формат спецификаторы бір таңбадан басталады және мәнді қалай сериалдау керектігін анықтайтын бір немесе бірнеше келесі таңбадан тұрады. Пішім тізбегінің синтаксисі мен семантикасы printf сияқты отбасының барлық функциялары үшін бірдей. Формат спецификаторлары мен мәндердің саны мен типінің сәйкес келмеуі қатеге немесе қауіпсіздікке әкелуі мүмкін. printf пішім тізбегі scanf пішім тізбегіне толықтырады, ол пішімделген енгізуді қамтамасыз етеді (лексикалық талдау, басқаша айтқанда, синтаксистік талдау). Екі пішім тізбегі де басқа үлгілермен салыстырғанда салыстырмалы түрде қарапайым функционалдылықты ұсынады. Пішімдеу дизайны басқа бағдарламалау тілдерінде көшірілген.
1970 жылдар: C
1973 жылы Unix 4-ші нұсқасының құрамына C процедурасы ретінде қосылған.
1990 жылдар: Shell командасы
1990 жылы 4.3BSD Reno бөлігі ретінде shell командасы кездеседі. Ол стандартты кітапхана функциясының үлгісімен жасалған. 1991 жылы команда GNU shellutils (қазір GNU Core Utilities құрамында) жинағына қосылды.
Дәлдік өрісі
Дәлдік өрісі әдетте белгілі бір форматтау түріне байланысты шығыстың ең жоғары шегін көрсетеді. Қабаттағы сандық типтер үшін, ол шығыс ондық нүктеден кейін қанша таңбаға дейін дөңгелектелу керектігін анықтайды. Строкалық тип үшін, ол шығарылатын таңбалардың санын шектейді, содан кейін строка қысқартылады. Дәлдік өрісін жіберуге болады, немесе сандық бүтін сан мәнін, немесе жұлдызша арқылы белгіленгенде, басқа аргумент ретінде берілгенде динамикалық мән болуы мүмкін. Мысалы, шығарады.
Өзіндік дерек түрі пішімдеуі
Өзгешелендірілген деректер түрімен пішімдеуді басқарудың ең көп қолданылатын тәсілі – деректер түрінің мәнін жолға түрлендіріп, содан кейін сериалданған мәнді үлкен хабарламаға енгізу үшін спецификаторды пайдалану болып табылады. Кейбір printf сияқты функциялар escape символына негізделген шағын тілге кеңейтулерді қоюға мүмкіндік береді, осылайша бағдарламашыға кіріктірілмеген типтер үшін арнайы пішімдеу функциясын қолдануға болады. Мысалы, (қазір қолданыстан шығарылған) glibc. Бірақ ол статикалық пішімді тізбектерді тексеруге кедергі келтіретіндіктен, көбінесе қолданылмайды. Тағы бір нұсқа – Vstr бейімделген форматтаушылары, олар көп символдан тұратын форматтағы атауларды қосуға мүмкіндік береді. Кейбір қолданбалар (мысалы, Apache HTTP сервері) өздерінің printf сияқты функциясын құрастырып, оған кеңейтімдерді енгізеді. Дегенмен, олардың барлығы дерлік сол мәселелерге тап болады. Linux ядросының printk функциясы қосымша пішімдеу таңбаларын қосу арқылы ядролық құрылымдарды көрсетудің бірнеше жолын қолдайды, осы арқылы жалпы спецификацияны пайдалануға болады. Мысалы, IPv4 адресін ондық нүктелі форматта шығарады. Бұл қалыпты printf-пен толық үйлесімділіктен айырмашылығы, (бөліктің) статикалық пішімді тізбектерді тексеруге мүмкіндік береді.
Отбасы
Форматтау мүмкіндіктерін ұсынатын, бірақ қосымша немесе сәл өзгеше әрекет ететін нұсқалары бар. Стандартты шығыстан өзге жерге шығаруға мүмкіндік беретін жүйелік файлдық объектіге шығарады. Стандартты шығу орнына жол буферіне жазады. Шақырушы буферге жазуға болатын максималды символдар санын анықтайтын ұзындығы (n) параметрін ұсынатындықтан, -дан қауіпсіздік деңгейін қамтамасыз етеді. printf функцияларының көпшілігі үшін, өзгермелі ұзындығы бар параметрлер тізімінен гөрі, қабылдайтын нұсқасы бар. Мысалы, , , функциялары бар.
Формат тізбегі шабуыл
Қосымша параметрлер назарға алынбайды, бірақ формат жолындағы формат спецификаторларының саны, берілген мән параметрлерінен көп болса, мінез-құлқы белгісіз болады. Кейбір C компиляторларында, артық формат спецификаторы болмаған жағдайда да, мәнді тұтынуы мүмкін. Бұл формат жолы арқылы шабуыл жасауға мүмкіндік береді. Әдетте, C тілінде аргументтер стекке жіберіледі. Егер жеткілікті аргументтер берілмесе, printf стек фреймінің соңынан асып оқуы мүмкін, соның салдарынан шабуылшы стек туралы ақпаратты оқи алады. Кейбір компиляторлар, мысалы GNU Compiler Collection, printf сияқты функциялардың формат жолын статикалық түрде тексереді және проблемалар туралы ескертеді (немесе флагтарын қолданғанда). GCC сондай-ақ, егер функцияға стандартты емес "format" атрибуты қолданылса, пайдаланушы анықтаған printf стиліндегі функциялар туралы ескертеді.
Қадағалаусыз пішім тізбегі эксплойты
Формат жолы көбінесе функцияны шақырудың статикалық талдауын жүргізуге мүмкіндік беретін мәтіндік тұрақты болып табылады. Дегенмен, формат жолы айнымалының мәні болуы мүмкін, бұл динамикалық пішімдеуге мүмкіндік береді, бірақ сонымен қатар бақылаусыз формат жолымен шабуыл деп аталатын қауіпсіздік осалдығына да әкелуі мүмкін.
Жадына жазу
Беттегі шығару функциясы аргумент арқылы жад орнына жазуға мүмкіндік береді. Бұл мүмкіндік кейде күрделі форматты қатарға шабуыл жасаудың бір бөлігі ретінде қолданылады. Функционалдылық сонымен қатар, тіпті дұрыс құрылған аргументтер жиынтығымен де кездейсоқ түрде толыққанды Тьюринг машинасына айналуы мүмкін. Форматты қатармен жазылған крестики-нолики ойыны 27-ші IOCCC жеңімпазы болды.