Page 1 of 2 12 LastLast
Results 1 to 10 of 19

Thread: K&R Questions (Dissecting the Bible: C Programming)

  1. #1
    Member
    Join Date
    May 2009
    Posts
    102

    Default K&R Questions (Dissecting the Bible: C Programming)

    I'm currently trying to learn C. So far I'm doing good. Finished reading K&R ansi edition a couple of times and as always, my usual habit when learning a programming language is to write notes for each topic so I can just go back to it in case i need to accomplish something. So far, I must agree with what others are saying. This books is not for fast readers. The author's approach for introducing new functions is by reusing the previously discussed functions. So if you did not pay attention how the function "swap" works, you'll have difficulties understanding the succeeding functions that uses it so you have to go back again.
    So far I have skipped the function qsort, binary tree (self referencial structures, and dcl (complicated declarations) as I find them difficult and as someone said, you won't really need to write those codes that often, mostly only programming students need to. I guess this book really has everything you need in order to learn C. I tried reading a huge application source code, and was happy to be able to understand what each syntax means..

    There's some other threads about C programming but this one is specifically for those who are learning through the K&R book.

    So for my first question:

    (K&R, sec. 6.7 Typedef)
    Suppose I have a structure:

    struct point {
    int x;
    int y;
    }rect;

    This declares a variable rect as a structure of type point.

    Then if I have something like,
    typedef struct point {
    int x;
    int y;
    }Shape;

    It creates a new name for a structure of type point. So where do I insert, "rect" here in this typedef creation if I want to declare "rect" right away? It's supposed to be where the Shape is..

  2. #2
    Junior Member
    Join Date
    Mar 2006
    Posts
    28

    Default

    Quote Originally Posted by wif1bust3r View Post
    Then if I have something like,
    typedef struct point {
    int x;
    int y;
    }Shape;

    It creates a new name for a structure of type point. So where do I insert, "rect" here in this typedef creation if I want to declare "rect" right away? It's supposed to be where the Shape is..
    This may not be what you are trying to do, but can't you just write a declaration after your initilizer, aka

    Shape rec;
    rec.x=5;
    rec.y=10;

    Since all typedef does is assign another name for the variable that you can use elsewhere. You can assign multiple typedefs so a variable could have 10,20 different names if you wanted to make really hard to read code

    aka
    typedef Shape rec;

    where now rec would also be a variable type like Shape. Then you could use it like:

    rec my_rec;
    my_rec.x=5;

  3. #3
    Member
    Join Date
    May 2009
    Posts
    102

    Default

    Quote Originally Posted by lakiw View Post
    This may not be what you are trying to do, but can't you just write a declaration after your initilizer, aka

    Thanks.. actually, I was just trying to find out if it is possible to declare rect at the same time of the typedef creation.. My guess is that, declaring variables of that structure type can just follow after the Typedef creation like:

    Shape rect;

    or maybe

    struct point rect;


    Anyone else who has K&R questions.. let's all learn together here. =)

  4. #4
    Very good friend of the forum Virchanza's Avatar
    Join Date
    Jan 2010
    Posts
    863

    Default

    struct point {
    int x;
    int y;
    }rect;

    This declares a variable rect as a structure of type point.

    Then if I have something like,
    typedef struct point {
    int x;
    int y;
    }Shape;

    It creates a new name for a structure of type point. So where do I insert, "rect" here in this typedef creation if I want to declare "rect" right away? It's supposed to be where the Shape is..
    You can't create an object within a typedef statement, it just can't be done. You'll have to create the typedef first, and then create the object separately:

    Code:
    typedef struct Whatever { int a, b, c; } AnotherName;
    
    AnotherName some_object;
    Or, if you like, you can create the object first, and then create the typedef:

    Code:
    struct Whatever { int a, b, c; } some_object;
    
    typedef struct Whatever AnotherName;
    lakiw said:
    Since all typedef does is assign another name for the variable that you can use elsewhere. You can assign multiple typedefs so a variable could have 10,20 different names if you wanted to make really hard to read code
    A typedef is used to give another name to a type, not a variable. (It looks like you know this already, maybe it was just a typo).

    It's up to you what books you use to learn C... but K&R C is really out-dated. K&R C contains a load of features which were thought to be good ideas back in the day, but turned out to be disastrous (stuff like implicit function declarations), which is why these "features" have been removed from future standards of C.

    I liked C for Dummies personally, but I don't know what's the best C book out there.

    If you're ever looking for an online reference for the C standard library, go to: Dinkumware, Ltd. - Compleat Libraries Reference (it's the only online C reference that's actually correct).

    Just one more thing:
    A declaration is where you introduce a name to the compiler. For instance, if you declare a function as follows:

    Code:
    int MyFunc(int whatever);
    then all it does is tell the compiler that this function exists, it does not actually create the function.

    A definition is where you declare something and create it at the same time, an example would be:

    Code:
    int MyFunc(int whatever)
    {
        return whatever + 7;
    }
    Same goes for declaring and defining variables.
    Ask questions on the open forums, that way everybody benefits from the solution, and everybody can be corrected when they make mistakes. Don't send me private messages asking questions that should be asked on the open forums, I won't respond. I decline all "Friend Requests".

  5. #5
    Member
    Join Date
    May 2009
    Posts
    102

    Default

    Quote Originally Posted by Virchanza View Post

    ...

    K&R C contains a load of features which were thought to be good ideas back in the day, but turned out to be disastrous (stuff like implicit function declarations), which is why these "features" have been removed from future standards of C.
    What do you mean when you say implicit function declaration?
    All I have learned so far is that, the return type and argument type on the function prototype (declaration) must match with those in the function definition. Also, in the declaration:

    int myfunction (int x, int, y);

    The very first int is optional since the default return type is int, also x and y can be omitted.

    Is there anything else I am missing? I'm reading the ANSI edition of K&R by the way.
    ....
    Just one more thing:
    A declaration is where you introduce a name to the compiler. For instance, if you declare a function as follows:
    ...
    Same goes for declaring and defining variables.
    Declaring and defining variables? Are you referring to external variables here? where you have to first define a variable once outside a function and then declared inside a function using an optional "extern" in case the variable was defined before the particular function that used it.

  6. #6
    Very good friend of the forum Virchanza's Avatar
    Join Date
    Jan 2010
    Posts
    863

    Default

    Here's what "implicit function declaration" is all about. Take the following C program:

    Code:
    int main(void)
    {
        SomeMysteriousFunction(56);
    
        return 0;
    }
    This file should fail to compile, because the compiler hasn't got a clue what "SomeMysteriousFunction" is.

    ...however, if a compiler supports "implicit function declaration", then if it ever encounters the name of a function which has not been declared, then it just goes and assumes that the function had been declared as:

    Code:
    int SomeMysteriousFunction(...);
    This leads to really annoying compiler errors.

    It's possible to declare structs, functions and variables before defining them. Here's an example of declaring a struct:

    Code:
    struct MyStruct;  /* Declares the struct but doesn't define it */
    typedef struct MyStruct *PointerToMyStruct;
    
    However you'll get a compiler error if you try to create an object:
    
    struct MyStruct obj;  /* BANG */
    Here's an example of declaring a variable:

    Code:
    extern int i; /* Declares it but does NOT define it */
    
    int main(void)
    {
        i = 5;  /* Error here if "i" isn't define somewhere else in the program */
        return 0;
    }
    Variable declarations can be used if one source file if the variable is defined in a different source file. You can use the "extern" keyword to let the compiler know that it's a declaration and not a definition.
    Ask questions on the open forums, that way everybody benefits from the solution, and everybody can be corrected when they make mistakes. Don't send me private messages asking questions that should be asked on the open forums, I won't respond. I decline all "Friend Requests".

  7. #7
    Member
    Join Date
    May 2009
    Posts
    102

    Default

    Quote Originally Posted by Virchanza View Post
    Here's what "implicit function declaration" is all about. Take the following C program:

    Code:
    int main(void)
    {
        SomeMysteriousFunction(56);
    
        return 0;
    }
    This file should fail to compile, because the compiler hasn't got a clue what "SomeMysteriousFunction" is.

    ...however, if a compiler supports "implicit function declaration", then if it ever encounters the name of a function which has not been declared, then it just goes and assumes that the function had been declared as:
    I guess this was mentioned in the book. First you declare, then you define, then you use a function.




    [/code]Here's an example of declaring a variable:

    Code:
    extern int i; /* Declares it but does NOT define it */
    
    int main(void)
    {
        i = 5;  /* Error here if "i" isn't define somewhere else in the program */
        return 0;
    }
    Variable declarations can be used if one source file if the variable is defined in a different source file. You can use the "extern" keyword to let the compiler know that it's a declaration and not a definition.
    I know this one. Here, you are trying to declare a global variable which is useable throughout the rest of the source (so you put it on top). However, since the variable was defined in another file, then you need to use the extern keyword.

    Normally, in single source file, extern declaration is used inside the functions where you want to use the external/global variable when the order looks like this:

    main(){}
    myfunct1(){}
    myfunct2(){}
    int x=1;

    That is, int x was defined after it could be used, maybe in one of those functions.
    So if you want to use it in any of those functions you need something that looks like this:

    main()
    {
    extern int x;
    }

    I hope I got this right. This was also mentioned in that book by the way.

  8. #8
    Very good friend of the forum Virchanza's Avatar
    Join Date
    Jan 2010
    Posts
    863

    Default

    Before I begin, I should define what a "translation unit" is. A translation unit is a C source file after all of its header files have been copy-and-pasted into it, and after all macros have been expanded.

    A translation unit is what gets fed into the C compiler, and the C compiler produces an "object file" from it.

    All the object files are then collected together and are put through the linker. The linker spits out an executable file.

    Quote Originally Posted by wif1bust3r View Post
    However, since the variable was defined in another file, then you need to use the extern keyword.
    The "extern" keyword gets abused a little bit in C. What it's supposed to do is make something have "external linkage", meaning that it will be accessible from other translation units, but somehow they decided in this context that it should turn a variable definition into a variable declaration.

    Normally, in single source file, extern declaration is used inside the functions where you want to use the external/global variable when the order looks like this:

    main(){}
    myfunct1(){}
    myfunct2(){}
    int x=1;
    You'll never see that. I can't think of any reason to define variables after all of the functions, never seen it done. However there's nothing stopping you from doing it.

    That is, int x was defined after it could be used, maybe in one of those functions.
    So if you want to use it in any of those functions you need something that looks like this:

    main()
    {
    extern int x;
    }

    I hope I got this right. This was also mentioned in that book by the way.
    Yes that's right. In order to satisfy the C compiler, you need to make sure that everything is declared. In order to satisfy the linker, you need to make sure that everything is defined.

    Imagine you have three files, two sources files and one header file.

    Code:
    /* This file is a.c */
    
    int i;  /* This is a definition */
    Code:
    /* This file is a.h */
    
    extern int i;  /* This is a declaration */
    Code:
    /* This file is b.c */
    
    #include "a.h"   /* Now "i" has been declared in b.c */
    
    int main(void)
    {
        i = 4;
    
        return 0;
    }
    If you compile both the source files, you'll get two object files: a.o and b.o. If you were to put b.o through a linker on its own, you'd get a linker error because "i" is never defined. However if you put both the object files through a linker, everything will be fine because everything is defined. Each object file contains a table listing all of the stuff inside it that has "external linkage" (i.e. a list of all the stuff that should be made available to other object files).

    Oh yeah by the way, to get "internal linkage", you use "static", as in:

    Code:
    static int i = 0;
    (but beware that the "static" keyword does different things in different contexts)
    Ask questions on the open forums, that way everybody benefits from the solution, and everybody can be corrected when they make mistakes. Don't send me private messages asking questions that should be asked on the open forums, I won't respond. I decline all "Friend Requests".

  9. #9
    Member
    Join Date
    May 2009
    Posts
    102

    Default Practical usage of Unions

    (K&R Section 6.8 - Unions)

    In the example:


    To declare:
    Code:
    union u_tag {
          int ival;
          float fval;
          char *sval;
    } u;
    And to use:

    "If the variable utype is used to keep track of the current type stored in u, then one might see the code such as"

    Code:
    if (utype == INT)
       printf("%d\n", u.ival);
    
    if (utype == FLOAT)
       printf("%f\n", u.fval);
    
    if (utype == STRING)
       printf("%s\n", u.sval);
    
    else
        printf("bad type %d in utype\n", utype);
    For once I thought unions is a C feature, like in other languages I know such as perl, that makes it no longer a requirement to declare a variable to be of a particular type (whether it is an int, character, or a float, simply declaring "my variable;" in perl would work.

    Another description is "Unions provide a way to manipulate different kinds of data in a single area of storage, without embedding any machine-dependent information in the program". I would assume this has something to do with whether an integer in a particular machine would occupy 16 or 32 bits.

    So for the above example using the union "u" I thought this is the way I'd use it:

    Code:
    #include <stdio.h>
    
    
    main()
    {
    int x = 1;
    int y = 2;
    
    union u_tag {
          int ival;
          float fval;
          char *sval;
     
    } u;
    
    u.ival = x + y;
    u.fval = x + y;
    
    printf("%d\n", u.ival);
    printf("%1.2f\n", u.fval);
    Hoping I would get:

    3
    3.00

    Surprisingly, the first printf didn't even print what I was expecting, instead gave me:

    1077936128
    3.00


    What's up with that 1077936128??

    Can anyone kindly give me a more layman's usage of unions?
    What about those "utype == XXX" expression? INT, FLOAT, and STRING are macros, right? Macros for what numbers?

    All I know is that unions are like structures, only that unlike structures, the members must be located in on particular place in the memory, and cannot have more than 1 variable of a particular type.

  10. #10
    Very good friend of the forum Gitsnik's Avatar
    Join Date
    Jan 2010
    Location
    The Crystal Wind
    Posts
    851

    Default

    Quote Originally Posted by wif1bust3r View Post
    u.ival = x + y;
    u.fval = x + y;

    printf("%d\n", u.ival);
    printf("%1.2f\n", u.fval);
    You're double assigning your union (you're using it wrong). If you reverse the u.ival = and u.fval = lines you will see a different result.

    A union is a single data structure that can have many different types, but it can only have one type at a time (so you need to check it against the INT, FLOAT or so on).

    Code:
    #include <stdio.h>
    
    int main() {
    	union u_tag {
    		float fval;
    		int ival;
    	} u;
    
    	u.ival = 2;
    	printf("%d\n", u.ival);	// we pushed in an int
    
    	u.fval = 3.00;
    	printf("%.2f\n", u.fval); // we pushed a float
    
    	return 0;
    }
    Will perform how you would expect.

    On your INT, FLOAT etc. question, I can't recall whether they are macros but you should think of them as:

    Code:
    if(lastpushedvalueforunion == INT) {
    	// we put an int in our union, process it as an int (maybe we want to convert it later)
    }
    You will need to look into the INT definitions harder, my C reference text is too far away to do it for you!
    Still not underestimating the power...

    There is no such thing as bad information - There is truth in the data, so you sift it all, even the crap stuff.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •