Forgot your password?
typodupeerror
Programming

Journal buffer-overflowed's Journal: For SamtheButcher: The basics of Procedural Languages (C) 41

UPDATE: I've implemented some of Cyberdine's helpful suggestions.  I've also clarified a few bits of jargon.

Since b-over is BFAA bored, BFAA broke, and BFAA single so he's sitting over at his BFAA parents house munchin wings and watchin TV, and also as an apology to Sam for helping to crowd his inbox... I figure I'll post a quick procedural language tutorial for him.

Note since you've not posted ANYTHING requesting specific knowledge I'm going over this in a fairly low-brow manner.  Feel free to ask in depth-questions in replies (anyone really, or correct my idiot ass if I screw something up).

Since tradition demands it, the Hello World program:

#include <stdio.h>

int main(void) {
       printf ("Hello World!\r\n");
       return 0;
}

This is of course the traditional opening program in just about *ANY* C book (or java, or anything) I've ever read.  It's fairly self-explanatory.

Now, as a preface since I've fufilled my requirements to the programming gods by posting hello world, I suck at teaching. =)

We will now dissect Hello World for shits and giggles.

#include <stdio.h>

Top level goes preprocessor directives, include statements (which draw in header file interfaces to libraries or serve as libraries of a sort themselves, or serve as glue to bring multiple file projects together... etc.), defines, sometimes logic (#ifdefs for example) or macro definitions (don't worry bout this for now).  The only one here is to the standard input/output header (stdio.h) which provides an interface under linux into glibc.

UPDATE: Preprocessor directives include anything proceeded by a '#' character.  They are processed by the compiler before anything else.  Hence if you do something like this; #ifdef _UNIX_ statements #endif it will only include that code if you have #define _UNIX_ 1 somewhere before it.  This includes all #define statements, #includes, and the like.  I had refrained from explaining this because it might be confusing.

int main() {

The main function, the entry point into the program.  Properly written as follows:
int main (int argc, char *argv[]) {
Note I mix those two up occassionally (almost never write programs that take command line inputs).  Argc (argument Count) is the number of arguments passed via STDIN(You know Unix at least a little, right Sam?), argv(argument Vector) are the actual arguments.

What's the * mean?  * means pointer, I'll explain those later.

Next up we have the printf function call.  This outputs stuff to STDOUT.

Then the return value.  Main returns 0 (or normal exit).  We could also use an:
exit(0)
here, but it wouldn't be officially correct.

Now, let's go into what happens when we run this through gcc.
gcc -o helloworld hello_world.c (This is a syntax screwup, check comments for the correct way for Makefiles [gratz Cyberdyne for the correction])

The compiler compiles it (this actually sums up a bunch of steps) and then it is linked dynamically to glibc.  When you run the ELF binary helloworld it simply outputs:
Hello World!

If you wanted to link it statically (for instance, so it would run on linux computers which for some reason lack glibc).  You could compile it in that manner.  Also, -Wall helps detect syntax errors and typos (Once again, gratz Cyberdyne for pointing this out).

C is a procedural language, by procedural I mean it breaks things apart into procedures (or functions as they are more often called).  For instance in the above example, main is a function.  You could also write the same program as follows:

#include <stdio.h>

void say_hello (void) {
        printf ("Hello World!\r\n");
}

int main(void) {
        say_hello();
        return 0;
}

Functionally it does the same thing, and in something this simple, there's no point in seperating printing out hello world from the main function.  Note the return type of say_hello is void.  It doesn't return anything (not even a non-typed pointer), hence the lack of a return statement.  However, say you wanted to generate some random numbers between x and y.  You'd probably want to do this quite often.  Here's an example of that:

#include <time.h>
#include <stdio.h>
#include <random.h> //May not exist, no access to man pages right now.

void seed_random (void) {
        time_t timeval;   //A variable to store the time in secs since the Unix Epoch
        time (&now);      //Get the current time, pass it by reference
        srandom (now);    //Seed the random number generator with the current time
}

int roll_dice (int sides) {
        int roll = random() % sides; /* Modulus division of a very large random number.  Modulus gets the remainder.  For instance 7 % 3 = 1. */

        roll ++; //Since the result will be between 0 and our number -1
        return roll; //Return the value
}

Seed random is a function to reseed the random number generator.  To do so we pass our time_t value to the time function by reference (the & symbol) since it takes a pointer to a time value.  roll_dice takes an interger argument for the number of sides to a dice, and then uses the random function %(modulus division, or calculating the remainder.  IE: 7 % 3 = 1) the number of sides to generate a number.  The result is then incremented by one to give a value range of 1 and sides.  Note:  In practice, we'd want to use a different time grabbing function, for instance gettimeofday() to get the time in u_secs.

It's now time to go into the best thing about C.  Pointers.  A pointer is simple a "pointer" or a reference to a section of memory.  For instance say I have this value:
char arg = 'a';
And I then do this:
char *parg = &arg;
parg points to arg, if I use parg I'm actually using the value of arg(since parg points to arg), so if arg changes, parg also changes and vice versa(but I must reference the location it points to rather then the pointer).  You can also have pointers to pointers and all other sorts of fun.  We use pointers to cut down on memory usage, this is also why we pass things by reference.  For instance when the time_t was passed by reference a pointer to it was passed, when that value was changed, the time_t we passed was also changed.

Next I'll go into the basics of loops.

We have the for loop, such as what follows:
for (a = 0;a < 5;a ++) {
          //Do Stuff
}
This loop sets a (presumably int value) to 0, increments a by one every iteration, and ends the moment a is no longer less then 5.

There's also the while loop.
a = 0;
while (a < 5) {
          //Do Stuff
          a++;
}
Which does the same thing.  A while loop escapes the moment the condition is no longer true on the next iteration.

Then we have the do while loop:
do {
     //stuff
} (while <condition>);
Basically a fancier while that looks better.  UPDATE: Technolust seems to think the differences here are important, so I'll go into them.  A while will not execute the loop if it's condition is met before it starts.  A do while will.

Next up are conditionals.  There are two types
the if, else if and else statements:
if (something) {
         //do something
} else if (something else) {
         //do something
} else {
         //do something
}
these are executed in order.  If the first statement is met it stops, otherwise it goes to the next, if that statement isn't met, it executes the else.

Now the second type, switches.
A switch compares a series of cases to whatever is used in the switch.

For instance we have a value X, X = 1.  We pass it to a switch as follows:

switch (x) {
        case 1:
              //do stuff
              break;
        default:
              break;
}
It's basically a simplified if/else ladder.  It compares X to each case, and if it meets the requirements of that case whatever is there is executed.  The break statement stops comparisons (break also exits loops, but it's considered bad form), otherwise it'll go on down the rest of the conditions (yes you can do weird things with a switch).  If it doesn't match anything, it executes default.

Dems the basics Sam.  I'll go into enumerated data types, structures, macros and a little bit into OO and how it's different for ya sometime later.  Oh, and lets not forget Scope and C99.  YAY.
This discussion has been archived. No new comments can be posted.

For SamtheButcher: The basics of Procedural Languages (C)

Comments Filter:
  • Note I mix those two up occassionally (almost never write programs that take command line inputs). Argv is the number of arguments passed via STDIN, argc are the actual arguments.

    You mixed them up here, too. The arguments themselves are called argv (argument Vector), and the number of arguments is called argc (argument Count).

    • I figured I would, it doesn't affect it when it compiles under gcc, it just looks bad. Thanks for the correction. Anything else you see that's off?
      • I figured I would, it doesn't affect it when it compiles under gcc, it just looks bad. Thanks for the correction. Anything else you see that's off?

        This bit - printf ("Hello World!\n\r"); - for Unix systems, lines are terminated by a single linefeed (\n) character, for DOS-derived systems it's CRLF (\r\n), as opposed to the \n\r you used.

        gcc -o helloworld hello_world.c - you change from "hello_world.c" to "helloworld". Minor, but once you start using Makefiles little inconsistencies like that will trip

        • C99 supports using // and /* for comments. I tend to use both (// for short one lines and /* */ for longer ones.) I studied C++ in college, so the // stuck. (easier to edit out for me)

          You can change the value of what a pointer points to, for instance a character array pointer, by using the * operand. I tried to clear that up, guess I failed. If parg points to the location of arg, if arg changes then parg is still pointing to arg (it's actually value doesn't change, but that's a nitpick, I'm trying to
          • Yea, yea, \r\n or \n\r. Newline return rather than Return Newline.

            I missed that! But isn't it just \n? I thought \n meant the line ending character(s) for the target OS. As I remember (from a long time ago), DOS/Win compilers would translate it into a cr and lf. The only time you needed to worry was if you were checking input character by character...how I remember it anyway. In Linux, \n will send the cursor to the start of the next line. \r will just put it at the start. Nifty trick, try this:

            printf

            • I missed that! But isn't it just \n? I thought \n meant the line ending character(s) for the target OS.

              No; \n represents the single byte for a newline character (ASCII code 10). Unix systems terminate lines with \n (LF), DOS and VMS with \r\n (CRLF), Macs with \r (CR). GCC regards any of these three (plus the \n\r used in the JE, just to be robust) as terminating a line of source code.

              As I remember (from a long time ago), DOS/Win compilers would translate it into a cr and lf. The only time you needed to

        • Seriously, I'm not being a smart-ass. If you improve my coding abilities AND help Sam out at the same time, you're the man. So be absolutely brutal.
    • ..or args in java.
      • .or args in java.

        Yes; in Java, the functionality of argv and argc is combined into a single entity. Instead of argc, use argc.length, and instead of accessing argv[2] you use args[1] (Java puts the first argument in args[0], whereas C puts it in argv[1] and stores the name by which the program was called in argv[0]. On the other hand, apparently some systems put junk in C's argv[0] anyway...)


  • .... you ARE bored. :-)

  • Comment removed based on user account deletion
  • Basically a fancier while that looks better.
    The main difference between a while loop and a do-while loop is that a do-while loop is ALWAYS executed at least once. A while loop may not be executed at all. This is important for someone not familiar with programming to grasp.

    Pretty good intro, although you might want to go back and check for typos and define some of the programming lingo, and look at Cyberdyne's comments.

    • I did, and I corrected a few things (little tired, little affected by fosters, far from perfect, etc.).

      Couple typos, but I'm not sure how to de-lingoize it much more. I'll address Sam's questions if he has any.

      Anything you want to add or correct? For Sam(and for me, I should be perfect even while tired and under the influence dammit)?
    • Also, if you want to help him out. I'm not that good at Java. I can explain the basics, and go into them quite well... but going into the finer details well I'll be at a loss (considering I've never really used it for anything serious).

      On another matter(keep in mind b-over is now tipsy), how do I go into programming lingo and keep it simple? If I go too deep he'll get lost unless he has some basis, or it'll be too dry to sink in. Do I really need to go into things like the scanner? I'm trying to avoid
      • You hit most of the ones I was thinking about. The big one was preprocessor directive, etc. You might want to expound upon procedural (ie, it's line by line as opposed to OO...) Actually, you might just add the procedural is line by line. :-)
        • I'll explain procedural more when I go into OO. It fits more and lets me divide stuff up enough that I don't overwhelm him. If you disagree, feel free to explain it, in as much detail as you feel appropriate. I updated it to tell him to check comments so you guys could correct my non-leet teachin skeels.
          • Actually, step by step pretty much covers it. It does one line, then the next (taking into account function calls, etc.). I think you are correct to wait until you do OO, I just hadn't realized that you were going into those later.
      • Comment removed based on user account deletion
        • I have a comment a ways back that's 99 bottles of beer on the wall in something like under 400 characters. Wish I could find it, but I posted it anonymously.

          The problem with thinking up examples is they have to be interesting. I'd rather get the basics out of the way and then toss out ideas for possible simple projects (and you can reference the theory through the JEs) so you have some questions to ask. Thus far, I've come pretty close to condensing CS101 into a journal entry. I should be most of the w

    • Quite.

      do { } while ( ) doesn't look any *better* than while { }, in fact, it's more complex and even a bit more dangerous, since the first loop is different from the next in that there is no explicit precondition check, and can therefore fail a semantic precondition. In other words it invites for bugs.

      Is a bit surprising that people learning to program seem to graps the concept of first doing something and then asking if I should do it again easier than vice versa.

      • I usually just use a regular while loop, with a boolean as the test. I.E.
        boolean bFlag = true;
        while(bFlag)
        {
        //Do Stuff
        if (condition)
        bFlag = false;
        }
        Or something like that. Usually it is because I'm calling some method or something that returns a boolean value. So I might do this:
        boolean bFlag = true;
        while(bFlag)
        {
        //Do Stuff
        bFlag = someMethod();
        }
  • #include <stdio.h>
    int main(void){

    /* Alright, first, I'm going to define a character value,
    * then right off the bat, I'm going to _initialize_ it
    * with a value, let's make it 'z'.
    */
    char foo='z';
    /* Now, while I COULD just add the next definition on
    * the same line, I'm going to separate it out, so you
    * can see the difference better.
    *
    * This definition is a character POINTER. Ergo, this
    * variable isn't ACTUALLY a character variable, but
    * rather the memory address OF a character variable
    * (in thi
    • Ach... I almost forgot:

      you may wonder why we have to give *bar a type (in this case char). Well, the reason for this is so that the compiler knows what kind of value it points to and hence how to perform certain arithmetic operations on it. For instance (and I'm only going to describe this generically for now), you can create a pointer to a character, and then point it to an array of characters. It will then point to the first value in that array. After that, you can simply increment the pointer by one
    • It is usually best to display the memory layout and it's changes while a programming is running to explain how pointers references and value types relate to one another. In the following paragraph I've put a code fragment and the memory related to the variables in the code next to each other. As every line is executed one after the other, you can follow what happens in memory.

      As it so happens, our program stored it's variables beginning from address 1020, and each variable takes up 4 bytes. So a is t 1020,
      • 'b' would not be 0, 'b' would be a random value. C does not implicately initialize variables to 0, simply allocates a section of the heap. b could be 0 or 1000 or 1024 or anything between 0 and 2^16 in size.
      • Another thing to remember:
        always always always initialize your integer variables. The above example is incorrect, because it shows b as 0 after it is declared, which is not the case. If you were to attempt to use b after it was declared but before assigning it a value, it would return whatever the integer equivalent was of the memory that was sitting at that location. Not that this is a bad illustration of memory, but for a beginner it is vitally important to realize the distinction between declaration a

        • Point taken!! :)

          Buffy here allready pointed it out to me :) and yes, it is one of those easily made mistakes. It *could* have been '0', just as well as anything else. '0' may suggest that it is initialised automatically, which is not true, as you point out. So people, beware, ALLWAYS INITIALISE everything right away!! :)

    • I'll need to go into pointer arithmetic soon, cause it's fun. And jebus A you couldn't resist using foo and bar could you?

      Anyway, thanks for replying, I thought you let you /. account die a slow and painful death.

      Have fun in Baltimore,
      -N
    • Comment removed based on user account deletion

Math is like love -- a simple idea but it can get complicated. -- R. Drabek

Working...