Teknologian jakaminen

[C-kieli] - Esikäsittelyn yksityiskohtainen selitys (osa 2)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Esipuhe

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.

7. # ja ##

7.1 # Operaattori

  • # 运算符 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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Mitä eroa on yllä olevien kahden koodirivin välillä? Katsotaan yhdessä:

Lisää kuvan kuvaus tähän

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

  
operaation tulos:

Lisää kuvan kuvaus tähän

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)
  • 1

  
en tiedä?Ymmärrät sen luettuasi alla olevan selityksen.
Lisää kuvan kuvaus tähän

  

7.2 ## operaattori

  ## 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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

  

Lisää kuvan kuvaus tähän

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;
		}
  • 1
  • 2
  • 3
  • 4
  • 5

  

#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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

  
operaation tulos:

Lisää kuvan kuvaus tähän

  
Voimme myös gcc gccgcc Tarkkaile esikäsiteltyjä tuloksia ympäristössä.i tiedostoa, ymmärrät sen intuitiivisemmin

Lisää kuvan kuvaus tähän

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:

Lisää kuvan kuvaus tähän

  

8. Nimeämissopimus

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.
  

Yhdeksän,# undef undefundef

  # undef undefundef Ohjeet ovat tottuneetPoista makron määritelmä

Lisää kuvan kuvaus tähän
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.

  

10. Komentorivin määritelmä

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)

Lisää kuvan kuvaus tähän

Lisää kuvan kuvaus tähän

Komentorivimääritys on sisäänesikäsittelyvaiheessaKäsitelty esikäsittelyvaiheessa yllä olevassa koodissa sz szsz Arvo on määritetty

  

11. Ehdollinen kokoaminen

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.
  

Lisää kuvan kuvaus tähän

  
Yleisesti käytetyt ehdollisen kokoamisohjeet:

11.1 Yksihaarainen ehdollinen kokoelma

#if 常量表达式
    //···
#endif
  • 1
  • 2
  • 3

Lisää kuvan kuvaus tähän

  

11.2 Monihaarainen ehdollinen kokoelma

#if  常量表达式
	//···
#elif  常量表达式
	//···
#else
	//···
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

  

11.3 Selvitä, onko se määritelty

#if defined(symbol)
#ifdef symbol

//上面两个的反面
if !defined(symbol)
#ifndef symbol
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Lisää kuvan kuvaus tähän

  

11.4 Sisäkkäiset ohjeet

#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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

  

12. Otsikkotiedostojen sisällyttäminen

12.1 Miten otsikkotiedostot sisällytetään

(1) Kuinka paikalliset tiedostot sisällytetään

# include "filename"
  • 1

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
  • 1

Vakiootsikkotiedostopolku VS-ympäristölle:

C:Program Files (x86)Microsoft Visual Studio 12.0VCinclude
//这是VS2013的默认路径
  • 1
  • 2

  

(2) Kirjastotiedosto sisältää

#include <filename.h>
  • 1

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?
  

12.2 Sisäkkäisten tiedostojen sisällyttäminen

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

testi. h testi.htest.h

void test();
struct Stu
{
int id;
char name[20];
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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
  • 1
  • 2
  • 3
  • 4

  
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ääriteltyhalutakoota
  • Välittömästi sen jälkeenMäärittele symboli __TEST_H__
  • Lisää sitten otsikkotiedosto uudelleen ja etsi __TEST_H__on määriteltyei enääSuorita myöhemmin sisällytettävälle otsikkotiedostollekoota

Yllä oleva kirjoitustapa on kuitenkin hankalampi.

#pragma once
  • 1

Vaikutus on sama kuin yllä olevassa menetelmässä
Tämä välttää otsikkotiedostojen toistuvan käyttöönoton
  

13. Muut esikäsittelyohjeet

#error
#pragma
#line
···
#pragma pack()//在结构体部分介绍
  • 1
  • 2
  • 3
  • 4
  • 5

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ä!