Avatar billede jonas_h Nybegynder
13. januar 2009 - 20:37 Der er 22 kommentarer

Bitshifting i C#

Hvis jeg udfører følgende kode:
addressValue = (uint)(Convert.ToUInt32("Hej") << 24);
addressValue = addressValue | (uint)(Convert.ToUInt32("199") << 16);
addressValue = addressValue | (uint)(Convert.ToUInt32("234") << 16);
addressValue = addressValue | (uint)(Convert.ToUInt32("112") << 8);
addressValue = addressValue | (uint)(Convert.ToUInt32("322") << 16);

Nedenstående er en måde at representere en IP adresse i en uint-datatype. (Ip = 199.234.112.322 i eksemplet")

Nu er mit spørgsmål, hvordan man får "regnet tilbage" og får værdien af ip'en ud igen?
Avatar billede jonas_h Nybegynder
13. januar 2009 - 20:38 #1
addressValue = (uint)(Convert.ToUInt32("199") << 24);
addressValue = addressValue | (uint)(Convert.ToUInt32("234") << 16);
addressValue = addressValue | (uint)(Convert.ToUInt32("112") << 8);
addressValue = addressValue | (uint)(Convert.ToUInt32("322"));

Var lige lidt hurtig med ovenstående :) Dette skulel væer korrekt kode.
Avatar billede hmortensen Nybegynder
13. januar 2009 - 20:51 #2
Hvis det er til brug for IP adresser, kan du bruge IPAddress klassen:

public uint IpToUInt(string ip)
{
  return (uint)IPAddress.Parse(ip).Address;
}

public string IpFromUInt(uint ui)
{
  return (new IPAddress(ui)).ToString();
}
Avatar billede arne_v Ekspert
13. januar 2009 - 20:54 #3
Jeg ville bruge:

        public static int S2I(string addr)
        {
            return BitConverter.ToInt32(IPAddress.Parse(addr).GetAddressBytes(), 0);
        }
        public static string I2S(int addr)
        {
            return (new IPAddress(BitConverter.GetBytes(addr))).ToString();
        }

men det er ca. det samme.
Avatar billede arne_v Ekspert
13. januar 2009 - 20:54 #4
322 er ioevrigt ikke en valid byte vaerdi.
Avatar billede jonas_h Nybegynder
13. januar 2009 - 21:01 #5
322 var også hurtigt skrevet i eksemplet - ikke tænkt nærmere over det :)

Men grunden til, at jeg skal bruge alt dette er, at jeg skal kunne lave forskellige mængde-operationer på IP-adresser.

F.eks. har jeg en mængde med alle ip'er mellem 192.122.43.1 til 193.133.22.3
Og så skal jeg kunne sige, at jeg vil have returneret differens-mængden mellem førnævnte og f.eks. 192.125.2.2 til 192.155.3.3.

Så vidt jeg har kunne analysere mig frem til, kan man nemt gøre alt dette når de er konverteret til "bitniveau". Er det rigtigt forstået?
Avatar billede arne_v Ekspert
13. januar 2009 - 21:08 #6
Ja.

Men saa skal du have en integer repraesentation som har den rigtige endianess.
Avatar billede jonas_h Nybegynder
13. januar 2009 - 21:22 #7
Har lige afprøvet lidt.
s1: 539128001 : 193.112.34.32
s2: 539128769 : 193.115.34.32

t1: 539128000 : 192.112.34.32
t2: 539128002 : 194.112.34.32

Følgende værdier fås ud fra de ip'er som står ud for. Så vil man jo ikke kunne bruge f.eks. større end eller mindre end, da en ip som er "større" end en anden ikke er det ud fra bit-værdien.
Avatar billede jonas_h Nybegynder
13. januar 2009 - 21:28 #8
Hov nåede ikke at se hvad du skrev med endianess - det er måske dette du mener?
Avatar billede arne_v Ekspert
13. januar 2009 - 21:47 #9
Jep.
Avatar billede arne_v Ekspert
13. januar 2009 - 21:50 #10
Du kan bruge IPAddress.HostToNetworkOrder til at vende en integer med.
Avatar billede jonas_h Nybegynder
13. januar 2009 - 22:16 #11
Nu er det her emne ret nyt for mig - hvad skal jeg give HostToNetwork som input? Min int-repræsentation som jeg fik lavet ud fra din tidligere kode?
Avatar billede arne_v Ekspert
13. januar 2009 - 22:20 #12
Ja.
Avatar billede arne_v Ekspert
13. januar 2009 - 22:21 #13
Hm.

Faktisk skal du vel bruge IPAddress.NetworkToHostOrder, men de to metoder goer praecis det samme.

:-)
Avatar billede locke Nybegynder
13. januar 2009 - 22:25 #14
Om de gør det samme, afhænger vel af hardwaren, hvis man skal være helt korrekt.
Avatar billede jonas_h Nybegynder
13. januar 2009 - 22:27 #15
Okay kanon :)

Og når man skal konvertere tilbage veksler man vel bare mellem de to metoder du lige har henvist til.
Avatar billede arne_v Ekspert
13. januar 2009 - 22:27 #16
Faktisk ikke.

Paa little endian systemer som x86/x86-64 vender de begge int.

Paa big endian systemer som PPC goer de begge ingenting.
Avatar billede arne_v Ekspert
13. januar 2009 - 22:27 #17
Principielt ja.
Avatar billede cwboy Nybegynder
14. januar 2009 - 12:11 #18
Jeg bruger nedenstående funktioner. Mest fordi jeg ikke kendte de andre funktioner, som er nævnt ovenfor. De er måske bedre end mine :)


        /// <summary>
        /// Converts a string IP-address (w.x.y.z) to 32 bit signed integer
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <returns></returns>
        public static int IPToInt(string ipAddress)
        {
            string[] ip = ipAddress.Split('.');
            if (ip.Length != 4) throw new FormatException("IP address must be in the format 1.2.3.4");

            uint uIp = uint.Parse(ip[0]) * 256U * 256U * 256U +
                        uint.Parse(ip[1]) * 256U * 256U +
                        uint.Parse(ip[2]) * 256U +
                        uint.Parse(ip[3]);
           
            int iIp = (int)uIp;

            return iIp;
        }


        /// <summary>
        /// Converts a 32 bit signed integer to string IP-address (w.x.y.z)
        /// </summary>
        /// <param name="intIp"></param>
        /// <returns></returns>
        public static string IntToIP(int intIp)
        {
            uint uintIp = (uint)intIp;

            return string.Format("{0}.{1}.{2}.{3}",
                            (uintIp >> 24) & 255,
                            (uintIp >> 16) & 255,
                            (uintIp >> 8) & 255,
                            uintIp & 255);
        }
Avatar billede jonas_h Nybegynder
14. januar 2009 - 13:31 #19
Nu har jeg skrevet det meste kode vha. det andet :) Men ved I, om det er muligt hurtigt at få "næste" ip i rækken vha. en IP repræseneret som int?
Avatar billede arne_v Ekspert
14. januar 2009 - 14:53 #20
Hvis adressen er vendt rigtig (jaevnfoer ovenfor) kan du bare bruge +1.
Avatar billede cwboy Nybegynder
14. januar 2009 - 15:09 #21
arne_v: Vil det ikke give overflow, når man runder int.MaxValue?  Måske man bør bruge (int)(((uint)ipAsInteger)+1) eller lignende?
Avatar billede arne_v Ekspert
14. januar 2009 - 15:15 #22
God pointe.

Hvis man builder med check for arithmetisk overflow, saa skal man goere noget for at
haandtere det. Hvis man builder uden det check, saa virker det som det skal.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester