• No results found

Sizes And Arrays

In document c Programing in Hard Way (Page 44-47)

In the last exercise you did math, but with a '\0' (nul) character. This may be odd coming from other languages, since they try to treat "strings" and "byte arrays" as different beasts. C however treats strings as just arrays of bytes, and it's only the different printing functions that know there's a difference.

Before I can really explain the significance of this, I have to introduce a few more concepts: sizeofand arrays. Here's the

code we'll be talking about:

Source 25: ex8.c

1 #include <stdio.h> 2

3 int main(int argc, char *argv[]) 4 {

5 int areas[] = {10, 12, 13, 14, 20}; 6 char name[] = "Zed";

7 char full_name[] = { 8 'Z', 'e', 'd', 9 ' ', 'A', '.', ' ', 10 'S', 'h', 'a', 'w', '\0' 11 }; 12

13 // WARNING: On some systems you may have to change the 14 // %ld in this code to a %u since it will use unsigned ints 15 printf("The size of an int: %ld\n", sizeof(int));

16 printf("The size of areas (int[]): %ld\n", 17 sizeof(areas));

18 printf("The number of ints in areas: %ld\n", 19 sizeof(areas) / sizeof(int));

20 printf("The first area is %d, the 2nd %d.\n", 21 areas[0], areas[1]);

22

23 printf("The size of a char: %ld\n", sizeof(char)); 24 printf("The size of name (char[]): %ld\n",

25 sizeof(name));

26 printf("The number of chars: %ld\n", 27 sizeof(name) / sizeof(char)); 28

29 printf("The size of full_name (char[]): %ld\n", 30 sizeof(full_name));

31 printf("The number of chars: %ld\n",

32 sizeof(full_name) / sizeof(char)); 33

34 printf("name=\"%s\" and full_name=\"%s\"\n", 35 name, full_name);

36

37 return 0; 38 }

In this code we create a few arrays with different data types in them. Because arrays of data are so central to how C works, there's a huge number of ways to create them. For now, just use the syntax type name[] = {initializer}; and we'll explore more. What this syntax means is, "I want an array of type that is initialized to ..." When C sees this it does the following:

1. Look at the type, in this first case it's int.

2. Look at the [] and see that there's no length given.

3. Look at the initializer, {10, 12, 13, 14, 20} and figure out that you

want those 5 ints in your array.

4. Create a piece of memory in the computer, that can hold 5 integers one after another.

5. Take the name you want, areas and assign it this location.

In the case of areas it's creating an array of 5 ints that contain

those numbers. When it gets tochar name[] = "Zed"; it's doing the same thing, except it's creating an array of 3 chars and assigning that to name. The final array we make is full_name, but

we use the annoying syntax of spelling it out, one character at a time. To C, name and full_name are identical methods of

creating a char array.

The rest of the file, we're using a keyword called sizeof to ask

C how big things are in bytes. C is all about the size and

location of pieces of memory and what you do with them. To help you keep that straight, it gives you sizeof so you can ask

how big something is before you work with it.

This is where stuff gets tricky, so first let's run this and then explain further.

9.1 What You Should See

Source 26: ex8 output

1$ make ex8

2cc -Wall -g ex8.c -o ex8 3$ ./ex8

4The size of an int: 4

5The size of areas (int[]): 20 6The number of ints in areas: 5 7The first area is 10, the 2nd 12. 8The size of a char: 1

9The size of name (char[]): 4 10The number of chars: 4

11The size of full_name (char[]): 12 12The number of chars: 12

13name="Zed" and full_name="Zed A. Shaw" 14$

Now you see the output of these different printf calls and start

to get a glimpse of what C is doing. Your output could actually be totally different from mine, since your computer might have different size integers. I'll go through my output:

5

My computer thinks an int is 4 bytes in size. Your computer might use a different size if it's a 32-bit vs. 64-bit.

6

The areas array has 5 integers in it, so it makes sense that my computer requires 20 bytes to store it.

7

If we divide the size of areas by size of an int then we get 5 elements. Looking at the code, this matches what we put in the initializer.

8

We then did an array access to get areas[0] and areas[1] which means

C is "zero indexed" like Python and Ruby. 9-11

We repeat this for the name array, but notice something odd about the size of the array? It says it's 4 bytes long, but we only typed "Zed" for 3 characters. Where's the 4th one coming from?

We do the same thing with full_name and notice it gets this correct. 13

Finally we just print out the name and full_name to prove that they actually are "strings" according to printf.

Make sure you can go through and see how these output lines match what was created. We'll be building on this and

exploring more about arrays and storage next.

9.2 How To Break It

Breaking this program is fairly easy. Try some of these:

7. Get rid of the '\0' at the end of full_name and re-run it. Run it under

Valgrind too. Now, move the definition of full_name to the top

of main before areas. Try running it under Valgrind a few times and see if you get some new errors. In some cases, you might still get lucky and not catch any errors.

8. Change it so that instead of areas[0] you try to print areas[10] and see

what Valgrind thinks of that.

9. Try other versions of these, doing it to name and full_name too.

9.3 Extra Credit

6. Try assigning to elements in the areas array with areas[0] = 100; and

similar.

7. Try assigning to elements of name and full_name.

8. Try setting one element of areas to a character from name.

9. Go search online for the different sizes used for integers on different CPUs.

Chapter 10

In document c Programing in Hard Way (Page 44-47)

Related documents