Hi all,

the following code prints garbage values. I want to read from an array two bytes and print then as a short int after doing ntohs.
What is the bug in the code?

Thanks and Regards,
Prashanth

#include<stdio.h>
struct converter {
   unsigned short int i;
};
main() {
   struct  converter * converts;
   char a[9]="12345678\0";
   converts = (struct converter*) (a + 0);

   printf("12 is printed %u\n", ntohs(converts->i));
}

What is the bug in the code?

#include <winsock.h> ?

Shouldn't you include <winsock.h> in your header?
That's where ntohs is found.

What compiler are you using?
Compiles fine with Borland 5.51 with winsock.h but generates an error when leaving out the winsock header.

Hank

Hi all,

the following code prints garbage values. I want to read from an array two bytes and print then as a short int after doing ntohs.
What is the bug in the code?

Thanks and Regards,
Prashanth

#include<stdio.h>
struct converter {
   unsigned short int i;
};
main() {
   struct  converter * converts;
   char a[9]="12345678\0";
   converts = (struct converter*) (a + 0);

   printf("12 is printed %u\n", ntohs(converts->i));
}

You realize that ch[9] is an array of characters not integers.

Try running this code...

#include<stdio.h>
struct converter {
   unsigned short int i;
};
main() {
   struct  converter * converts;
   char a[9]="12345678\0";
   converts = (struct converter*) (a + 0);

   printf("12 is printed %p\n", ntohs(converts->i));
}

it produces - 12 is printed 0x3132
Where 0x31 and 0x32 are the ascii values of 1 and 2

Also manpages has this to say about ntohs

htonl, htons, ntohl, ntohs - convert values between host and network
byte order

Of course it prints the ASCII values of 1 and 2, because when you created the string of characters you initialised it with ASCII characters so unsurprisingly that is the values contained.

When you say "I want to read from an array two bytes and print then as a short int" do you mean you want to from an array of 2 bytes containing ASCII values and display them as an integer or do you mean you want to read from an array of 2 bytes containing the binary representation on a short int in big endian format and display the short int value?

In the first case you need to use a function like strtol or aoti and in the second case you have you array initialisation completely wrong you want something like char a[9]={0, 12, 0, 0, 0, 0, 0, 0, 0};

Of course it prints the ASCII values of 1 and 2, because when you created the string of characters you initialised it with ASCII characters so unsurprisingly that is the values contained.

When you say "I want to read from an array two bytes and print then as a short int" do you mean you want to from an array of 2 bytes containing ASCII values and display them as an integer or do you mean you want to read from an array of 2 bytes containing the binary representation on a short int in big endian format and display the short int value?

In the first case you need to use a function like strtol or aoti and in the second case you have you array initialisation completely wrong you want something like char a[9]={0, 12, 0, 0, 0, 0, 0, 0, 0};

Hi My idea is as follows:
When data comes on the wire we usually store that data on to some buffer(char array). After that if we want two bytes from the buffer, we read those two bytes using a structure and this structure has a member of short int type. After that we do a ntohs on the data stored in the member of the structure and then print the data.
I was trying to simulate the same idea by storing in a char arryay a string.

Trying to simulate the idea is fine but to do that you have to have the correct data in the buffer.

If its a short buffer then use a debugger to set a break point at a point where the buffer is already loaded and copy the data. Alternitively print out the buffer. Alternitively if you have one sniff the data on the wire directly.

What is certain is that the data coming down the wire is not going to be ASCII data like the data you used to initialise your buffer.

Hi,
You are right. I was storing the char values which obviously would be converted in to ASCII and then stored in the array. But on the wire the data that we receive is all hex values. So I changed the array to hold hex values as shown in the code. But Im getting a new kind of problem: I'm storing first two bytes as 0x1 and 0x2.
Hence I would expect 12 to be printed when I use a short int to fetch the data from &a[0]. But I get the output as "12 is printed 1020304". How to fix this issue?
But if I use left shift operator for endianness, I get the correct result.

