Thread: Array of functions

  1. #16
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    There's not anything wrong with using printf %d on a char (it is perfectly safe and acceptable), however, stylistically it is just silly to use a char to pass around an int:

    Code:
    void func2(char token, char times)
    should be:
    Code:
    void func2(char token, int times)
    Unless there is a reason you need a char there.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  2. #17
    Registered User
    Join Date
    Jun 2010
    Posts
    182
    Quote Originally Posted by MK27 View Post
    There's not really anything wrong with using %d on a char, however, stylistically it is just silly to use a char to pass around an int:

    Code:
    void func2(char token, char times)
    should be:
    Code:
    void func2(char token, int times)
    Unless there is a reason you need a char there.
    Well I have reasons indeed, because the pgm I'm dreaming about is
    doing some sort of compression, so if I use 1 byte to represent numbers from 0 to 255
    instead of an integer, I spare 3 bytes.

  3. #18
    Registered User
    Join Date
    Jun 2010
    Posts
    182
    Quote Originally Posted by Elysia View Post
    Yes, they can be used in many ways. It is a storage of 1 byte, but it's usually used to represent characters.
    But that's not the problem. You can safely pass <= 255 to it, but you are lying to printf by saying you are passing an int:
    printf("Token = \'%c\' - to repeat %d times tripled\n",token,times);
    Either you pass an int from the beginning:
    Code:
      void func5(char token, int times)
    {
        printf("Called Func5!\n");
        printf("Token = \'%c\' - to repeat %d times tripled\n",token,times);
    }
    Or you cast the char to an int:
    Code:
      void func5(char token, char times)
    {
        printf("Called Func5!\n");
        printf("Token = \'%c\' - to repeat %d times tripled\n",token,(int)times);
    }
    The format specifier is there to tell printf what types you are passing to it, so you can obviously not lie. That will cause undefined behavior.
    Well it actually works, and nothing I've read so far suggests not
    using chars in this way as well. Of course if problems could arise, I'd prefer
    to typecast to int in order to save the original compressing idea.

  4. #19
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You never notice undefined behavior and implementation defined behavior until it's too late. One second it works, the next it breaks. And you can get different results on different compilers and platforms. Not a good idea.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #20
    Registered User
    Join Date
    Jun 2010
    Posts
    182
    Quote Originally Posted by Elysia View Post
    You never notice undefined behavior and implementation defined behavior until it's too late. One second it works, the next it breaks. And you can get different results on different compilers and platforms. Not a good idea.
    Are you sure? I've only read ANSI C manuals so far...

  6. #21
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by frktons View Post
    Well I have reasons indeed, because the pgm I'm dreaming about is
    doing some sort of compression, so if I use 1 byte to represent numbers from 0 to 255
    instead of an integer, I spare 3 bytes.
    Yes, I used to believe using a short int (2 bytes) was better than using an int because of this.

    In fact, it is not true. Compilers and desktop processors tend to deal with things in units of 4 bytes (32-bits) or 8 bytes (64-bits). Anything smaller than this must be padded up with zeros when the processor works with the value, meaning an int is the most efficient unit, because no additional padding and chopping operations are necessary.

    WRT to just storage, odd numbers don't work either, and unless the compiler finds a clever way to segment stuff, it will probably pad this out to.

    In other words, you think you are saving space but you are probably not, and the assembly level code for your program, created by the compiler, will be less efficient, and/or the processor will have to resort to additional (time wasting operations) to deal with the single byte.

    You could place both chars into a single int and bitshift them out, that might be a slight optimization, but I think most people would consider it pointless.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #22
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Elysia View Post
    You never notice undefined behavior and implementation defined behavior until it's too late.
    In fact, printf'ing a char with %d is not undefined behavior, it's secured by the standard. So this logic does not apply here.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #23
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Promotion rules? What do they say?
    Btw, regardless of whether it's defined or not, I would say I recommend it anyway to avoid confusion and raised eye browns.
    Also note that chars may not be as fast as ints, but they will take up less space in memory. Regardless of how the CPU does it, it will take less memory storage, because the CPU has to pad it, not C.
    And the performance impact from ints vs chars is negligible.
    On x64 systems, it's even worse because each number has to be 64 bits. Are you going to use a 64-bit type instead? 8 bytes vs 1? A lot of wasted memory there.
    Last edited by Elysia; 06-30-2010 at 09:17 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #24
    Registered User
    Join Date
    Jun 2010
    Posts
    182
    Quote Originally Posted by MK27 View Post
    Yes, I used to believe using a short int (2 bytes) was better than using an int because of this.

    In fact, it is not true. Compilers and desktop processors tend to deal with things in units of 4 bytes (32-bits) or 8 bytes (64-bits). Anything smaller than this must be padded up with zeros when the processor works with the value, meaning an int is the most efficient unit, because no additional padding and chopping operations are necessary.

    WRT to just storage, odd numbers don't work either, and unless the compiler finds a clever way to segment stuff, it will probably pad this out to.

    In other words, you think you are saving space but you are probably not, and the assembly level code for your program, created by the compiler, will be less efficient, and/or the processor will have to resort to additional (time wasting operations) to deal with the single byte.

    You could place both chars into a single int and bitshift them out, that might be a slight optimization, but I think most people would consider it pointless.
    You are right, I am aware of the Assembly level coding that the compilers do.
    But the implementation I've in my mind is just to store compressed data inside
    variables inside the program, and when I read them one byte at a time, I'm just
    using low bytes like AL or BL or CL and so on registers. Probably the inner part
    of the routine dealing with these codes will be written in Assembly, to take advantage
    of the speed and capacity of the low level coding. I don't have any problem of portability
    in my mind because the pgm will just run on my pc Win 7 Ultimate 64 bit.

    Promotion rules? What do they say?
    Btw, regardless of whether it's defined or not, I would say I recommend it anyway to avoid
    confusion and raised eye browns.
    Also note that chars may not be as fast as ints, but they will take up less space in memory.
    Regardless of how the CPU does it, it will take less memory storage, because the CPU has to pad it, not C.
    And the performance impact from ints vs chars is negligible.
    On x64 systems, it's even worse because each number has to be 64 bits. Are you going to use a 64-bit type
    instead? 8 bytes vs 1? A lot of wasted memory there.
    Please read the objective the pgm will have, I understand all these recommendations and
    I'd probably say the same thing. But this is a specific case. I need to compress data inside
    a variable inside a program.
    Last edited by frktons; 06-30-2010 at 09:21 AM.

  10. #25
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Elysia View Post
    Promotion rules? What do they say?
    That the char is promoted to an int -- eg, you could use %hhd in which case it's promoted to an int anyway, then converted to a char, so this is sort of pointless. It's the same as:
    Code:
    char a, b;
    a = a + b;
    Arithmetic operations are not performed on chars. They default to ints in this case (which is another example of how using a char in place of an int only involves more work, not less), then the result is truncated into a char.
    Last edited by MK27; 06-30-2010 at 09:21 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  11. #26
    Registered User
    Join Date
    Jun 2010
    Posts
    182
    Quote Originally Posted by MK27 View Post
    That the char is promoted to an int -- eg, you could use %hhd in which case it's promoted to an int anyway, then converted to a char, so this is sort of pointless. It's the same as:
    Code:
    char a, b;
    a = a + b;
    Arithmetic operations are not performed on chars. They default to ints in this case (which is another example of how using a char in place of an int only involves more work, not less), then the result is truncated into a char.
    I'm NOT going to use char to perform arithmetic, or anything stupid. Please believe me. :-)

  12. #27
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by frktons View Post
    I'm NOT going to use char to perform arithmetic, or anything stupid. Please believe me. :-)
    There is nothing stupid about performing arithmetic on chars, it's allowed, normal, sometimes necessary. The point is it incurrs a time penalty for handling a single byte. The EXACT SAME THING IS TRUE with regatd to using printf(%d) on a char. It is exactly the same penalty. It is not undefined or unsafe, it's just less efficient. You are not using an 8-bit processor. You are using a 32 or 64 bit processor.

    So as I tried to explain before, you are not saving anything this way. You are actually de-optimizing (the opposite of your intent).

    I still have old code where I used short ints for stuff because I thought that was "saving", but it's not! It's WASTE.
    Last edited by MK27; 06-30-2010 at 09:36 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  13. #28
    Registered User
    Join Date
    Jun 2010
    Posts
    182
    Quote Originally Posted by MK27 View Post
    There is nothing stupid about performing arithmetic on chars, it's allowed, normal, sometimes necessary. The point is it incurrs a time penalty for handling a single byte. The EXACT SAME THING IS TRUE with regatd to using printf(%d) on a char. It is exactly the same penalty. It is not undefined or unsafe, it's just less efficient. You are not using an 8-bit processor. You are using a 32 or 64 bit processor.

    So as I tried to explain before, you are not saving anything this way. You are actually de-optimizing (the opposite of your intent).

    I still have old code where I used short ints for stuff because I thought that was "saving", but it's not! It's WASTE.
    Of course, and I repeat I'm well aware of that.

    At the Assembly level dealing with 1 byte is possible but less efficient
    than dealing with 4 or 8 bytes at a time like in any other language. But there are
    situations in which you HAVE to work at a byte level or even at a bit level.
    It just depends on what you have to do. Compressing data is not the same of
    doing general programming, it is a specific task with specific requirements.
    The main goal is reducing space, the second one is doing it at a decent speed and in
    a safe non destructive way.
    Last edited by frktons; 06-30-2010 at 09:43 AM.

  14. #29
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by frktons View Post
    But there are
    situations in which you HAVE to work at a byte level or even at a bit level.
    It just depends on what you have to do.
    It's your program, but the code you posted does not need to use a char in place of an int. So in terms of "what you have to do" there, you should be using an int.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  15. #30
    Registered User
    Join Date
    Jun 2010
    Posts
    182
    Quote Originally Posted by MK27 View Post
    It's your program, but the code you posted does not need to use a char in place of an int. So in terms of "what you have to do" there, you should be using an int.
    I agree, so this would be better, I suppose:
    Code:
     // Program to demonstrate
      // array of functions
      #include<stdio.h>
    
      // -- FUNCTION PROTOTYPES --
    
      void func1(char,int);
      void func2(char, int);
      void func3(char,int);
      void func4(char,int);
      void func5(char, int);
      // -- ENDS --
    
      int main(void)
      {
       // notice the prototype
    
       void (*ptr[5])(char, int);
    
       // arrays are made to point
       // at the respective functions
    
       ptr[0]=&func1;
       ptr[1]=&func2;
       ptr[2]=&func3;
       ptr[3]=&func4;
       ptr[4]=&func5;
    
       // now the array elements
       // point to different functions
       // which are called just like
       // we access the elements of
       // an array
    
       for(int i=0;i<5;i++)
         ptr[i]('A',(int) ' ');
       return 0;
      }
    
      // -- FUNCTIONS DEFINITION --
    
      void func1(char token, int times)
      {
       printf("Called Func1!\n");
       printf("Token = \'%c\' - to repeat %d times\n",token,times);
      }
    
      void func2(char token, int times)
      {
       printf("Called Func2!\n");
       printf("Token = \'%c\' - to repeat %d times incremented by 1\n",token,times);
      }
    
      void func3(char token,int times)
      {
       printf("Called Func3!\n");
       printf("Token = \'%c\' - to repeat %d times doubled\n",token,times);
      }
    
      void func4(char token, int times )
      {
       printf("Called Func4!\n");
       printf("Token = \'%c\' - to repeat %d times doubled except the last time\n",token,times);
      }
    
      void func5(char token, int times)
      {
       printf("Called Func5!\n");
       printf("Token = \'%c\' - to repeat %d times tripled\n",token,times);
      }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Array of Functions?
    By CPlus in forum C++ Programming
    Replies: 10
    Last Post: 05-10-2010, 02:06 PM
  2. warning: excess elements in array initializer
    By redruby147 in forum C Programming
    Replies: 6
    Last Post: 09-30-2009, 06:08 AM
  3. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  4. Merge sort please
    By vasanth in forum C Programming
    Replies: 2
    Last Post: 11-09-2003, 12:09 PM
  5. Array Program
    By emmx in forum C Programming
    Replies: 3
    Last Post: 08-31-2003, 12:44 AM