# More on bases

And why are `printf` and `scanf` so complicated?

`0xdeadbeef`
`0666`
`01010101001100001000101001`
`%d %i %f %u %lf %%%%!`

# Why oh Why?

• There are tons of programming languages to choose from, but C is commonly chosen for its efficiency and low-level control.
• Therefore, understanding the foundation is important for all C programmers.
• This will help you understand “why” for a lot of things, and help prevent inadvertent errors.

# I’m thinking of a number…

• First we need a number for examples.
• How about 0644 in octal.
• It’s the number you use in `chmod` from CS155 to make a file be readable and writeable by you and readable by everyone else, so why not?
• The 0 in the beginning just means it is in octal.
• What is it though?
• In C it is an `int`.
• Everything is an `int` or a `double` unless you say otherwise!

# 0644 in octal… okayyyyyy…

• What is it in different bases?
• So, first what does 644 mean in octal?
• 6 in the 64’s place (64 = 8²)
• 4 in the 8’s place (8 = 8¹)
• 4 in the 1’s place (1 = 80)

# What is 0644 in binary?

Hardest way is convert to decimal, then convert to binary.

• Hard way:
• 6×8² = 384
• 4×8¹ = 32
• 4×10 = 4
• Total = 420, or 256+128+32+4, or 1101001002
• Easy Way: Break it into pieces of 3 each
• Why 3? 8¹ = 23, that’s why!
• One digit in octal is three digits in binary!
• 110 100 100 Look! 1102 = 6 and 1002 = 4

• Duh
• 644
• ’Nuff said.

# What is 0644 in decimal?

• Octal to decimal
• Not hard, we just need to do the math.
• Fortunately, we love math!
• 6 × 8² + 4 × 8¹ + 4 × 80
• 6 × 64 + 4 × 8 + 4 × 1
• 384 + 32 + 4
• 420

# What is 0644 in hexadecimal?

• Hard way:
• Hexadecimal is base 16, so the places are 4096, 256, 16, 1
• (163, 16², 16¹, 160)
• How many of each?
• 1 × 256 + 10 × 16 + 4 × 1
• So, it’s 0x1a4

# What is 0644 in hexadecimal?

• Easy way:
• We already know it is 110100100 in binary.
• 16¹ = 24
• Each hex digit is 4 binary digits.
• 1 1010 0100
• 1 is easy: 1
• 1010 is 8+2 = 10 = a
• 0100 is 4 … so 4
• 0x1a4

# Why doesn’t the easy way work for other conversions?

It’s all about the ratios:

FromToRatioDifficulty
DecimalOctal10 = 81.1073Hard
DecimalBinary10 = 23.3219Hard
OctalBinary 8 = 23Easy

Yow!

# So, our number is:

110100100 in binary or… 644 in octal or… 420 in decimal or… 1a4 in hexadecimal…

• What’s the difference?!
• To a human? It’s the difference between a number and a headache.
• To the computer?
• Nothing!

# Nothing? Nothing at ALL!?

Nope, not a thing. Try it:

```printf("%d\n", 0644);
printf("%d\n", 420);
printf("%d\n", 0x1a4);
```
```420
420
420
```

Why??

# The computer doesn’t care!

• It stores it all in binary.
• They all look the same in binary.
• They’re all just ints.
• In fact, even if it DID care, it can’t tell the difference anyway!
• If a memory cell contains, 000110110000101100101 was it binary, octal, decimal, or hex to begin with?
• So how does `printf` know how to print it?

# How does it know?

• It doesn’t know—you have to tell it!
• For printing an `int`:
• `%d` means print out an `int` as a signed decimal.
• `%u` means print out an `int` as an unsigned decimal.
• `%x` means print out an `int` as an unsigned hexadecimal
• `%o` means print out an `int` as an unsigned octal
• There are more: `long`, `unsigned long`, `short`, `unsigned short`, `float`, `double`, `long double`, `long long`, `unsigned long long`, `char`, `unsigned char`, …, etc.
• We’ll cover more later… this is enough for now.

# What if it is isn’t an `int`?

• `%s` will print a string (array of `char`)
• `%f` will print a `float`
• `%lf` will print a `double`
• `%lu` will print an `unsigned long`
• `%ld` (or `%li`) will print a `signed long`

# MAKE THEM MATCH!!!!

• It is vital that the format string matches the type of the value you are printing.
• What happens if you tell it to print an `int` (`%d` or `%x` or `%o`), but give it a float?

# Best case: Bad things happen.

```printf("%d",3.14f);
```
```c.c: In function 'main':
c.c:1: warning: format '%d' expects argument of type 'int', but argument 2 has type 'double'
25048072```
• This is a lie! You are telling it that you are giving it an `int` that you want to print in decimal, but you are giving it a `double` instead.
• It will believe the lie!

# Worst Case: Crash!

