In this SAP Press book chapter excerpt, you'll find out how to read, navigate and program ABAP coding at the bits...
and bytes level. In addition, you'll learn how to use ABAP bitwise operators to write Boolean algebraic expressions.
Advanced ABAP operations with elementary data types
Working with ABAP date and time data types
Understanding ABAP programming bits and bytes
2.3 Bits and Bytes
Modern programming languages do such a tremendous job of abstracting the complexities
of computer architectures that, these days, we seldom have any need to
work at the bits and bytes level. However, with the advent of Unicode, it’s becoming
more important to understand how to work at this level because many external
data sources encode their data using multi-byte encodings — as opposed to
the single-byte code pages normally used in ABAP (e.g., ASCII, etc.). In addition,
knowledge of this area can be quite handy in other applications, as you’ll see in
2.3.1 Introduction to the Hexadecimal Type in ABAP
Normally, whenever we talk about the built-in native data types provided in the
ABAP programming language, we focus our attention around the numeric and
character data types. However, ABAP also provides a hexadecimal data type (X)
that is used to represent individual bytes in memory. The values stored in the individual
bytes are represented as two-digit hexadecimal numbers.
Binary and Hexadecimal Numbers
If you have never worked with binary or hexadecimal numbers before, then a brief introduction
is in order. A byte is a unit of measure for memory inside of a computer. Each
byte is comprised of 8 bits. The term bit is an abbreviation for binary digit. A bit can
have one of two logical values: 1 (or true) or 0 (or false). In terms of computer circuitry,
bits that have the value 1 are turned on, while those that have the value 0 are turned
The binary (or base-2) number system represents numeric values using binary digits.
Figure 2.8 shows an example of an 8-bit binary number whose decimal value is 170. As
you can see, reading from right to left, the value of each bit is calculated by multiplying
one or zero (i.e., the bit value) by two raised to the power of the current index (where
indexes start at zero).
2^7 2^6 2^5 2^4 2^3 2^2 2^1 2^0
= (2^7 * 1) + (2^5 * 1) + (2^3 * 1) + (2^1 * 1)
Figure 2.8 Example of an 8-Bit Binary Number
Binary numbers can be very difficult to work with if you’re not a computer. Therefore,
the values of bytes are often represented using the hexadecimal (or base-16) numbering
system. Each hexadecimal digit is in the range [0123456789ABCDEF], where A = 10, B =
11, C = 12, and so on. Conveniently, each hexadecimal digit can hold any possible value
of 4 bits (commonly called a nibble). Therefore, two hexadecimal digits can be used to
represent a single byte of information in memory.
In addition to the fixed length X data type, ABAP also provides the XSTRING variable-
length hexadecimal type, which is commonly used in various input/output
(I/O) operations. Here, as is the case with the C and STRING data types described in
Chapter 1, String Processing Techniques, there is a trade-off between performance
Now that you know a little bit about the hexadecimal type, let’s take a look at the
types of operations you can perform on data objects of this type. The following
sections describe the built-in bitwise operators available in ABAP.
2.3.2 Reading and Writing Individual Bits
You can use the GET BIT and SET BIT statements to read and write individual bits
of a hexadecimal data object. The general syntax of these statements is shown in
Listing 2.12 and Listing 2.13, respectively.
GET BIT lv_index OF lv_hex INTO lv_bit.
Listing 2.12 Syntax of GET BIT Statement
SET BIT lv_index OF lv_hex TO lv_bit.
Listing 2.13 Syntax of SET BIT Statement
To demonstrate how these statements work, let’s consider an example. Listing 2.14
contains a contrived piece of sample code that swaps the first byte of a two-byte
hexadecimal data object with the last byte by manipulating individual bits internally.
For good measure, we also shift the bits around one more time at the end of
the code snippet, using the SHIFT statement in byte mode.
DATA: lv_hex(2) TYPE x VALUE 'F00F',
lv_front_idx TYPE i,
lv_back_idx TYPE i,
lv_front_bit TYPE i,
lv_back_bit TYPE i.
WRITE: / lv_hex.
DO 8 TIMES.
lv_front_idx = sy-index.
lv_back_idx = lv_front_idx + 8.
GET BIT lv_front_idx OF lv_hex INTO lv_front_bit.
GET BIT lv_back_idx OF lv_hex INTO lv_back_bit.
SET BIT lv_front_idx OF lv_hex TO lv_back_bit.
SET BIT lv_back_idx OF lv_hex TO lv_front_bit.
WRITE: / lv_hex.
SHIFT lv_hex BY 1 PLACES CIRCULAR IN BYTE MODE.
WRITE: / lv_hex.
Listing 2.14 Reading and Writing Bits in ABAP
In and of itself, low-level bit manipulation isn’t all that exciting. However, there
are situations where it can be quite useful.
For example, let’s imagine you’re working on a problem where you need to work
with arbitrarily large numbers that exceed the limits of the built-in ABAP numeric
types. One way other modern programming languages, such as Java or .NET, get
around this limitation is by developing a so-called numeric wrapper class. For
instance, the java.math.BigInteger class provided with the Java 2 SDK is used to
represent arbitrarily large integer values. Internally, bitwise operators are used to
mimic the behavior of a normal primitive type represented in two’s complement
notation.3 Because this implementation is open source, it wouldn’t be too difficult
to reverse-engineer an ABAP version of this class to suit your purposes.
2.3.3 Bitwise Logical Operators
In addition to the GET BIT and SET BIT statements, ABAP also provides a series of
bitwise logical operators that can be used to build Boolean algebraic expressions.
If you aren’t familiar with Boolean algebra, there are many excellent resources
available online — simply search for the term “Boolean Algebra,” and you’ll find
a wealth of information. Of course, even if you have worked with Boolean operators
before, you might need a bit of a refresher. Table 2.4 depicts a truth table that
shows the values generated when applying the Boolean AND, OR, or XOR operators
against the two bit values contained in Field A and Field B.
|Field A||Field B||AND||OR||XOR|
Table 2.4 Truth Table for Boolean Operators
Table 2.5 shows the bitwise operators provided with the ABAP language. Just like
normal arithmetic operators, the bitwise operators can be combined in complex
expressions using parentheses, and so on.
3 The two’s complement notation is a common system used to represent signed integers in computers.
|BIT-NOT||Unary operator that flips all of the bits in the hexadecimal number
to the opposite value. For example, applying this operator to a
hexadecimal number having the bit-level value 10101010 (e.g., 'AA')
would yield 01010101.
|BIT-AND||Binary operator that compares each field bit-by-bit using the Boolean
|BIT-XOR||Binary operator that compares each field bit-by-bit using the Boolean
XOR (or eXclusive OR) operator.
|BIT-OR||Binary operator that compares each field bit-by-bit using the Boolean
Table 2.5 Bitwise Logical Operators in ABAP
To see the power of bitwise operators such as the ones listed in Table 2.5, it’s useful
to consider an example. Imagine that you are tasked with building a custom
document management system. One of the requirements of this system is to be
able to assign rights permissions to the individual documents maintained in the
system. For the purposes of this simple example, let’s assume that the possible
permissions are Create, Remove, Update, and Display.
One way to store these assignments might be to create a database table that contained
a series of flag columns to indicate whether or not a user had a particular
permission for a given document. Unfortunately, there are a couple of problems
with this approach. First of all, it requires that we create separate fields for
each possible permission type. As the system grows, additional permission types
require a modification to the database table. This phenomenon leads into the second
problem — namely, space. In other words, each additional flag column adds
another byte or two of storage to every row in the table. Of course, another option
is to capture the permissions in separate rows. Still, either way you slice it, this can
get expensive from a storage perspective.
Instead of creating a new flag column each time we want to add a new permission
type to our system, what if we could figure out a way to store a bunch of Boolean
flags in a single field? Naturally, the hexadecimal data type lends itself well to this
kind of storage operation because it can be used as a type of bit mask to represent
a large number of flags at the bit level. For example, a single byte bit mask could
represent up to 28, or 256, possible values, leaving us plenty of room to grow. The values of the individual Boolean flags can then be set using bitwise operators. Collectively,
the process of representing a series of flags at the bit level and manipulating
those flags using bitwise operators is referred to as bit masking.
The code excerpt in Listing 2.15 demonstrates how bit masking works using the
ABAP bitwise logical operators. To keep things simple, we’ve created an interface
that contains constants to represent the possible permission values (e.g., CO_CREATE,
etc.). These permission values are assigned to a display-only user using the
BIT-OR operator, which effectively works like an addition operator in this case. We
can then confirm whether or not the user has a given permission by applying the
BIT-AND operator. Here, the result matches the permission constant bit-for-bit if
the particular permission has been assigned. This can be confirmed by using the
equality operator in an IF statement. In the example, the user has Display permissions
but not Create permissions.
CONSTANTS: CO_CREATE TYPE x VALUE '01',
CO_REMOVE TYPE x VALUE '02',
CO_UPDATE TYPE x VALUE '04',
CO_DISPLAY TYPE x VALUE '08'.
DATA: lv_display_user TYPE x,
lv_permission TYPE x.
* Assign read-only access to a display user:
lv_display_user BIT-OR lif_permissions=>CO_DISPLAY.
* Check the user's permissions:
lv_display_user BIT-AND lif_permissions=>CO_DISPLAY.
IF lv_permission EQ lif_permissions=>CO_DISPLAY.
WRITE: / 'User has display only access.'.
WRITE: / 'User does not have display access.'.
lv_display_user BIT-AND lif_permissions=>CO_CREATE.
IF lv_permission EQ lif_permissions=>CO_CREATE.
WRITE: / 'User can create documents.'.
WRITE: / 'User is not authorized to create documents.'.
Listing 2.15 Mapping Permissions Using Bit Masking
As you can see, bit masking can be used as an effective compression technique.
Other practical examples of bit masking include the storage of user preferences
and set operations, which are described in an example in the online SAP Help
In this chapter, you learned about some advanced and perhaps lesser-known features
of elementary data types in ABAP. During the course of this book, you’ll see
how some of these fundamental concepts provide the foundation for implementing
new features in SAP NetWeaverAS ABAP, such as support for Unicode and
XML processing. In the next chapter, we mix things up a bit and take a look at
dynamic programming in ABAP.
This excerpt from ABAP Cookbook: Programming Recipes for Everyday Solutions by James Woods is reprinted here with permission from SAP Press, copyright 2010. Download a PDF of this chapter.