- Learn C The Hard Way
- Preface
- Introduction: The Cartesian Dream Of C
- Exercise 0: The Setup
- Exercise 1: Dust Off That Compiler
- Exercise 2: Make Is Your Python Now
- Exercise 3: Formatted Printing
- Exercise 4: Introducing Valgrind
- Exercise 5: The Structure Of A C Program
- Exercise 6: Types Of Variables
- Exercise 7: More Variables, Some Math
- Exercise 8: Sizes And Arrays
- Exercise 9: Arrays And Strings
- Exercise 10: Arrays Of Strings, Looping
- Exercise 11: While-Loop And Boolean Expressions
- Exercise 12: If, Else-If, Else
- Exercise 13: Switch Statement
- Exercise 14: Writing And Using Functions
- Exercise 15: Pointers Dreaded Pointers
- Exercise 16: Structs And Pointers To Them
- Exercise 17: Heap And Stack Memory Allocation
- Exercise 18: Pointers To Functions
- Exercise 19: A Simple Object System
- Exercise 20: Zed's Awesome Debug Macros
- Exercise 21: Advanced Data Types And Flow Control
- Exercise 22: The Stack, Scope, And Globals
- Exercise 23: Meet Duff's Device
- Exercise 24: Input, Output, Files
- Exercise 25: Variable Argument Functions
- Exercise 26: Write A First Real Program
- Exercise 27: Creative And Defensive Programming
- Exercise 28: Intermediate Makefiles
- Exercise 29: Libraries And Linking
- Exercise 30: Automated Testing
- Exercise 31: Debugging Code
- Exercise 32: Double Linked Lists
- Exercise 33: Linked List Algorithms
- Exercise 34: Dynamic Array
- Exercise 35: Sorting And Searching
- Exercise 36: Safer Strings
- Exercise 37: Hashmaps
- Exercise 38: Hashmap Algorithms
- Exercise 39: String Algorithms
- Exercise 40: Binary Search Trees
- Exercise 41: Using Cachegrind And Callgrind For Performance Tuning
- Exercise 42: Stacks and Queues
- Exercise 43: A Simple Statistics Engine
- Exercise 44: Ring Buffer
- Exercise 45: A Simple TCP/IP Client
- Exercise 46: Ternary Search Tree
- Exercise 47: A Fast URL Router
- Exercise 48: A Tiny Virtual Machine Part 1
- Exercise 48: A Tiny Virtual Machine Part 2
- Exercise 50: A Tiny Virtual Machine Part 3
- Exercise 51: A Tiny Virtual Machine Part 4
- Exercise 52: A Tiny Virtual Machine Part 5
- Next Steps
- Deconstructing K & RC Is Dead
Exercise 8: Sizes And Arrays
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: sizeof
and arrays. Here's the code we'll be talking about:
#include <stdio.h>
int main(int argc, char *argv[])
{
int areas[] = {10, 12, 13, 14, 20};
char name[] = "Zed";
char full_name[] = {
'Z', 'e', 'd',
' ', 'A', '.', ' ',
'S', 'h', 'a', 'w', '\0'
};
// WARNING: On some systems you may have to change the
// %ld in this code to a %u since it will use unsigned ints
printf("The size of an int: %ld\n", sizeof(int));
printf("The size of areas (int[]): %ld\n",
sizeof(areas));
printf("The number of ints in areas: %ld\n",
sizeof(areas) / sizeof(int));
printf("The first area is %d, the 2nd %d.\n",
areas[0], areas[1]);
printf("The size of a char: %ld\n", sizeof(char));
printf("The size of name (char[]): %ld\n",
sizeof(name));
printf("The number of chars: %ld\n",
sizeof(name) / sizeof(char));
printf("The size of full_name (char[]): %ld\n",
sizeof(full_name));
printf("The number of chars: %ld\n",
sizeof(full_name) / sizeof(char));
printf("name=\"%s\" and full_name=\"%s\"\n",
name, full_name);
return 0;
}
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:
- Look at the type, in this first case it's
int
. - Look at the
[]
and see that there's no length given. - Look at the initializer,
{10, 12, 13, 14, 20}
and figure out that you want those 5 ints in your array. - Create a piece of memory in the computer, that can hold 5 integers one after another.
- 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 to char 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.
What You Should See
$ make ex8
cc -Wall -g ex8.c -o ex8
$ ./ex8
The size of an int: 4
The size of areas (int[]): 20
The number of ints in areas: 5
The first area is 10, the 2nd 12.
The size of a char: 1
The size of name (char[]): 4
The number of chars: 4
The size of full_name (char[]): 12
The number of chars: 12
name="Zed" and full_name="Zed A. Shaw"
$
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?
12-13
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.
How To Break It
Breaking this program is fairly easy. Try some of these:
- Get rid of the
'\0'
at the end offull_name
and re-run it. Run it under Valgrind too. Now, move the definition offull_name
to the top ofmain
beforeareas
. 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. - Change it so that instead of
areas[0]
you try to printareas[10]
and see what Valgrind thinks of that. - Try other versions of these, doing it to
name
andfull_name
too.
Extra Credit
- Try assigning to elements in the
areas
array withareas[0] = 100;
and similar. - Try assigning to elements of
name
andfull_name
. - Try setting one element of
areas
to a character fromname
. - Go search online for the different sizes used for integers on different CPUs.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论