2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
viimeisessä numerossa[C-kieli] - Esikäsittelyn yksityiskohtainen selitys (osa 2) Opinnäytetyön aikana esittelimme yksityiskohtaisesti makrojen asiantuntemusta esikäsittelyssä. Uskon, että jokainen saa paljon. Älä huoli, jatketaan muiden tietojen oppimista esikäsittelystä tässä numerossa.
# 运算符
Muuntaa makron argumentin merkkijonoliteraaliksi.Se saa näkyä makrojen korvausluettelossa parametreilla.# 运算符
Suoritettu operaatio voidaan ymmärtää "joustoiksi"
Mitä tuo tarkoittaa?
Tehdään ensin esikuva:
int mian()
{
printf("hello" "worldn");
printf("helloworldn");
return 0;
}
Mitä eroa on yllä olevien kahden koodirivin välillä? Katsotaan yhdessä:
Kuten näet, kahden merkkijonon ja yhden merkkijonon vaikutus on sama.C语言会把两个字符串天然连成一个字符串
, välilyönnin lisääminen keskelle on turhaa.
Nyt on tällainen kohtaus:
int main()
{
int a = 1;
printf("The value of a is %dn", a);
int b = 20;
printf("The value of b is %dn", b);
float f = 8.5f;
printf("The value of f is %fn", f);
return 0;
}
Huomasimme, että kolmen koodirivin logiikka on hyvin相像
Kyllä, mutta niitä on些许不同
。
Joten ajattelimme, että koska ne ovat niin samanlaisia, voisimmeko laittaa ne封装成一个函数
, käytön helpottamiseksi?
Mutta toiminnot eivät voi suorittaa tätä toimintoa.
mitä sitten pitäisi tehdä?
Voimme yrittää käyttää makroja sen ratkaisemiseen
#define Print(n, format) printf("The value of n is " format "n", n)
int main()
{
int a = 1;
Print(a, "%d");
//printf("The value of a is %dn", a);
int b = 20;
Print(b, "%d");
//printf("The value of b is %dn", b);
float f = 8.5f;
Print(f, "%f");
//printf("The value of f is %fn", f);
return 0;
}
operaation tulos:
löydämme nnn Se ei ole muuttunut, joten miten minun pitäisi muokata sitä?
Tässä tulee käyttää #-operaattoria:# Muuntaa makron argumentin muotoonmerkkijono literaali,Juuri nyt nnn tulla "n" "n"“n”
Tällä hetkellä voimme käyttää liitosmenetelmää tullakseen
#define Print(n, format) printf("The value of " #n " is " format "n", n)
en tiedä?Ymmärrät sen luettuasi alla olevan selityksen.
##
voi sijaita hänessäMolemmilla puolilla olevat symbolit on yhdistetty yhdeksi symboliksi, joka mahdollistaa makromäärittelyn从分离的文本片段创建标识符
。##
kutsutaanmerkin liimaus .Tällaisen yhteyden tulee tuottaa a合法
indikaattori, muuten tulos on määrittelemätön.
Olemme sanoneet aiemmin, että kirjoittaaksesi funktion, joka löytää kahden luvun suuremman arvon, sinun on kirjoitettava eri funktioita eri tietotyypeille.
int int_max(int x, int y)
{
return x > y ? x : y;
}
float float_max(float x, float y)
{
return x > y ? x : y;
}
Tämä on väistämättä liian hankalaa, ja näiden kahden toiminnon välillä on monia yhtäläisyyksiä.
Onko mahdollista luoda nopeasti tällainen toiminto?kuin toimintoMuottiSama, käytä vain funktiota ja se tulee ulos
Voimme kirjoittaa tällaisen宏
:
#define GENERIC_MAX(type)
type type##_max(type x, type y)
{
return x > y ? x : y;
}
#define GENERIC_MAX(type)
type type##_max(type x, type y)
{
return x > y ? x : y;
}
GENERIC_MAX(int); //相当于定义了一个函数int_max
GENERIC_MAX(float); //相当于定义了一个函数float_max
int main()
{
int r1 = int_max(3, 5);
printf("%dn", r1);
float r2 = float_max(2.3f, 7.6f);
printf("%fn", r2);
return 0;
}
operaation tulos:
Voimme myös gcc gccgcc Tarkkaile esikäsiteltyjä tuloksia ympäristössä.i
tiedostoa, ymmärrät sen intuitiivisemmin
Tietenkin tällä tavalla luotu toiminto on myös hankala virheenkorjaus.
Sitten tänne ##
Mikä rooli sillä on?
lisätä ##
, kääntäjä pitää niitä symbolina
Katsotaanpa Kangaa##
Vaikutus:
Yleisesti ottaen funktioiden ja makrojen syntaksi on hyvin samanlainen, joten语言本身没法帮我们区分二者
Yksi tavallisista tavoistamme on:
- Nimeä makrokaikki korkit
- Toiminnon nimiÄlä käytä kaikkia kirjaimia
Nämä nimeämissäännöt eivät tietenkään ole ehdottomia
esimerkiksi offset offsetoffset Tämä makro on kirjoitettu pienillä kirjaimilla
Huomautus: offset offsetoffset Sitä käytetään laskemaan rakenneosien siirtymä suhteessa rakenteen alkuasentoon.
# undef undefundef Ohjeet ovat tottuneetPoista makron määritelmä
Yllä olevaa koodia käytetään rivillä 169# undef undefundef Poistettu makro MAX.Ei ongelmia soitettaessa 168 linjaan ennen poistamista, mutta 170 linjaan soitettaessa tulee virheilmoitus poiston jälkeen.
Monet C-kääntäjät (ei sisällä VS:ää) tarjoavat mahdollisuuden määritellä symboleja komentorivillä.Käytetään kokoamisprosessin aloittamiseen
Esimerkiksi : Tämä ominaisuus on hyödyllinen, kun haluamme kääntää eri versioita ohjelmasta saman lähdetiedoston perusteella. (Oletetaan, että ohjelmassa on ilmoitettu tietynpituinen taulukko. Jos koneen muisti on rajallinen, tarvitsemme hyvin pienen taulukon, mutta jos toisen koneen muisti on suurempi, tarvitsemamme taulukko voi olla suurempi)
Komentorivimääritys on sisäänesikäsittelyvaiheessaKäsitelty esikäsittelyvaiheessa yllä olevassa koodissa sz szsz Arvo on määritetty
Ohjelmaa käännettäessä on erittäin vaikeaa kääntää tai luopua siitä (lauseryhmästä).方便
/.koska voimme käyttääehdollinen kokoamisohje
Ehdollinen käännösohje on tämä koodi我想让你编译就编译,不想让你编译你就不要编译了
. Voimme asettaa hänelle ehdon. Jos ehto on tosi, tämä koodi käännetään, jos ehto on epätosi.
Esimerkiksi:
Olisi sääli poistaa virheenkorjauskoodia, mutta se haittaisi sen säilyttämistä, jotta voimme valikoivasti kääntää sen.
Yleisesti käytetyt ehdollisen kokoamisohjeet:
#if 常量表达式
//···
#endif
#if 常量表达式
//···
#elif 常量表达式
//···
#else
//···
#endif
Mikä väite on totta, se väite suoritetaan
#define M 1
int main()
{
#if M == 0
printf("hellon");
#elif M == 1
printf("worldn");
#elif M == 2
printf("csdnn");
#endif
printf("886n");
return 0;
}
#if defined(symbol)
#ifdef symbol
//上面两个的反面
if !defined(symbol)
#ifndef symbol
#if defined(OS_UNIX)
#ifdef OPTION1
unix_version_option1();
#endif
#ifdef OPTION2
unix_version_option2();
#endif
#elif defined(OS_MSDOS)
#ifdef OPTION2
msdos_version_option2();
#endif
#endif
# include "filename"
Hakustrategia: ensinProjektihakemisto, jossa lähdetiedostot sijaitsevatJos otsikkotiedostoa ei löydy, kääntäjä etsii kirjastofunktion otsikkotiedostoa samalla tavalla.Normaali sijainnin hakupää Tiedosto
Jos et löydä sitä uudelleenKäännösvirhe
L inux LinuxLsisäänux Ympäristön normaali otsikkotiedostopolku (johon otsikkotiedosto sijoitetaan):
/usr/include
Vakiootsikkotiedostopolku VS-ympäristölle:
C:Program Files (x86)Microsoft Visual Studio 12.0VCinclude
//这是VS2013的默认路径
#include <filename.h>
Etsi otsikkotiedosto ja siirry suoraan kohtaanvakiopolkuMene ja etsi, ja jos et löydä sitä, saat kehotteen.Käännösvirhe。
Tarkoittaako tämä, että sitä voidaan käyttää myös kirjastotiedostoille?“ ”
Lomake sisältää
vastaus onvahvistaaKyllä, mutta haku tehdään tällä tavallavähemmän tehokasta, tietysti myös näinei ole helppo erottaaOnko se kirjastotiedosto vai paikallinen tiedosto?
Tutkittuamme edellistä (kääntäminen ja linkittäminen) tiedämme, että otsikkotiedosto on mukana esikäsittelyvaiheessa.直接将该文件的代码拷贝到包含头文件的地方
Jos otsikkotiedosto sisällytetään 10 kertaa, se käännetään itse asiassa 10 kertaa, jos se sisällytetään toistuvasti, käännöspaine on suurempi.
testi. c testi.ctest.c
#include "test.h"
#include "test.h"
#include "test.h"
#include "test.h"
#include "test.h"
int main()
{
return 0;
}
testi. h testi.htest.h
void test();
struct Stu
{
int id;
char name[20];
};
Mutta projektissa tiedosto sisällytetään väistämättä useita kertoja, joten kuinka ratkaista tämä ongelma?
Vastaus:ehdollinen kokoelma
#ifndef __TEST_H__
#define __TEST_H__
//头文件的内容
#endif
Miten se ymmärretään?
- Kun sisällytät otsikkotiedoston ensimmäistä kertaa, pitäisikö se kääntää?tuomari ensin
- Symboli __TEST_H__ ei oleei määritelty,halutakoota
- Välittömästi sen jälkeenMäärittele symboli __TEST_H__
- Lisää sitten otsikkotiedosto uudelleen ja etsi __TEST_H__on määritelty,ei enääSuorita myöhemmin sisällytettävälle otsikkotiedostollekoota
Yllä oleva kirjoitustapa on kuitenkin hankalampi.
#pragma once
Vaikutus on sama kuin yllä olevassa menetelmässä
Tämä välttää otsikkotiedostojen toistuvan käyttöönoton
#error
#pragma
#line
···
#pragma pack()//在结构体部分介绍
Kiinnostuneet ystävät voivat lukea "C-kielen syvällinen anatomia"
Okei, tässä on kaikki tiedot esikäsittelystä tässä numerossa. Toivon, että tämä blogi voi olla hyödyllinen sinulle. Samalla korjatkaa jos on virheitä ja edistykäämme yhdessä C-kielen oppimisen tiellä!