#include<stdio.h>
struct converter {
   unsigned  int i;
};
main() {
   struct  converter * converts;
//   char a[9]="12345678\0";
   char a[9] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x6, 0x7, 0x8};
   converts = (struct converter*) (a + 0);

   printf("12 is printed %x\n", ntohl(converts->i));
   converts->i = 0x1 << 4  | 0x2 << 0;
   printf("12 is printed %x\n",converts->i);
}

the output is :

12 is printed 1020304
12 is printed 12

This converts->i = 0x1 << 4 | 0x2 << 0; is basically dealing with nibbles (nominally 1/2 a byte, 4 bits) so the value is 0x12 = 18.

However it is normal to deal with bytes not nibbles and that is what ntohl operates on. Not only that but see the l (ell) on the end, that is the function that deals with longs or 4 bytes. It takes 4 bytes in big edian format and converts them to a long value in local machine format which you then output in hex.

What are the first 4 bytes of your array? 0x01, 0x02, 0x03, 0x04
What does it output? 1020304
See the correlation?

I can tell you that it is outputing the correct value given the data you supplied and that your manual calculation is not the calculation that ntohl is doing.

If you want to work on 16bit (short) values you might be better off using ntohs.

Hi,

thanks for the reply.
But why 0x1, 0x2, 0x3, 0x4 is converted to 1020304? Should it not be 01020304?

Regards,
Prashanth

Erm, 1020304 and 01020304 are the same number the second one just has a leading 0.

Hey, thanks for the reply. The discussions with you have consolidated my ideas.
After the modifications as per discussions with you I have the following code:

#include<stdio.h> struct converter { unsigned int i; }; main() { struct converter * converts; // char a[9]="12345678\0"; char a[9] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x6, 0x7, 0x8}; converts = (struct converter*) (a + 0); printf("l2 is printed without ntohl: %x\n", converts->i); printf("12 is printed with ntohl %x\n", ntohl(converts->i)); converts->i = 0x1 << 24 | 0x2 << 16 | 0x3 << 8 | 0x4 << 0; printf("12 is printed using the << operator for endianness %x\n",converts->i); }

[root@host4 ~]# ./a.out l2 is printed without ntohl: 4030201 12 is printed with ntohl 1020304 12 is printed using the << operator for endianness 1020304 [root@host4 ~]# [/coded][code=c]
#include<stdio.h>
struct converter {
unsigned int i;
};
main() {
struct converter * converts;
// char a[9]="12345678\0";
char a[9] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x6, 0x7, 0x8};
converts = (struct converter*) (a + 0);
printf("l2 is printed without ntohl: %x\n", converts->i);
printf("12 is printed with ntohl %x\n", ntohl(converts->i));
converts->i = 0x1 << 24 | 0x2 << 16 | 0x3 << 8 | 0x4 << 0;
printf("12 is printed using the << operator for endianness %x\n",converts->i);
}

[root@host4 ~]# ./a.out
l2 is printed without ntohl: 4030201
12 is printed with ntohl 1020304
12 is printed using the << operator for endianness 1020304
[root@host4 ~]#
[/coded]

Hey, thanks for the reply. The discussions with you have consolidated my ideas.
After the modifications as per discussions with you I have the following code:

#include<stdio.h>
struct converter {
unsigned int i;
};
main() {
struct converter * converts;
// char a[9]="12345678\0";
char a[9] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x6, 0x7, 0x8};
converts = (struct converter*) (a + 0);
printf("l2 is printed without ntohl: %x\n", converts->i);
printf("12 is printed with ntohl %x\n", ntohl(converts->i));
converts->i = 0x1 << 24 | 0x2 << 16 | 0x3 << 8 | 0x4 << 0;
printf("12 is printed using the << operator for endianness %x\n",converts->i);
}

[root@host4 ~]# ./a.out
l2 is printed without ntohl: 4030201
12 is printed with ntohl 1020304
12 is printed using the << operator for endianness 1020304
[root@host4 ~]#
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.