Thread: Can I assign address of pointer to array ?

  1. #1
    Registered User
    Join Date
    Jan 2016
    Posts
    84

    Can I assign address of pointer to array ?

    Hi,

    I want to assign address of pointer to array.

    The reason for this is that the pointer would be a global pointer to have the address of a function pointer argument.

    Then at task manager I have a main array buffer which holds transmitting data routine.

    This is my example:

    Code:
    #include <stdio.h>#include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    #include <stdbool.h>
    
    
    
    
    uint8_t str_counts, i;
    const char *str_ptr;
    const char *str1 = {"hi how are you ?"};
    uint8_t task_buffer[16];
    
    
    // functions
    void data_print(void);
    void write_chars(const char *str);
    
    
    
    
    int main(){
    
    
        str_counts = strlen(str1);
    
    
    
    
        str_ptr = str1;
        //task_buffer = str_ptr;
    
    
    
    
        //printf("%p\n",str1);
        //printf("%p\n",str_ptr);
        //printf("%p\n",task_buffer);
    
    
        write_chars(str1);
    
    
        return 0;
    }
    
    
    void data_print(void){
        printf("hi");
        task_buffer[0] = str_ptr;
        for(i=0; i<str_counts; i++){
            printf("%c",task_buffer[i]);
            //printf("%c",str_ptr[i]);
        }
    }
    void write_chars(const char *str){
        str_ptr = str;
        data_print();
    }
    I commented

    Code:
    printf("%c",str_ptr[i]);
    which is the working line.

  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
    Well no, you can't assign the contents of what a pointer points to to an array.

    That's why we have functions like strcpy.

    You should find a way of solving your question without so many messy globals.
    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
    Jan 2016
    Posts
    84
    Yep, you're right. But I really need a global pointer at least to hold anything that I need to pass to another function. Would agree with me or there's another way of getting the data passed to one function and find it in another one ?

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Is data_print really an ISR capable of only printing one character at a time to some external device?
    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.

  5. #5
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by wolfrose View Post
    Yep, you're right. But I really need a global pointer at least to hold anything that I need to pass to another function. Would agree with me or there's another way of getting the data passed to one function and find it in another one ?
    Code:
    void dosomething( int *p )
    { *p = 1; }
    
    void print( int *p )
    { printf( "%d\n", *p ); }
    
    int main ( void )
    {
      int x;
    
      dosomething( &x );
      print( &x );
    }

  6. #6
    Registered User
    Join Date
    Jan 2016
    Posts
    84
    Quote Originally Posted by Salem View Post
    Is data_print really an ISR capable of only printing one character at a time to some external device?
    It's a function for transmitting one byte, it's a code for Arduino LCD128x64

  7. #7
    Registered User
    Join Date
    Jan 2016
    Posts
    84
    This is my complete code, it's working like 90%, I just need to do some improvements.

    It's a console simulation for Arduino code. Because I want to design the main FSM code in codeblocks then move the actual implementation to Arduino code.

    Code:
    /*    Title:    function pointers    Date:    Thu, 30 July 2020
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    #include <stdbool.h>
    #include <malloc.h>
    #include <math.h>
    
    
    // definitions
    #define CURSOR_MOVE         0
    #define PIXEL_WRITE         1
    #define CHARS_WRITE         2
    #define GRAPHICS_SET        3
    
    
    // enumerations
    enum TASK_STATES{CMD, DATA, STRING};
    enum TASK_STATES state;
    
    
    // delay variables
    uint32_t dly_st, delay_period;
    bool dly_lock, lock;
    bool write_lock;
    uint16_t i, counter, counts, str_counts, cmd_state;
    
    
    // command / data variables
    char * str_buf;
    const char *str_ptr;
    const char *str1 = {"hi how are you ?"};
    // basic pixel variables
    uint8_t y,x, task_buffer[16];
    bool row2_4, graphics;
    
    
    // functions
    void task_switcher(void);
    void task1(void);
    void task2(void);
    void write_chars(uint8_t row, uint8_t col, const char *str);
    void graphics_set_mode(bool mode);
    void transmit(uint8_t cmd);
    void delay_routine(void);
    
    
    // function pointers
    void (*fun_ptr)(void);      // main function pointer
    
    
    int main(){
    
    
        //graphics_set_mode(1); // not finished !
         task1();printf("\n\n>>2nd function>>\n\n\n");task2();
        //write_chars(0,0,str1);
    
    
        return 0;
    }
    
    
    //////////////////////////////////////////////////////
    // lcd transmission commands/data, locks and callback functions
    void task_switcher(void){
        if(!dly_lock){
            switch(state){
                case CMD:
    
    
                    if(counter < counts){
                        transmit(task_buffer[counter]);
                        counter++;
                    }
                    else{
                        if(cmd_state == PIXEL_WRITE){
                            counts = 4;         // counter = 2 at this point
                            state = DATA;
                        }
                        else if(cmd_state == CURSOR_MOVE || cmd_state == GRAPHICS_SET){
                            write_lock = 0;
                        }
                        else if(cmd_state == CHARS_WRITE){
                            counter = 0;
                            counts = str_counts;
                            state = DATA;
                            strcpy(task_buffer,str_ptr);
                        }
                    }
    
    
                break;
    
    
                case DATA:
                    if(counter < counts){
                        transmit(task_buffer[counter]);
                        counter++;
                    }
                    else{
                        write_lock = 0;
                        counter = 0;            // cleared for multiple pixels writes
    
    
                        if(cmd_state == PIXEL_WRITE){
                            counts = 2;
                            state = CMD;        // multiple pixels writes
                            printf("\n");       // for this program data display
                        }
    
    
                        if(cmd_state == CHARS_WRITE){
    
    
    
    
                        }
                    }
                break;
            }
        }
        else {delay_routine();}           // first check delay flag
        if(write_lock){task_switcher();}  // still between cmd1-data2
        else if(lock){fun_ptr();}         // method2 function pointer
        //else if(!write_lock){lock = 0;}   // finished writes ? : clear lock
    }
    
    
    void write_chars(uint8_t row, uint8_t col, const char *str){
        if(!lock){
            state = CMD;
            cmd_state = CHARS_WRITE;
            if(graphics){graphics_set_mode(0);}
            counter = 0; counts = 1;
            str_counts = strlen(str);
            str_ptr = str;
            lock = 1;
        }
        // identify row/column location
        else{
            if        (row == 1)task_buffer[0] = (0x80 + (col - 1));
            else if    (row == 2)task_buffer[0] = (0x90 + (col - 1));
            else if    (row == 3)task_buffer[0] = (0x88 + (col - 1));
            else if    (row == 4)task_buffer[0] = (0x98 + (col - 1));
        }
    
    
        write_lock = 1;
        task_switcher();
    }
    
    
    // graphics mode
    void graphics_set_mode(bool mode){
        if(!lock){
            state = CMD;
            cmd_state = GRAPHICS_SET;
            task_buffer[0] = 1;
            counter = 0; counts = 3;
            write_lock = 0;
            if(mode){
                task_buffer[1] = 11;
                task_buffer[2] = 22;
                graphics = 1;
            }
            else{
                task_buffer[1] = 33;
                task_buffer[2] = 44;
                graphics = 0;
            }
            write_lock = 1;
            lock = 1;
            task_switcher();
        }
    
    
    }
    
    
    void task2(void){
        if(!lock){
            fun_ptr = &task2;
            state = CMD;
            cmd_state = PIXEL_WRITE;
            x = 0; y = 0;
            counter = 0; counts = 2;
            lock = 1; row2_4 = 0; write_lock = 0;
        }
    
    
        if(y<2 && !row2_4){         // 1st half of lcd
            task_buffer[0] = y;   task_buffer[1] = x;
            task_buffer[2] = 'E';     task_buffer[3] = 'F';
        }
    
    
    
    
        if(y<4 && row2_4){         // 2nd half of lcd
            task_buffer[0] = y;   task_buffer[1] = x;
            task_buffer[2] = 'G'; task_buffer[3] = 'H';
        }
        x++; if(x>7){y++;x=0;}
        if(y>1){row2_4 = 1;}
        if(y>3){row2_4 = 0;lock = 0;}
    
    
        write_lock = 1;
        task_switcher();
    }
    
    
    void task1(void){
        if(!lock){
            fun_ptr = &task1;
            state = CMD;
            cmd_state = PIXEL_WRITE;
            x = 0; y = 0;
            counter = 0; counts = 2;
            lock = 1; row2_4 = 0; write_lock = 0;
        }
    
    
        if(y<2 && !row2_4){         // 1st half of lcd
            task_buffer[0] = y;   task_buffer[1] = x;
            task_buffer[2] = 'A'; task_buffer[3] = 'B';
        }
    
    
    
    
        if(y<4 && row2_4){         // 2nd half of lcd
            task_buffer[0] = y;   task_buffer[1] = x;
            task_buffer[2] = 'C'; task_buffer[3] = 'D';
        }
        x++; if(x>7){y++;x=0;}
        if(y>1){row2_4 = 1;}
        if(y>3){row2_4 = 0;lock = 0;}
    
    
        write_lock = 1;
        task_switcher();
    }
    
    
    // command tx
    void transmit(uint8_t cmd){
        if(state == CMD)      {printf("%d ",cmd);}
        else                   {printf("%c  ",cmd);}
    }
    
    
    // delay routine
    void delay_routine(void){if(dly_lock){dly_lock = 0;}}

  8. #8
    Registered User
    Join Date
    Jan 2016
    Posts
    84
    Quote Originally Posted by flp1969 View Post
    Code:
    void dosomething( int *p )
    { *p = 1; }
    
    void print( int *p )
    { printf( "%d\n", *p ); }
    
    int main ( void )
    {
      int x;
    
      dosomething( &x );
      print( &x );
    }
    OK, got the idea.

    So I can change the whole behavior of functions by changing the type of argument pass by address and not by a copy of that variable.

    But anyway, I need a buffer in my code and most of embedded system codes, they use a lot of global variables.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You have a lot of direct and indirect recursion of task_switcher().

    Multiple global variables called 'lock', 'count' and 'str' doesn't help with readability.

    Here's my take on your two tasks.
    Code:
    #include <stdio.h>
    #include <ctype.h>
    #include <unistd.h>
    
    #define LOOP_INTERVAL 1 /* mSec interval how often loop is called */
    #define WORK_INTERVAL 50 /* mSec interval how often we need to do something */
    
    typedef enum {
      s_init,       // The initial state
      s_task_init,  // A task is initialising
      s_task_run,   // A task is running
      s_task_exit,  // A task has finished
    } state_t;
    
    typedef struct {
      int   count;  // The number of things output so far
      int   length; // The number of things to output
      enum {
        is_int,     // output an int
        is_ptr,     // output a user-supplied buffer pointer
        is_buff     // output the local buffer
      }     type;
      union {
        int     ival;     // the int
        char *  ptr;      // the user pointer
        char    buff[10]; // the local buffer
      } u;
    } transmit_t;
    
    // This is your only global
    transmit_t transmit;
    
    void transmitter(transmit_t *t)
    {
      if ( t->count == t->length ) return;
      switch ( t->type ) {
        case is_int:
          printf("I=%d ", t->u.ival);
          break;
        case is_ptr:
          printf("P=%c ", t->u.ptr[t->count]);
          break;
        case is_buff:
        {
          char c = t->u.buff[t->count];
          if ( isprint(c) ) {
            printf("C=%c ", c);
          } else {
            // First two are Y/X coordinates
            printf("%c=%d ", t->count == 0 ? 'Y' : 'X', c);
          }
          break;
        }
      }
      t->count++;
      if ( t->count == t->length )
        printf("\n");
    }
    int transmit_done(const transmit_t *t) {
      return t->count == t->length;
    }
    
    
    typedef struct {
      const char *arg;    // something unique to each task
      int         x;
      int         y;
      int         row2_4;
    } taskdata_t;
    
    state_t task(taskdata_t *t, state_t s) {
      state_t result = s;
      if ( s == s_task_init ) {
        result = s_task_run;  // will be running next
        t->x = 0;
        t->y = 0;
        t->row2_4 = 0;
      }
      else if ( s == s_task_run ) {
        // Setup transmit buffer with the next sequence
        transmit.count = 0;
        transmit.length = 4;
        transmit.type = is_buff;
        transmit.u.buff[0] = t->y;
        transmit.u.buff[1] = t->x;
        transmit.u.buff[2] = t->arg[t->row2_4*2+0];
        transmit.u.buff[3] = t->arg[t->row2_4*2+1];
    
        t->x++;
        if (t->x > 7) {
          t->y++;
          t->x = 0;
        }
        if (t->y > 1) {
          t->row2_4 = 1;
        }
        if (t->y > 3) {
          result = s_task_exit;   // and we're done.
        }
      }
      return result;
    }
    
    void doWork() {
      static taskdata_t taskdata[2] = {
        { "ABCD" },
        { "EFGH" },
      };
      static int      task_id = 0;
      static state_t  state = s_init;
      switch(state) {
        case s_init:
          // Any other first time stuff
          state = s_task_init;
          break;
        case s_task_init:
        case s_task_run:
          state = task(&taskdata[task_id], state);
          break;
        case s_task_exit:
          task_id = (task_id + 1) % 2;
          state = s_task_init;
          break;
      }
    }
    
    // Top-level entry point on Arduino
    void loop() {
      static int count = 0;
      if ( ++count == WORK_INTERVAL ) {
        // First order of business is to complete the
        // output of the current LCD transmit buffer
        transmitter(&transmit);
    
        if ( transmit_done(&transmit) ) {
          // Then see if any regular work needs doing
          doWork();
        }
    
        // reset the work interval counter
        count = 0;
      }
    }
    
    // Top-level entry point on Host
    int main() {
      for(;;) {
        loop();
        usleep(LOOP_INTERVAL*1000);
      }
    }
    - use structs to group data with a common purpose, like the transmit buffer and the task data
    - use the static keyword on data in functions, to achieve persistence and some sense of scope, without resorting to a mass of globals.
    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.

  10. #10
    Registered User
    Join Date
    Jan 2016
    Posts
    84
    Thank you so much for writing a code for me. It would take me a serious time studying this code.

    I know that structs are useful but I'm moving step by step in using more advanced programming skills.
    I used to program in a very basic programming styles, starting with normal global variables, then the next step was the arrays.

    Then I moved to basic pointers, and now I'm working with enums.

    Now working with enums, they are basically a defined names with values and the object of the enum would be the variable that would work like the register to hold a value each time.

    I did the same method using definitions and a normal static global variable, so it's basically the same.


    ------------------------------------------------------------------------------------------------------------------

    Just did a 2nd quick check for the code, it seem a bit complicated to me as I have been doing basic C programming with Arduino for like 4 years but this code still more than my level.

    Just a quick question, why you use typedefs for the structs and enums ?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. comparing the address of a pointer to an array address for size
    By ridgerunnersjw in forum C Programming
    Replies: 4
    Last Post: 04-17-2020, 06:25 PM
  2. assign the value of an array to a pointer c++
    By kox in forum C++ Programming
    Replies: 8
    Last Post: 10-29-2012, 11:33 AM
  3. Assign a value to address of memory;
    By sergioms in forum C Programming
    Replies: 4
    Last Post: 03-22-2011, 02:28 PM
  4. assign value of pointer array
    By zcrself in forum C Programming
    Replies: 12
    Last Post: 08-17-2009, 02:12 PM
  5. Replies: 6
    Last Post: 02-27-2006, 03:11 AM

Tags for this Thread