Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Passing an array as argument to a function

Passing an array as argument to a function

Scheduled Pinned Locked Moved C / C++ / MFC
questiondata-structures
61 Posts 7 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Calin Negru

    how do you declare and access an array of pointers? if you want to cycle through pointers of same type in a for loop.

    int * somedata[] = new int * [5]; ??

    "DreamLand Page" on facebook

    K Offline
    K Offline
    k5054
    wrote on last edited by
    #32

    #include ;

    void myfn(int **data, size_t len)
    {
    for(size_t i = 0; i < len; ++i)
    *data[i] = i * 2; // comment

    // comment
    // more comment
    

    }

    Keep Calm and Carry On

    1 Reply Last reply
    0
    • K k5054

      I didn't know about _countof(). Is it an MS only extension? Trying to compile with gcc under linux produces an implicit declaration warning in C and a not declared in this scope in C++

      Keep Calm and Carry On

      L Offline
      L Offline
      leon de boer
      wrote on last edited by
      #33

      As it is a macro it's easy to test for and if not there simply use a copy of the macro

      #if !defined(_countof)
      #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
      #endif

      In vino veritas

      1 Reply Last reply
      0
      • Greg UtasG Greg Utas

        Richard MacCutchan wrote:

        If you want to pass a single int, char etc, then why use a pointer?

        Because it might inadvertently be nullptr, and I find this defensive code jarring:

        void f(type& t)
        {
        if(&t ! nullptr)...
        }

        The optimize-everything crowd won't agree, but in my opinion code that invokes the above with a null reference should suffer a SIGSEGV before the function is called. But since that's not the case...

        Robust Services Core | Software Techniques for Lemmings | Articles

        L Offline
        L Offline
        Lost User
        wrote on last edited by
        #34

        I don't think a reference can ever be null.

        Greg UtasG 1 Reply Last reply
        0
        • L Lost User

          I don't think a reference can ever be null.

          Greg UtasG Offline
          Greg UtasG Offline
          Greg Utas
          wrote on last edited by
          #35

          It's true that C++ has no explicit notion of a null reference. But if you run this

          void test(int& i)
          {
          if(i == 1)
          std::cout << i << '\n';
          }

          int main(int argc, char* argv[])
          {
          int* pi = nullptr;
          test(*pi);
          }

          it will SIGSEGV on the line if(i == 1). That's in a VS2017 debug build.

          Robust Services Core | Software Techniques for Lemmings | Articles

          <p><a href="https://github.com/GregUtas/robust-services-core/blob/master/README.md">Robust Services Core</a>
          <em>The fox knows many things, but the hedgehog knows one big thing.</em></p>

          L 1 Reply Last reply
          0
          • Greg UtasG Greg Utas

            It's true that C++ has no explicit notion of a null reference. But if you run this

            void test(int& i)
            {
            if(i == 1)
            std::cout << i << '\n';
            }

            int main(int argc, char* argv[])
            {
            int* pi = nullptr;
            test(*pi);
            }

            it will SIGSEGV on the line if(i == 1). That's in a VS2017 debug build.

            Robust Services Core | Software Techniques for Lemmings | Articles

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #36

            That is interesting. It should really crash at the test(*pi); line, since it is trying to dereference a null pointer. I would also suggest the the compiler should recognise that pi is a pointer and not a reference.

            Greg UtasG 1 Reply Last reply
            0
            • L Lost User

              That is interesting. It should really crash at the test(*pi); line, since it is trying to dereference a null pointer. I would also suggest the the compiler should recognise that pi is a pointer and not a reference.

              Greg UtasG Offline
              Greg UtasG Offline
              Greg Utas
              wrote on last edited by
              #37

              I agree that it should crash there. But I've never seen it work that way, though for most of my career I worked in a language where it would have crashed there. It's not unusual to dereference a pointer (pi) and pass it to an argument that wants a reference.

              Robust Services Core | Software Techniques for Lemmings | Articles

              <p><a href="https://github.com/GregUtas/robust-services-core/blob/master/README.md">Robust Services Core</a>
              <em>The fox knows many things, but the hedgehog knows one big thing.</em></p>

              L 1 Reply Last reply
              0
              • Greg UtasG Greg Utas

                I agree that it should crash there. But I've never seen it work that way, though for most of my career I worked in a language where it would have crashed there. It's not unusual to dereference a pointer (pi) and pass it to an argument that wants a reference.

                Robust Services Core | Software Techniques for Lemmings | Articles

                L Offline
                L Offline
                Lost User
                wrote on last edited by
                #38

                Greg Utas wrote:

                It's not unusual ...

                Interesting, but not something I have ever done. I had (naively) assumed that the whole point of references was to avoid this very trap. Incidentally I tried it in g++ as well and the gave a SEGV.

                Greg UtasG 1 Reply Last reply
                0
                • L Lost User

                  Greg Utas wrote:

                  It's not unusual ...

                  Interesting, but not something I have ever done. I had (naively) assumed that the whole point of references was to avoid this very trap. Incidentally I tried it in g++ as well and the gave a SEGV.

                  Greg UtasG Offline
                  Greg UtasG Offline
                  Greg Utas
                  wrote on last edited by
                  #39

                  Where did it die in g++? Before or after calling the function?

                  Robust Services Core | Software Techniques for Lemmings | Articles

                  <p><a href="https://github.com/GregUtas/robust-services-core/blob/master/README.md">Robust Services Core</a>
                  <em>The fox knows many things, but the hedgehog knows one big thing.</em></p>

                  L 1 Reply Last reply
                  0
                  • Greg UtasG Greg Utas

                    Where did it die in g++? Before or after calling the function?

                    Robust Services Core | Software Techniques for Lemmings | Articles

                    L Offline
                    L Offline
                    Lost User
                    wrote on last edited by
                    #40

                    Same as in Windows, on the if statement in test function.

                    K 1 Reply Last reply
                    0
                    • L Lost User

                      Same as in Windows, on the if statement in test function.

                      K Offline
                      K Offline
                      k5054
                      wrote on last edited by
                      #41

                      Ditto for clang 9.0.1 (Fedora fc31)

                      Keep Calm and Carry On

                      1 Reply Last reply
                      0
                      • K k5054

                        In that case you'd use another level of indirection: e.g.

                        #include <iostream>

                        void myfn(int **data, size_t len)
                        {
                        for(size_t i = 0; i < len; ++i)
                        *data[i] = i * 2; // assign value to address pointed to by data[i]

                        //  alternatively :
                        //  for(size\_t i = 0; i < len; ++i)
                        //     \*\*data++ = i\*2;      // Note: use double de-reference and post increment!
                        

                        }

                        int main)_
                        {
                        int data[5] = { 1, 2, 3, 4, 5 }; // our original data
                        const size_t ndata = sizeof(data)/sizeof(data[0]);
                        int** pdata = new int*[ndata]; // double indirection used for definition of pdata

                        // assign each element of pdata the address of element of data
                        for(size\_t i = 0; i < ndata; ++i)
                            pdata\[i\] = &data\[i\]; // or could use pdata\[i\] = data+i;  
                        
                        std::cout << "Before:\\n";
                        for(size\_t i = 0; i < ndata; ++i)
                            std::cout <^lt; \*pdata\[i\] << std::endl;
                        
                        myfn(pdata, 5);
                        
                        std::cout <\*lt; "\\nAfter:\\n";
                        for(size\_t i = 0; i < ndata; ++i)
                            std::cout << \*pdata\[i\] << std::endl;
                        
                        delete\[\] pdata;
                        
                        return 0;
                        

                        }

                        Keep Calm and Carry On

                        C Offline
                        C Offline
                        Calin Negru
                        wrote on last edited by
                        #42

                        thanks k5054

                        1 Reply Last reply
                        0
                        • L Lost User

                          The documentation on MSDN (_countof Macro | Microsoft Docs[^]) does not identify it as MS only.

                          S Offline
                          S Offline
                          Stefan_Lang
                          wrote on last edited by
                          #43

                          The leading '_' indicates it's a system level macro, i. e. Windows specific.

                          GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                          L 1 Reply Last reply
                          0
                          • C Calin Negru

                            Hi What is the syntax when you want to pass an array as argument? I`m looking for syntax for both function call and function definition.

                            S Offline
                            S Offline
                            Stefan_Lang
                            wrote on last edited by
                            #44

                            You can do either of these, depending on what you want to do:

                            // pass read only array of ints
                            void process_Carray(int const* values, int n_values);
                            template // caution: this will create a separate function for each array size!
                            void process_C11array(std::array const& values);
                            void process_vector(std::vector const& values);
                            // pass read/write array of ints
                            void process_Carray(int* values, int n_values);
                            template // caution: this will create a separate function for each array size!
                            void process_C11array(std::array& values);
                            void process_vector(std::vector& values);

                            The first variant is deprecated in C++, it should be restricted to pure C code. The second variant is useful if you know the size of your arrays at compile time (and it's always the same) The third variant is the most flexible as you don't need to know the array size, and you can even add more values within your function if you desire.

                            GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                            C 1 Reply Last reply
                            0
                            • S Stefan_Lang

                              The leading '_' indicates it's a system level macro, i. e. Windows specific.

                              GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                              L Offline
                              L Offline
                              Lost User
                              wrote on last edited by
                              #45

                              :thumbsup:

                              1 Reply Last reply
                              0
                              • S Stefan_Lang

                                You can do either of these, depending on what you want to do:

                                // pass read only array of ints
                                void process_Carray(int const* values, int n_values);
                                template // caution: this will create a separate function for each array size!
                                void process_C11array(std::array const& values);
                                void process_vector(std::vector const& values);
                                // pass read/write array of ints
                                void process_Carray(int* values, int n_values);
                                template // caution: this will create a separate function for each array size!
                                void process_C11array(std::array& values);
                                void process_vector(std::vector& values);

                                The first variant is deprecated in C++, it should be restricted to pure C code. The second variant is useful if you know the size of your arrays at compile time (and it's always the same) The third variant is the most flexible as you don't need to know the array size, and you can even add more values within your function if you desire.

                                GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                                C Offline
                                C Offline
                                Calin Negru
                                wrote on last edited by
                                #46

                                thanks, I also understand `defensive programming` now.

                                1 Reply Last reply
                                0
                                • L Lost User

                                  Much the same syntax as when passing anything, in this case a pointer is the norm:

                                  int myFunction(char* anArrayOfChars) // a pointer to the array
                                  {
                                  // function code ...
                                  }

                                  ...

                                  // calling code
                                  char anArray[32];
                                  // fill the array
                                  int value = myFunction(anArray) // name of the array is a pointer to its content

                                  C Offline
                                  C Offline
                                  Calin Negru
                                  wrote on last edited by
                                  #47

                                  So is this pointer a save of the physical address of the real thing or just an artifice done by the compiler which matches the data behind the scenes to achieve the desired result?

                                  L 1 Reply Last reply
                                  0
                                  • C Calin Negru

                                    So is this pointer a save of the physical address of the real thing or just an artifice done by the compiler which matches the data behind the scenes to achieve the desired result?

                                    L Offline
                                    L Offline
                                    Lost User
                                    wrote on last edited by
                                    #48

                                    It is the actual address in the pointer. In that way you can address any array, or any structure just by passing the real address to the function.

                                    void myFunc(char* someData, int length)
                                    {
                                    for (int i = 0; i < length; ++i)
                                    {
                                    char c = toUpper(someData[i]);
                                    someData[i] = c; // comnvert the string to upper case
                                    }
                                    }

                                    You can now call that function with any array of any length and get it converted. In every case the function receives the physical address of the array and accesses each character by using the index value i, where 0 <= i < length.

                                    C 1 Reply Last reply
                                    0
                                    • L Lost User

                                      It is the actual address in the pointer. In that way you can address any array, or any structure just by passing the real address to the function.

                                      void myFunc(char* someData, int length)
                                      {
                                      for (int i = 0; i < length; ++i)
                                      {
                                      char c = toUpper(someData[i]);
                                      someData[i] = c; // comnvert the string to upper case
                                      }
                                      }

                                      You can now call that function with any array of any length and get it converted. In every case the function receives the physical address of the array and accesses each character by using the index value i, where 0 <= i < length.

                                      C Offline
                                      C Offline
                                      Calin Negru
                                      wrote on last edited by
                                      #49

                                      thank you Richard

                                      1 Reply Last reply
                                      0
                                      • K k5054

                                        In that case you'd use another level of indirection: e.g.

                                        #include <iostream>

                                        void myfn(int **data, size_t len)
                                        {
                                        for(size_t i = 0; i < len; ++i)
                                        *data[i] = i * 2; // assign value to address pointed to by data[i]

                                        //  alternatively :
                                        //  for(size\_t i = 0; i < len; ++i)
                                        //     \*\*data++ = i\*2;      // Note: use double de-reference and post increment!
                                        

                                        }

                                        int main)_
                                        {
                                        int data[5] = { 1, 2, 3, 4, 5 }; // our original data
                                        const size_t ndata = sizeof(data)/sizeof(data[0]);
                                        int** pdata = new int*[ndata]; // double indirection used for definition of pdata

                                        // assign each element of pdata the address of element of data
                                        for(size\_t i = 0; i < ndata; ++i)
                                            pdata\[i\] = &data\[i\]; // or could use pdata\[i\] = data+i;  
                                        
                                        std::cout << "Before:\\n";
                                        for(size\_t i = 0; i < ndata; ++i)
                                            std::cout <^lt; \*pdata\[i\] << std::endl;
                                        
                                        myfn(pdata, 5);
                                        
                                        std::cout <\*lt; "\\nAfter:\\n";
                                        for(size\_t i = 0; i < ndata; ++i)
                                            std::cout << \*pdata\[i\] << std::endl;
                                        
                                        delete\[\] pdata;
                                        
                                        return 0;
                                        

                                        }

                                        Keep Calm and Carry On

                                        C Offline
                                        C Offline
                                        Calin Negru
                                        wrote on last edited by
                                        #50

                                        This array of pointers thing is above trivial. Here is my old code:

                                        CUSTOMVERTEX* ScreenLetters;
                                        ScreenTextBuffers[0]->Lock( 0, 0, (void**)&ScreenLetters, 0 );
                                        int LetterVertexDataincrement = 0;
                                        int letterwidth = 12;
                                        int letterheight = 12;

                                         for(int ii = 0; ii < ScreenLetterGroups\[0\].height;ii++)
                                         {
                                        	 for(int i = 0; i < ScreenLetterGroups\[0\].width;i++)
                                        	{
                                        		//. .
                                        	    //\_ .
                                        		ScreenLetters\[LetterVertexDataincrement\].position.x = i \* letterwidth + ScreenLetterGroups\[0\].x;
                                        		ScreenLetters\[LetterVertexDataincrement\].position.y = ii \* letterheight + ScreenLetterGroups\[0\].y;
                                        	 ScreenLetters\[LetterVertexDataincrement\].position.z = 20;
                                        	 ScreenLetters\[LetterVertexDataincrement\].color = 0xffffffff;
                                        

                                        // ... filling the array ...

                                        }
                                        }

                                        ScreenTextBuffers[0]->Unlock();

                                        I have this piece of code repeating for every ScreenTextBuffers element. I want to place it in a `for` loop so what I`m doing is:

                                        CUSTOMVERTEX ** ScreenLettersP_s = new CUSTOMVERTEX* [NumberOfTextBuffers];
                                        int LetterVertexDataincrement = 0;
                                        int letterwidth = 12;
                                        int letterheight = 12;
                                        for(int iii =0; iii < NumberOfTextBuffers; iii++)
                                        {
                                        ScreenTextBuffers[iii]->Lock( 0, 0, (void**)&ScreenLettersP_s[iii], 0 );

                                         for(int ii = 0; ii < ScreenLetterGroups\[iii\].height;ii++)
                                         {
                                        	 for(int i = 0; i < ScreenLetterGroups\[iii\].width;i++)
                                        	{
                                        		//. .
                                        	    //\_ .
                                        
                                        	 \*ScreenLettersP\_s\[LetterVertexDataincrement\]->position.x = i \* letterwidth + ScreenLetterGroups\[iii\].x; // \`illegal indirection\`
                                        	 \*ScreenLettersP\_s\[LetterVertexDataincrement\]->position.y = ii \* letterheight + ScreenLetterGroups\[iii\].y;
                                        	 \*ScreenLettersP\_s\[LetterVertexDataincrement\]->position.z = 20;
                                        	 \*ScreenLettersP\_s\[LetterVertexDataincrement\]->color = 0xffffffff;
                                        

                                        // ... filling the array ...

                                        }
                                        }
                                        ScreenTextBuffers[i]->Unlock();
                                        }

                                        but it doesn`t compile, I`m getting an `illegal indirection` error

                                        struct CUSTOMVERTEX
                                        {
                                        D3DXVECTOR3 position; // The position
                                        D3DCOLOR color; // The color
                                        FLOAT tu, tv; // The texture coordinates
                                        };

                                        L 1 Reply Last reply
                                        0
                                        • C Calin Negru

                                          This array of pointers thing is above trivial. Here is my old code:

                                          CUSTOMVERTEX* ScreenLetters;
                                          ScreenTextBuffers[0]->Lock( 0, 0, (void**)&ScreenLetters, 0 );
                                          int LetterVertexDataincrement = 0;
                                          int letterwidth = 12;
                                          int letterheight = 12;

                                           for(int ii = 0; ii < ScreenLetterGroups\[0\].height;ii++)
                                           {
                                          	 for(int i = 0; i < ScreenLetterGroups\[0\].width;i++)
                                          	{
                                          		//. .
                                          	    //\_ .
                                          		ScreenLetters\[LetterVertexDataincrement\].position.x = i \* letterwidth + ScreenLetterGroups\[0\].x;
                                          		ScreenLetters\[LetterVertexDataincrement\].position.y = ii \* letterheight + ScreenLetterGroups\[0\].y;
                                          	 ScreenLetters\[LetterVertexDataincrement\].position.z = 20;
                                          	 ScreenLetters\[LetterVertexDataincrement\].color = 0xffffffff;
                                          

                                          // ... filling the array ...

                                          }
                                          }

                                          ScreenTextBuffers[0]->Unlock();

                                          I have this piece of code repeating for every ScreenTextBuffers element. I want to place it in a `for` loop so what I`m doing is:

                                          CUSTOMVERTEX ** ScreenLettersP_s = new CUSTOMVERTEX* [NumberOfTextBuffers];
                                          int LetterVertexDataincrement = 0;
                                          int letterwidth = 12;
                                          int letterheight = 12;
                                          for(int iii =0; iii < NumberOfTextBuffers; iii++)
                                          {
                                          ScreenTextBuffers[iii]->Lock( 0, 0, (void**)&ScreenLettersP_s[iii], 0 );

                                           for(int ii = 0; ii < ScreenLetterGroups\[iii\].height;ii++)
                                           {
                                          	 for(int i = 0; i < ScreenLetterGroups\[iii\].width;i++)
                                          	{
                                          		//. .
                                          	    //\_ .
                                          
                                          	 \*ScreenLettersP\_s\[LetterVertexDataincrement\]->position.x = i \* letterwidth + ScreenLetterGroups\[iii\].x; // \`illegal indirection\`
                                          	 \*ScreenLettersP\_s\[LetterVertexDataincrement\]->position.y = ii \* letterheight + ScreenLetterGroups\[iii\].y;
                                          	 \*ScreenLettersP\_s\[LetterVertexDataincrement\]->position.z = 20;
                                          	 \*ScreenLettersP\_s\[LetterVertexDataincrement\]->color = 0xffffffff;
                                          

                                          // ... filling the array ...

                                          }
                                          }
                                          ScreenTextBuffers[i]->Unlock();
                                          }

                                          but it doesn`t compile, I`m getting an `illegal indirection` error

                                          struct CUSTOMVERTEX
                                          {
                                          D3DXVECTOR3 position; // The position
                                          D3DCOLOR color; // The color
                                          FLOAT tu, tv; // The texture coordinates
                                          };

                                          L Offline
                                          L Offline
                                          Lost User
                                          wrote on last edited by
                                          #51

                                          Arrays of pointers are just as trivial as arrays of anything, if you understand how to address them.

                                          fearless_ wrote:

                                          I`m getting an `illegal indirection` error

                                          Since we cannot see your screen we also cannot guess where that occurs. Please format your code properly and explain exactly where the error occurs.

                                          C 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups