5.13.5.2.2.1.1.3.3. Floating point
Not like variant integer constants there, in C++ front-end, constant of REAL_TYPE type can only be REAL_CST.
output_constant (continue)
3791 case REAL_TYPE:
3792 if (TREE_CODE (exp) != REAL_CST)
3793 error ("initializer for floating value is not a floating constant");
3794
3795 assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);
3796 break ;
The detail about floating point constant has been covered in section Create node for real constant , we would not repeat here again.
1918 void
1919 assemble_real (REAL_VALUE_TYPE d, enum machine_mode mode, unsigned int align)
1920 {
1921 long data[4];
1922 int i;
1923 int bitsize, nelts, nunits, units_per;
1924
1925 /* This is hairy. We have a quantity of known size. real_to_target
1926 will put it into an array of *host* longs, 32 bits per element
1927 (even if long is more than 32 bits). We need to determine the
1928 number of array elements that are occupied (nelts) and the number
1929 of *target* min-addressable units that will be occupied in the
1930 object file (nunits). We cannot assume that 32 divides the
1931 mode's bitsize (size * BITS_PER_UNIT) evenly.
1932
1933 size * BITS_PER_UNIT is used here to make sure that padding bits
1934 (which might appear at either end of the value; real_to_target
1935 will include the padding bits in its output array) are included. */
1936
1937 nunits = GET_MODE_SIZE (mode);
1938 bitsize = nunits * BITS_PER_UNIT;
1939 nelts = CEIL (bitsize, 32);
1940 units_per = 32 / BITS_PER_UNIT;
1941
1942 real_to_target (data, &d, mode);
1943
1944 /* Put out the first word with the specified alignment. */
1945 assemble_integer (GEN_INT (data[0]), MIN (nunits, units_per), align, 1);
1946 nunits -= units_per;
1947
1948 /* Subsequent words need only 32-bit alignment. */
1949 align = min_align (align, 32);
1950
1951 for (i = 1; i < nelts; i++)
1952 {
1953 assemble_integer (GEN_INT (data[i]), MIN (nunits, units_per), align, 1);
1954 nunits -= units_per;
1955 }
1956 }
Above at line 1942, the kernel of real_to_target is function round_for_format , and the format encoding function in structure real_format associating with the target machine (generally is encode_ieee_single or encode_ieee_double ).
5.13.5.2.2.1.1.3.4. Literal string
Literal string, in C/C++, is treated as constant by default, it is built with node STRING_CST.
output_constant (continue)
3798 case COMPLEX_TYPE:
3799 output_constant (TREE_REALPART (exp), thissize / 2, align);
3800 output_constant (TREE_IMAGPART (exp), thissize / 2,
3801 min_align (align, BITS_PER_UNIT * (thissize / 2)));
3802 break ;
3803
3804 case ARRAY_TYPE:
3805 case VECTOR_TYPE:
3806 if (TREE_CODE (exp) == CONSTRUCTOR)
3807 {
3808 output_constructor (exp, size, align);
3809 return ;
3810 }
3811 else if (TREE_CODE (exp) == STRING_CST)
3812 {
3813 thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp),
3814 size);
3815 assemble_string (TREE_STRING_POINTER (exp), thissize);
3816 }
3817 else if (TREE_CODE (exp) == VECTOR_CST)
3818 {
3819 int elt_size;
3820 tree link;
3821 unsigned int nalign;
3822 enum machine_mode inner;
3823
3824 inner = GET_MODE_INNER (TYPE_MODE (TREE_TYPE (exp)));
3825 nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
3826
3827 elt_size = GET_MODE_UNIT_SIZE (TYPE_MODE (TREE_TYPE (exp)));
3828
3829 link = TREE_VECTOR_CST_ELTS (exp);
3830 output_constant (TREE_VALUE (link), elt_size, align);
3831 while ((link = TREE_CHAIN (link)) != NULL)
3832 output_constant (TREE_VALUE (link), elt_size, nalign);
3833 }
3834 else
3835 abort ();
3836 break ;
STRING_CST just encuplsates literal string simply, by TREE_STRING_POINTER and TREE_STRING_LENGTH can fetch the string and its length.
1190 void
1191 assemble_string (const char *p, int size) in varasm.c
1192 {
1193 int pos = 0;
1194 int maximum = 2000;
1195
1196 /* If the string is very long, split it up. */
1197
1198 while (pos < size)
1199 {
1200 int thissize = size - pos;
1201 if (thissize > maximum)
1202 thissize = maximum;
1203
1204 ASM_OUTPUT_ASCII (asm_out_file , p, thissize);
1205
1206 pos += thissize;
1207 p += thissize;
1208 }
1209 }
To avoid violating the limitation of section size, every block is not larger than 2000 characters. Below macro output the string. At line 452, STRING_LIMIT is defined as 256. That is if the string (or the left part) is less than 256 characters, it is output by ASM_OUTPUT_LIMITED_STRING, this macro is quite similar with ASM_OUTPUT_ASCII here. At line 445 and 456, it outputs character ” and breaks the line. Conceivable, the macro will output like this:
“………”
“………”
430 #undef ASM_OUTPUT_ASCII
431 #define ASM_OUTPUT_ASCII (FILE, STR, LENGTH) / in elfos.h
432 do /
433 { /
434 register const unsigned char *_ascii_bytes = /
435 (const unsigned char *) (STR); /
436 register const unsigned char *limit = _ascii_bytes + (LENGTH); /
437 register unsigned bytes_in_chunk = 0; /
438 /
439 for (; _ascii_bytes < limit; _ascii_bytes++) /
440 { /
441 register const unsigned char *p; /
442 /
443 if (bytes_in_chunk >= 60) /
444 { /
445 fprintf ((FILE), "/"/n"); /
446 bytes_in_chunk = 0; /
447 } /
448 /
449 for (p = _ascii_bytes; p < limit && *p != '/0'; p++) /
450 continue ; /
451 /
452 if (p < limit && (p - _ascii_bytes) <= (long)STRING_LIMIT) /
453 { /
454 if (bytes_in_chunk > 0) /
455 { /
456 fprintf ((FILE), "/"/n"); /
457 bytes_in_chunk = 0; /
458 } /
459 /
460 ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); /
461 _ascii_bytes = p; /
462 } /
463 else /
464 { /
465 register int escape; /
466 register unsigned ch; /
467 /
468 if (bytes_in_chunk == 0) /
469 fprintf ((FILE), "%s/"", ASCII_DATA_ASM_OP); /
470 /
471 switch (escape = ESCAPES[ch = *_ascii_bytes]) /
472 { /
473 case 0: /
474 putc (ch, (FILE)); /
475 bytes_in_chunk++; /
476 break ; /
477 case 1: /
478 fprintf ((FILE), "//%03o", ch); /
479 bytes_in_chunk += 4; /
480 break ; /
481 default : /
482 putc ('//', (FILE)); /
483 putc (escape, (FILE)); /
484 bytes_in_chunk += 2; /
485 break ; /
486 } /
487 } /
488 } /
489 /
490 if (bytes_in_chunk > 0) /
491 fprintf ((FILE), "/"/n"); /
492 } /
493 while (0)
At line 469, ASCII_DATA_ASM_OP is defined as “/t.ascii/t”, and ESCAPES at line 471 is the string below.
"/1/1/1/1/1/1/1/1btn/1fr/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/
/0/0/"/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/
/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0///0/0/0/
/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/0/1/
/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/
/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/
/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/
/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1/1"
It indicates who to output the corresponding ASCII character.
5.13.5.2.2.1.1.3.5. For aggregate type
If aggregate type has initializer (the case of empty initializer is handled at line 3756 in output_constant , refers to section Content of 0 ), it comes into below code.
output_constant (continue)
3838 case RECORD_TYPE:
3839 case UNION_TYPE:
3840 if (TREE_CODE (exp) == CONSTRUCTOR)
3841 output_constructor (exp, size, align);
3842 else
3843 abort ();
3844 return ;
3845
3846 case SET_TYPE:
3847 if (TREE_CODE (exp) == INTEGER_CST)
3848 assemble_integer (expand_expr (exp, NULL_RTX,
3849 VOIDmode, EXPAND_INITIALIZER),
3850 thissize, align, 1);
3851 else if (TREE_CODE (exp) == CONSTRUCTOR)
3852 {
3853 unsigned char *buffer = alloca (thissize);
3854 if (get_set_constructor_bytes (exp, buffer, thissize))
3855 abort ();
3856 assemble_string ((char *) buffer, thissize);
3857 }
3858 else
3859 error ("unknown set constructor type");
3860 return ;
3861
3862 case ERROR_MARK:
3863 return ;
3864
3865 default :
3866 abort ();
3867 }
3868
3869 if (size > thissize)
3870 assemble_zeros (size - thissize);
3871 }
In previous, we have seen that in CONSTRUCTOR node, its CONSTRUCTOR_ELTS is a tree_list containing initializer for every member. In every node in this list, the TREE_VALUE field is the initializer, and TREE_PURPOSE field, for class type is FIELD_DECL node, while for arrary type, is the index.
3918 static void
3919 output_constructor (tree exp, unsigned HOST_WIDE_INT size, in varasm.c
3920 unsigned int align)
3921 {
3922 tree type = TREE_TYPE (exp);
3923 tree link, field = 0;
3924 tree min_index = 0;
3925 /* Number of bytes output or skipped so far.
3926 I n other words, current position within the constructor. */
3927 HOST_WIDE_INT total_bytes = 0;
3928 /* Nonzero means BYTE contains part of a byte, to be output. */
3929 int byte_buffer_in_use = 0;
3930 int byte = 0;
3931
3932 if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT)
3933 abort ();
3934
3935 if (TREE_CODE (type) == RECORD_TYPE)
3936 field = TYPE_FIELDS (type);
3937
3938 if (TREE_CODE (type) == ARRAY_TYPE
3939 && TYPE_DOMAIN (type) != 0)
3940 min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
3941
3942 /* As LINK goes through the elements of the constant,
3943 FIELD goes through the structure fields, if the constant is a structure.
3944 if the constant is a union, then we override this,
3945 by getting the field from the TREE_LIST element.
3946 But the constant could also be an array. Then FIELD is zero.
3947
3948 There is always a maximum of one element in the chain LINK for unions
3949 (even if the initializer in a source program incorrectly contains
3950 more one). */
3951 for (link = CONSTRUCTOR_ELTS (exp);
3952 link;
3953 link = TREE_CHAIN (link),
3954 field = field ? TREE_CHAIN (field) : 0)
3955 {
3956 tree val = TREE_VALUE (link);
3957 tree index = 0;
3958
3959 /* The element in a union constructor specifies the proper field
3960 or index. */
3961 if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
3962 || TREE_CODE (type) == QUAL_UNION_TYPE)
3963 && TREE_PURPOSE (link) != 0)
3964 field = TREE_PURPOSE (link);
3965
3966 else if (TREE_CODE (type) == ARRAY_TYPE)
3967 index = TREE_PURPOSE (link);
3968
3969 #ifdef ASM_COMMENT_START
3970 if (field && flag_verbose_asm )
3971 fprintf (asm_out_file , "%s %s:/n",
3972 ASM_COMMENT_START,
3973 DECL_NAME (field)
3974 ? IDENTIFIER_POINTER (DECL_NAME (field))
3975 : "<anonymous>");
3976 #endif
3977
3978 /* Eliminate the marker that makes a cast not be an lvalue. */
3979 if (val != 0)
3980 STRIP_NOPS (val);
Note that above for array, variable field is NULL, it uses variable index instead; vice verse for class type. At line 3980, STRIP_NOPS strips the encuplsations not affecting the assemble output (for instance conversion needs not code generated).
output_constructor (continue)
3982 if (index && TREE_CODE (index) == RANGE_EXPR)
3983 {
3984 unsigned HOST_WIDE_INT fieldsize
3985 = int_size_in_bytes (TREE_TYPE (type));
3986 HOST_WIDE_INT lo_index = tree_low_cst (TREE_OPERAND (index, 0), 0);
3987 HOST_WIDE_INT hi_index = tree_low_cst (TREE_OPERAND (index, 1), 0);
3988 HOST_WIDE_INT index;
3989 unsigned int align2 = min_align (align, fieldsize * BITS_PER_UNIT);
3990
3991 for (index = lo_index; index <= hi_index; index++)
3992 {
3993 /* Output the element's initial value. */
3994 if (val == 0)
3995 assemble_zeros (fieldsize);
3996 else
3997 output_constant (val, fieldsize, align2);
3998
3999 /* Count its size. */
4000 total_bytes += fieldsize;
4001 }
4002 }
The front-end node RANGE_EXPR is used for array, to represent elements within a range. For example,
int a [8] = {0};
whose initializer is a RANGE_EXPR, stands for using value 0 within range from index 0 to 7. In above, can see that, its first operand is the lower limit, and the second operand is the upper one. In C++, initializer in RANGE_EXPR can only be 0.
Nodes satisfying condition at line 4003 below are: array (field is NULL), non-bit-field member. Variable pos holds the position the initializer applied. For class member, as the layout has been done, int_byte_position at line 4010 invokes byte_position to get the offset to the class head. For array, by element size x index span, can get the offset to the array head (line 4014).
output_constructor (continue)
4003 else if (field == 0 || !DECL_BIT_FIELD (field))
4004 {
4005 /* An element that is not a bit-field. */
4006
4007 unsigned HOST_WIDE_INT fieldsize;
4008 /* Since this structure is static,
4009 we know the positions are constant. */
4010 HOST_WIDE_INT pos = field ? int_byte_position (field) : 0;
4011 unsigned int align2;
4012
4013 if (index != 0)
4014 pos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)
4015 * (tree_low_cst (index, 0) - tree_low_cst (min_index, 0)));
4016
4017 /* Output any buffered-up bit-fields preceding this element. */
4018 if (byte_buffer_in_use)
4019 {
4020 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
4021 total_bytes++;
4022 byte_buffer_in_use = 0;
4023 }
4024
4025 /* Advance to offset of this element.
4026 Note no alignment needed in an array, since that is guaranteed
4027 if each element has the proper size. */
4028 if ((field != 0 || index != 0) && pos != total_bytes)
4029 {
4030 assemble_zeros (pos - total_bytes);
4031 total_bytes = pos;
4032 }
4033
4034 /* Find the alignment of this element. */
4035 align2 = min_align (align, BITS_PER_UNIT * pos);
4036
4037 /* Determine size this element should occupy. */
4038 if (field)
4039 {
4040 fieldsize = 0;
4041
4042 /* If this is an array with an unspecified upper bound,
4043 the initializer determines the size. */
4044 /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL,
4045 but we cannot do this until the deprecated support for
4046 initializing zero-length array members is removed. */
4047 if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
4048 && TYPE_DOMAIN (TREE_TYPE (field))
4049 && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
4050 {
4051 fieldsize = array_size_for_constructor (val);
4052 /* Given a non-empty initialization, this field had
4053 better be last. */
4054 if (fieldsize != 0 && TREE_CHAIN (field) != NULL_TREE)
4055 abort ();
4056 }
4057 else if (DECL_SIZE_UNIT (field))
4058 {
4059 /* ??? This can't be right. If the decl size overflows
4060 a host integer we will silently emit no data. */
4061 if (host_integerp (DECL_SIZE_UNIT (field), 1))
4062 fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
4063 }
4064 }
4065 else
4066 fieldsize = int_size_in_bytes (TREE_TYPE (type));
4067
4068 /* Output the element's initial value. */
4069 if (val == 0)
4070 assemble_zeros (fieldsize);
4071 else
4072 output_constant (val, fieldsize, align2);
4073
4074 /* Count its size. */
4075 total_bytes += fieldsize;
4076 }
Variable total_bytes records the size of the part initialized. For class, C++ requires to initialize members in order of declaration (the front-end does the layout by that order), so if pos doesn’t equate to total_bytes , it means between pos and total_bytes is an area need padding. By standard, it should be padded with 0. For array, as elements are of the same size, there is no padding area between elements, if pos doesn’t equate to total_bytes , it means elements within the range aren’t given, and by standard, it should be initialized by 0. At line 4018, variable byte_buffer_in_use comes from bit-field handling below.
Thus below code is the treatment of bit-field in class. First, its initializer must be an integer constant, condition at line 4077 ensures this. Besides, between the bit-field and the field ahead, it may be a padding area, line 4098 finishes this padding.
output_constructor (continue)
4077 else if (val != 0 && TREE_CODE (val) != INTEGER_CST)
4078 error ("invalid initial value for member `%s'",
4079 IDENTIFIER_POINTER (DECL_NAME (field)));
4080 else
4081 {
4082 /* Element that is a bit-field. */
4083
4084 HOST_WIDE_INT next_offset = int_bit_position (field);
4085 HOST_WIDE_INT end_offset
4086 = (next_offset + tree_low_cst (DECL_SIZE (field), 1));
4087
4088 if (val == 0)
4089 val = integer_zero_node;
4090
4091 /* If this field does not start in this (or, next) byte,
4092 skip some bytes. */
4093 if (next_offset / BITS_PER_UNIT != total_bytes)
4094 {
4095 /* Output remnant of any bit field in previous bytes. */
4096 if (byte_buffer_in_use)
4097 {
4098 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
4099 total_bytes++;
4100 byte_buffer_in_use = 0;
4101 }
4102
4103 /* If still not at proper byte, advance to there. */
4104 if (next_offset / BITS_PER_UNIT != total_bytes)
4105 {
4106 assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes);
4107 total_bytes = next_offset / BITS_PER_UNIT;
4108 }
4109 }
4110
4111 if (! byte_buffer_in_use)
4112 byte = 0;
4113
4114 /* We must split the element into pieces that fall within
4115 separate bytes, and combine each byte with previous or
4116 following bit-fields. */
4117
4118 /* next_offset is the offset n fbits from the beginning of
4119 the structure to the next bit of this element to be processed.
4120 end_offset is the offset of the first bit past the end of
4121 this element. */
4122 while (next_offset < end_offset)
4123 {
4124 int this_time;
4125 int shift;
4126 HOST_WIDE_INT value;
4127 HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
4128 HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
4129
4130 /* Advance from byte to byte
4131 within this element when necessary. */
4132 while (next_byte != total_bytes)
4133 {
4134 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
4135 total_bytes++;
4136 byte = 0;
4137 }
4138
4139 /* Number of bits we can process at once
4140 (all part of the same byte). */
4141 this_time = MIN (end_offset - next_offset,
4142 BITS_PER_UNIT - next_bit);
4143 if (BYTES_BIG_ENDIAN)
4144 {
4145 /* On big-endian machine, take the most significant bits
4146 first (of the bits that are significant)
4147 and put them into bytes from the most significant end. */
4148 shift = end_offset - next_offset - this_time;
4149
4150 /* Don't try to take a bunch of bits that cross
4151 the word boundary in the INTEGER_CST. We can
4152 only select bits from the LOW or HIGH part
4153 not from both. */
4154 if (shift < HOST_BITS_PER_WIDE_INT
4155 && shift + this_time > HOST_BITS_PER_WIDE_INT)
4156 {
4157 this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
4158 shift = HOST_BITS_PER_WIDE_INT;
4159 }
4160
4161 /* Now get the bits from the appropriate constant word. */
4162 if (shift < HOST_BITS_PER_WIDE_INT)
4163 value = TREE_INT_CST_LOW (val);
4164 else if (shift < 2 * HOST_BITS_PER_WIDE_INT)
4165 {
4166 value = TREE_INT_CST_HIGH (val);
4167 shift -= HOST_BITS_PER_WIDE_INT;
4168 }
4169 else
4170 abort ();
4171
4172 /* Get the result. This works only when:
4173 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
4174 byte |= (((value >> shift)
4175 & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
4176 << (BITS_PER_UNIT - this_time - next_bit));
4177 }
4178 else
4179 {
4180 /* On little-endian machines,
4181 take first the least significant bits of the value
4182 and pack them starting at the least significant
4183 bits of the bytes. */
4184 shift = next_offset - int_bit_position (field);
4185
4186 /* Don't try to take a bunch of bits that cross
4187 the word boundary in the INTEGER_CST. We can
4188 only select bits from the LOW or HIGH part
4189 not from both. */
4190 if (shift < HOST_BITS_PER_WIDE_INT
4191 && shift + this_time > HOST_BITS_PER_WIDE_INT)
4192 this_time = (HOST_BITS_PER_WIDE_INT - shift);
4193
4194 /* Now get the bits from the appropriate constant word. */
4195 if (shift < HOST_BITS_PER_WIDE_INT)
4196 value = TREE_INT_CST_LOW (val);
4197 else if (shift < 2 * HOST_BITS_PER_WIDE_INT)
4198 {
4199 value = TREE_INT_CST_HIGH (val);
4200 shift -= HOST_BITS_PER_WIDE_INT;
4201 }
4202 else
4203 abort ();
4204
4205 /* Get the result. This works only when:
4206 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
4207 byte |= (((value >> shift)
4208 & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
4209 << next_bit);
4210 }
4211
4212 next_offset += this_time;
4213 byte_buffer_in_use = 1;
4214 }
4215 }
4216 }
4217
4218 if (byte_buffer_in_use)
4219 {
4220 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
4221 total_bytes++;
4222 }
4223
4224 if ((unsigned HOST_WIDE_INT)total_bytes < size)
4225 assemble_zeros (size - total_bytes);
4226 }
Above variable next_offset is the offset of this bit-field (in bits), and variable end_offset records the tail of the memory the bit-field will occupy (see that the bit-field may need more than 1 byte memory, so it needs WHILE loop at line 4122). Remember in class layout (refer to section Alignment – bit field in GCC layout and Alignment – bit field in MS layout ) several bit-fields can share the memory, as we only write data by bytes, data can’t fill one byte is cached by byte , and is told by byte_buffer_in_use . And as several bit-fields can share memory, when output them in form of bit pattern (in fact the value), it should given consideration about big-endian and little-endian. For example:
char a:2;
char b:3;
char c:3;
If except the initializer of a is 1, others are 0, then in little-endian machine, we should write the byte with 1, while on big-endian machine, it is 128. So it should be treated differently according to the definition of BYTES_BIG_ENDIAN. For x86/Linux, the macro is defined as 0, it is a little-endian machine.