• `printf("%s", 3.14);`
• HUGE LIE
• `printf` is expecting a string, which is an array of `char`.
• You gave it a `double`—they are SO different that it might crash!

# So, whats the “&” and scanf?

• In C, “&” is the “address-of” operator.
• Everything lives in memory.
• If you have an `int` named `fred`, `&fred` is the physical location in memory where fred is stored. It is his address.
• Why does `scanf` need that?

# scanf reads values IN

• It needs to know where to store them.
• It reads in what you tell it
• converts it from whatever base you tell it
• converts it to whatever type you tell it
• and puts the result where you tell it
• Where = address
• Why doesn’t `printf` need the address too?

# Lying to scanf

• What happens if you lie to scanf?
• It will do as it is told.
• If you lie, you get what you deserve
• probably a big fat core dump.
```int foo;
scanf("%f",&foo);
```

What is in `foo`?

# Why not & in printf?

• printf doesn’t care where they are stored; it only needs the values to print.
• It won’t modify any memory, so you can just give it the value.
• `scanf` needs to modify memory, so you need to tell it what memory to modify, and what type of thing to store there.

# Example

```#include <stdio.h>
int main() {
int fred = 12;
printf("%d", fred);
return 0;
}
```
• What gets passed into `printf`?
• If you said `fred`, you’re wrong!
• `12` gets passed. Not `fred`. A copy of the contents of `fred`.
• `printf` can’t touch `fred` even if it wanted to.
• `fred` may as well be in GTMO! He’s untouchable.

# Example2

```#include <stdio.h>
int main() {
int fred = 12;
scanf("%d", fred);
return 0;
}
```
• Why is this wrong?
• What can `scanf` do with a “12”?
• `scanf` doesn’t care what was in `fred`.
• It wants to know where `fred` lives, so that it can change the contents of it.
• Hence, it wants `&fred`, the address of `fred`.

# Example2

```#include <stdio.h>
int main() {
int fred = 12;
scanf("%d", fred);
return 0;
}
```
• So what will happen if we do this anyway? What does it mean?
• “Read a number user and store it as a signed int into memory address 12”
• What’s in memory locatino 12?
• A BIG FAT SEGMENTATION FAULT
• The chances that memory location 12 is YOURS to touch is minuscule.
• The chances are good that it is part of the operating system.
• Mess with memory that isn’t yours, and you get a segfault right between the eyes!

# Example2

```#include <stdio.h>
int main() {
int fred = 12;
scanf("%d", &fred);
return 0;
}
```
• This is what it should be.
• “Fred is over there”

# What about strings?

```int main() {
char name[6];
strcpy(name, "Bubba");
printf("%s\n", name);
return 0;
}
```

```     name[0]  name[1]  name[2]  name[3]  name[4]  name[5]
┌────────┬────────┬────────┬────────┬────────┬────────┐
│   B    │   u    │   b    │   b    │   a    │   \0   │
└────────┴────────┴────────┴────────┴────────┴────────┘
```
• name[1] is a `char` (in fact, it is a ‘u’)
• But what is `name`?
• It might sound odd, but `name` is the address where the chars start.
• `name == &name == &name[0]`

# What about strings?

```int main() {
char name[6];
strcpy(name, "Bubba");
printf("%s\n", name);
return 0;
}
```

```     name[0]  name[1]  name[2]  name[3]  name[4]  name[5]
┌────────┬────────┬────────┬────────┬────────┬────────┐
│   B    │   u    │   b    │   b    │   a    │   \0   │
└────────┴────────┴────────┴────────┴────────┴────────┘
```
• What’s passed to `printf`?
• A pointer to the beginning of the string.
• It will read the characters, and stop reading when it hits a `\0`.
• Why not pass in a copy of the contents of the array (like what happens with ints?)
• Too much copying.

# What about strings?

```int main() {
char name[6];
strcpy(name, "Bubba");
scanf("%s\n", name);
return 0;
}
```

```     name[0]  name[1]  name[2]  name[3]  name[4]  name[5]
┌────────┬────────┬────────┬────────┬────────┬────────┐
│   B    │   u    │   b    │   b    │   a    │   \0   │
└────────┴────────┴────────┴────────┴────────┴────────┘
```
• The same thing gets passed to `scanf`.
• Except that it will write there instead of read.
• And it will put a `\0` at the end.

# It all sounds so delicate

• How can I prevent accidental mistakes, segfaults, cores, garbage data, and other nasty things that go crash in the night?
• Easy. When you compile your program, add `-Wall` (big “W”, little “all”)
• It makes the compiler do some checking and tell you if a parameter doesn’t match the format strings in `printf`, `scanf`, etc.
• It won’t catch everything—that’s why they have you.

# Let me say that again

`c11 -Wall`

User: Guest

Check: HTML CSS
Edit History Source

Modified: 2017-12-19T11:20

Apply to CSU | Contact CSU | Disclaimer | Equal Opportunity
Colorado State University, Fort Collins, CO 80523 USA