I've been learning C by using some book and there's some code that I don't understand regarding working with base in C programming. So, here's the code:
/* By default, integers are decimal */
#define GN_ANY_BASE 0100 /* Can use any base - like strtol(3) */
#define GN_BASE_8 0200 /* Value is expressed in octal */
#define GN_BASE_16 0400 /* Value is expressed in hexadecimal */
// rlength: Read length bytes from the file, starting at the current file offset, and display them in text form.
int main(int argc, char *argv[]) {
fd = open(argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); /* rw-rw-rw- */
if (fd == -1)
errExit("open");
for (ap = 2; ap < argc; ap ) {
switch (argv[ap][0]) {
case 'r': /* Display bytes at current offset, as text */
case 'R': /* Display bytes at current offset, in hex */
len = getLong(&argv[ap][1], GN_ANY_BASE, argv[ap]);
buf = malloc(len);
...
}
And here's the getLong
function:
long getLong(const char *arg, int flags, const char *name) {
return getNum("getLong", arg, flags, name);
}
And here's the getNum
function:
static long getNum(const char *fname, const char *arg, int flags, const char *name) {
long res;
char *endptr;
int base;
if (arg == NULL || *arg == '\n')
gnFail(fname, "null or empty string", arg, name);
base = (flags & GN_ANY_BASE) ? 0 : (flags & GN_BASE_8) ? 8 : (flags & GN_BASE_16) ? 16 : 10;
res = strtol(arg, &endptr, base);
return res;
}
This line really confuses me, and what happened after that didn't help either:
base = (flags & GN_ANY_BASE) ? 0 : (flags & GN_BASE_8) ? 8 : (flags & GN_BASE_16) ? 16 : 10;
What did it do? and why do we need this? what is GN_BASE
?
I can run the programs from the terminal by using the command:
./main file.txt r50
And it will give the following output like this:
r50: this is a text inside file.txt
I tried removing as many codes as possible for this example and hope it helps clear the example.
I'm sorry for asking beforehand. Thank you very much.
CodePudding user response:
- The argument
flag
can carry other information so we mask what we are interested in with bitwise and-operator (&
). Btw, often those mutually exclusive flags are written with a left shift instead of absolute values (1<<6
,1<<7
,1<<8
). - We map the value provided to something that is more convenient for use internally (0100 to 0, 0200 to 8, and 0400 to 16).
- Finally, we provide a default value of
10
if none of those 3 base bits were found.