Thread: Learning C99 using Linux and GCC

  1. #1
    Registered User
    Join Date
    Mar 2019
    Posts
    11

    Unhappy Learning C99 using Linux and GCC

    Hi all,
    I'm working through a book on electrical principles, transcoding
    the end of chapter BASIC programs into C. I'm using the following version of gcc and Ubuntu.


    $ gcc --version
    gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
    Copyright (C) 2013 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


    With my latest small program, gcc is generating the following error
    and I really don't see what the problem is. I should state here
    that I am more used to C89 than C99 and so I wonder if the formatting of my code in the final for() loop is not suitable for the latter.


    First, here are the contents of my makefile.

    Code:
    P=sect_13_9
    OBJECTS=
    CFLAGS= -g -Wall
    LDLIBS= -lm
    CC=c99
    $(P): $(OBJECTS)
    I should state that this has worked for several other programs with
    only a change in the name of the program in the first line.


    Now here are the contents of my source file.
    Code:
    /* sect_13_9.c */
    
    
    #include <stdio.h>
    #include <stdlib.h>    // For system().
    #include <math.h>      // For pow().
    
    
    int main(void)
    {
      char cr = 'a';              // Remove <cr> from input stream/buffer. 'a' is dummy value.
      float Vdc = 0.0f;           // User specified value of DC voltage source.
      float capacitance = 0.0f;   // User specified value of capacitance.
      float resistance = 0.0f;    // User specified value of resistance.
      float timeIntervals = 0.0f; // User specified number of time intervals.
    
    
      system("clear");  // Clear the screen.
    
    
      // Tell the user what this program does.
      printf("This program computes and tabulates the instantaneous\n");
      printf("capacitor voltage and percent of full charge at\n");
      printf("number of specified time intervals during charging\n");
      printf("in a specified RC circuit.\n\n");
      printf("Enter the Dc source voltage, Resistance in Ohms,\n");
      printf("Capacitance in Farads, and desired number of time intervals.\n");
      
      // Generate delay to allow user to read previous text.
      for (int t = 0; t <= 4000; ++t)
        ;                              // NULL statement.
       system("clear");
      
      // Gather input from user.
      printf("DC source voltage : ");
      scanf("%f%c", &Vdc, &cr);
      printf("Capacitance in Farads : ");
      scanf("%f%c", &capacitance, &cr);
      printf("Resistance on Ohms : ");
      scanf("%f%c", &resistance, &cr);
      printf("Number of time intervals, tau : ");
      scanf("%f%c", &timeIntervals, &cr);
      system("clear");
      
      // Display column headings.
      printf("Time (sec\tCapacitor Voltage\t%% of Full Charge\n");
      
      // Perform calculations and display results.
      for (float time = 0.0f; time <= (5 * resistance * capacitance); time = (5 * resistance * capacitance) / timeIntervals);
      {
        float exponent = time / (resistance * capacitance);   // Line 50. This comment does not occur in source file.
        float v = Vdc * (1 - pow(2.718, -exponent));
        float pfc = (v / Vdc) * 100;
        printf("%fs\t%fV\t%f%%", time, v, pfc);
      }
      
      // Exit program.
      return 0;
    }
    Now here is the error generated by gcc.


    $ make
    c99 -g -Wall sect_13_9.c -lm -o sect_13_9
    sect_13_9.c: In function ‘main’:
    sect_13_9.c:50:22: error: ‘time’ undeclared (first use in this function)
    float exponent = time / (resistance * capacitance);
    ^
    sect_13_9.c:50:22: note: each undeclared identifier is reported only once for each function it appears in
    make: *** [sect_13_9] Error 1


    As the variable "time" is declared and initialised in the first
    clause of the surrounding for() loop, I really don't see why this
    error is being generated. Could someone please explain what I
    clearly don't understand.


    Thanks in advance,


    Best regards,


    Stuart

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You are correct.
    Your final for loop is new syntax for C99.

    Also, calling your variable 'time' will conflict with the function of the same name in time.h (if you were to ever include it).

    > for (int t = 0; t <= 4000; ++t)
    1. 4000 is nothing to a CPU running at GHz speed.
    2. Most compilers will optimise it away as a 'do nothing' loop, especially at higher optimisation levels.

    You should probably get rid of all those system(clear) calls.
    system() is a known security vulnerability, so it's best avoided.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Your "for" is (reformated):

    Code:
      for ( float time = 0.0f; 
            time <= ( 5 * resistance * capacitance ); 
            time = ( 5 * resistance * capacitance ) / timeIntervals );
      {
        float exponent = time / ( resistance * capacitance ); // Line 50. This comment does not occur in source file.
        float v = Vdc * ( 1 - pow ( 2.718, -exponent ) );
        float pfc = ( v / Vdc ) * 100;
        printf ( "%fs\t%fV\t%f%%", time, v, pfc );
      }
    ...
    Notice the ';' before the block?

    BTW:
    Nowadays GCC defaults to an extended variant of ISO 9989:2011:

    Code:
    $ gcc --version
    gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
    Copyright (C) 2017 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    $ gcc -dM -E - < /dev/null | grep STDC_VERSION
    #define __STDC_VERSION__ 201112L

  4. #4
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    And the increment should be "time += 5 * resistance * capacitance / timeIntervals".

    And you can use expf( -expoent ), instead of powf( 2.718, -expoent ).
    Last edited by flp1969; 03-13-2019 at 12:33 PM.

  5. #5
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Just as a comment - If you get rid of the system("clear") calls, your programme is fine to run on windows And it might be handy to look back at what values were entered (if the results are a bit unexpected)

    And as an electonics guy - Make your capacitance in nF
    Fact - Beethoven wrote his first symphony in C

  6. #6
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by Click_here View Post
    Just as a comment - If you get rid of the system("clear") calls, your programme is fine to run on windows And it might be handy to look back at what values were entered (if the results are a bit unexpected)

    And as an electonics guy - Make your capacitance in nF
    I would have picked micro-farads instead of nano-farads; but, nano-farads is much better than farads.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  7. #7
    Registered User
    Join Date
    Mar 2019
    Posts
    11
    Hi Salem,

    Thanks for the reply.

    Quote Originally Posted by Salem View Post
    You are correct.
    Your final for loop is new syntax for C99.

    Also, calling your variable 'time' will conflict with the function of the same name in time.h (if you were to ever include it).

    > for (int t = 0; t <= 4000; ++t)
    1. 4000 is nothing to a CPU running at GHz speed.
    2. Most compilers will optimise it away as a 'do nothing' loop, especially at higher optimisation levels.

    You should probably get rid of all those system(clear) calls.
    system() is a known security vulnerability, so it's best avoided.
    WRT naming the variable "time", I see what you mean. It probably would have been better to come up with an alternate name for that variable. However, I was just trying to code up a C program that was as close to the BASIC original as possible.

    WRT the value of the delay in the for() loop. Although I will probably just increase this value to something like 4,000,000. In reality I understand that this would be the place to make use of time.h.

    WRT security. Thanks for the heads up. These system() calls were included because the BASIC program was making use of CLS at those points. Again, just trying to stay close to the spirit of the BASIC original.

    Thanks again for the help. It is much appreciated.

    Best regards,

    Stuart

  8. #8
    Registered User
    Join Date
    Mar 2019
    Posts
    11
    Hi flp1969,

    Thanks for your reply.

    Quote Originally Posted by flp1969 View Post
    Your "for" is (reformated):

    Code:
      for ( float time = 0.0f; 
            time <= ( 5 * resistance * capacitance ); 
            time = ( 5 * resistance * capacitance ) / timeIntervals );
      {
        float exponent = time / ( resistance * capacitance ); // Line 50. This comment does not occur in source file.
        float v = Vdc * ( 1 - pow ( 2.718, -exponent ) );
        float pfc = ( v / Vdc ) * 100;
        printf ( "%fs\t%fV\t%f%%", time, v, pfc );
      }
    ...
    Notice the ';' before the block?

    BTW:
    Nowadays GCC defaults to an extended variant of ISO 9989:2011:

    Code:
    $ gcc --version
    gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
    Copyright (C) 2017 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    $ gcc -dM -E - < /dev/null | grep STDC_VERSION
    #define __STDC_VERSION__ 201112L
    WRT the ";" at the end of the for() statement. I had not realised that the ";" was required. I've yet to find a good downloadable pdf-based tutorial on C99.

    WRT GCC defaulting to C11. I note that you are running Ubuntu 18.04. Sadly my system is I686 and so is limited to running (what I believe is) the last 32-bit version of Kubuntu, 14.04 LTS. I don't know if C11 was implemented on the version of GCC that was supplied with Kubuntu 14.04, and if so to what extent.

    Thanks very much for your help. It is much appreciated.

    Best regards,

    Stuart

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by stuarte83
    WRT the ";" at the end of the for() statement. I had not realised that the ";" was required.
    Actually, flp1969 copied that from your own code to point it out as a syntactically legal logic error: the semi-colon becomes the terminator for an empty statement that is the body of the for loop, which can be useful, but is a mistake here since you want to do something in the loop body.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    Mar 2019
    Posts
    11
    Hi again flp1969,

    Thanks for this reply as well.

    Quote Originally Posted by flp1969 View Post
    And the increment should be "time += 5 * resistance * capacitance / timeIntervals".

    And you can use expf( -expoent ), instead of powf( 2.718, -expoent ).
    WRT using the "+=" operator. Oops, my bad. https://cboard.cprogramming.com/images/icons/icon11.png

    WRT using expf(-exponent): what library provides the expf() function and is that library provided as a standard part of GCC ?

    Thanks again for this help as well.

    Best regards,

    Stuart

  11. #11
    Registered User
    Join Date
    Mar 2019
    Posts
    11
    Hi Click_here,

    Thanks for your reply.

    Quote Originally Posted by Click_here View Post
    Just as a comment - If you get rid of the system("clear") calls, your programme is fine to run on windows And it might be handy to look back at what values were entered (if the results are a bit unexpected)

    And as an electonics guy - Make your capacitance in nF
    I included the calls to system() because the original BASIC program was using CLS at those points. I was just trying to stay as close as possible to the spirit of the original program.

    WRT making capacitance in nF: again the book BASIC program that I was transcoding requested that the value for capacitance be entered in Farads, as you will see in my original posting. Still, I do take your point. It is more usual to quote uF or nF values for capacitance.

    Thanks again for your help. It is much appreciated.

    Best regards,

    Stuart

  12. #12
    Registered User
    Join Date
    Mar 2019
    Posts
    11
    Hi laserlight,

    Quote Originally Posted by laserlight View Post
    Actually, flp1969 copied that from your own code to point it out as a syntactically legal logic error: the semi-colon becomes the terminator for an empty statement that is the body of the for loop, which can be useful, but is a mistake here since you want to do something in the loop body.
    Thank you for your reply and for pointing out my misunderstanding of the point raised by flp1969. It is much appreciated.

    Best regards,

    Stuart

  13. #13
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    expf() -- the f suffix is used to deal with float type, exp() deals with double. The prototype is found in the same math.h header you used to get pow(). It is in ISO 9989 standard.

    What's the difference? Well... pow() is generic, and some processors, with math co-processors, have specialized instructions to deal with e^x.

  14. #14
    Registered User
    Join Date
    Mar 2019
    Posts
    11
    Hi flp1969,


    Quote Originally Posted by flp1969 View Post
    expf() -- the f suffix is used to deal with float type, exp() deals with double. The prototype is found in the same math.h header you used to get pow(). It is in ISO 9989 standard.

    What's the difference? Well... pow() is generic, and some processors, with math co-processors, have specialized instructions to deal with e^x.
    Thank you for another very informative reply.

    Best regards,

    Stuart

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Best UNIX/Linux OS for technical learning
    By subdene in forum General Discussions
    Replies: 8
    Last Post: 08-12-2016, 04:31 AM
  2. (Where) learning linux tcp/ip sockets
    By codecaine_21 in forum Networking/Device Communication
    Replies: 4
    Last Post: 09-17-2010, 05:54 PM
  3. newbie:Learning C programming in GNU/Linux with gcc-4.x
    By prakashjk in forum C Programming
    Replies: 2
    Last Post: 01-29-2009, 03:18 PM
  4. Interested in learning how to program in linux
    By carrja99 in forum Linux Programming
    Replies: 4
    Last Post: 10-17-2002, 01:09 AM
  5. Learning Linux
    By MethodMan in forum Linux Programming
    Replies: 4
    Last Post: 10-09-2002, 12:05 AM

Tags for this Thread