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. Why can't I initialize ("initializer element is not constant") a struct with a truncated function pointer?

Why can't I initialize ("initializer element is not constant") a struct with a truncated function pointer?

Scheduled Pinned Locked Moved C / C++ / MFC
adobetoolshelptutorialquestion
8 Posts 4 Posters 11 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.
  • A Offline
    A Offline
    arnold_w
    wrote on last edited by
    #1

    I need to save space and reduce some of my function pointers from 32-bit to 16-bit and this is ok since the flash region I've specified in the linker script is only 32 kBytes. Does anybody know how I can make my 3rd example below compile properly?

    typedef struct {
    uint16_t myFunctPtrTruncated;
    } myUint16struct_s;

    typedef struct {
    void* myFunctPtr;
    } myVoidstruct_s;

    static void myDummyFunc() {}

    myVoidstruct_s myStruct1 = { myDummyFunc }; // Ok
    myUint16struct_s myStruct2 = { 0 }; // Ok
    myUint16struct_s myStruct3 = { (uint16_t)(uint32_t)myDummyFunc }; // Error: "initializer element is not constant"

    L CPalliniC L 3 Replies Last reply
    0
    • A arnold_w

      I need to save space and reduce some of my function pointers from 32-bit to 16-bit and this is ok since the flash region I've specified in the linker script is only 32 kBytes. Does anybody know how I can make my 3rd example below compile properly?

      typedef struct {
      uint16_t myFunctPtrTruncated;
      } myUint16struct_s;

      typedef struct {
      void* myFunctPtr;
      } myVoidstruct_s;

      static void myDummyFunc() {}

      myVoidstruct_s myStruct1 = { myDummyFunc }; // Ok
      myUint16struct_s myStruct2 = { 0 }; // Ok
      myUint16struct_s myStruct3 = { (uint16_t)(uint32_t)myDummyFunc }; // Error: "initializer element is not constant"

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

      I just tried this with Microsoft's Visual C++ compiler and it compiles cleanly.

      A 1 Reply Last reply
      0
      • L Lost User

        I just tried this with Microsoft's Visual C++ compiler and it compiles cleanly.

        A Offline
        A Offline
        arnold_w
        wrote on last edited by
        #3

        I am using System Workbench (=gcc?) and I get error (not warning) message "initializer element is not constant".

        L 1 Reply Last reply
        0
        • A arnold_w

          I need to save space and reduce some of my function pointers from 32-bit to 16-bit and this is ok since the flash region I've specified in the linker script is only 32 kBytes. Does anybody know how I can make my 3rd example below compile properly?

          typedef struct {
          uint16_t myFunctPtrTruncated;
          } myUint16struct_s;

          typedef struct {
          void* myFunctPtr;
          } myVoidstruct_s;

          static void myDummyFunc() {}

          myVoidstruct_s myStruct1 = { myDummyFunc }; // Ok
          myUint16struct_s myStruct2 = { 0 }; // Ok
          myUint16struct_s myStruct3 = { (uint16_t)(uint32_t)myDummyFunc }; // Error: "initializer element is not constant"

          CPalliniC Offline
          CPalliniC Offline
          CPallini
          wrote on last edited by
          #4

          Are you sure you are using the right tools for (cross?) compilation? The compiler should be aware of the target addressing modes and adjust the pointers size accordingly.

          In testa che avete, signor di Ceprano?

          1 Reply Last reply
          0
          • A arnold_w

            I am using System Workbench (=gcc?) and I get error (not warning) message "initializer element is not constant".

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

            arnold_w wrote:

            I am using System Workbench (=gcc?)

            A pity you did not mention that in your original message.

            1 Reply Last reply
            0
            • A arnold_w

              I need to save space and reduce some of my function pointers from 32-bit to 16-bit and this is ok since the flash region I've specified in the linker script is only 32 kBytes. Does anybody know how I can make my 3rd example below compile properly?

              typedef struct {
              uint16_t myFunctPtrTruncated;
              } myUint16struct_s;

              typedef struct {
              void* myFunctPtr;
              } myVoidstruct_s;

              static void myDummyFunc() {}

              myVoidstruct_s myStruct1 = { myDummyFunc }; // Ok
              myUint16struct_s myStruct2 = { 0 }; // Ok
              myUint16struct_s myStruct3 = { (uint16_t)(uint32_t)myDummyFunc }; // Error: "initializer element is not constant"

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

              Your statement 3 as written will only compile in C++ it isn't valid C code. Which is why the person who tried it on VC++ it worked. In C "myDummyFunc" can not be typecast to an address like in C++, in C "&myDummyFunc" is the pointer address that needs typecasting Remember what that pesky "&" character means in C The first case you list was defined as valid in C99, but your 3rd case is junk and correctly rejected So try proper C code using the "&" so it understands what you are trying to do

              myUint16struct\_s myStruct3 = { (uint16\_t)(uint32\_t)&myDummyFunc };
              

              Now if you want to do it properly so its portable the correct way is to use uintptr_t for the translation and C99 dot format This allows you move the pointer anywhere within the struct and it sets correctly

              myUint16struct_s myStruct4 = { .myFunctPtrTruncated = (uint16_t)(uintptr_t)&myDummyFunc };

              In C99, uintptr_t will put some safety around your code because it is defined as

              an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer

              In vino veritas

              A 1 Reply Last reply
              0
              • L leon de boer

                Your statement 3 as written will only compile in C++ it isn't valid C code. Which is why the person who tried it on VC++ it worked. In C "myDummyFunc" can not be typecast to an address like in C++, in C "&myDummyFunc" is the pointer address that needs typecasting Remember what that pesky "&" character means in C The first case you list was defined as valid in C99, but your 3rd case is junk and correctly rejected So try proper C code using the "&" so it understands what you are trying to do

                myUint16struct\_s myStruct3 = { (uint16\_t)(uint32\_t)&myDummyFunc };
                

                Now if you want to do it properly so its portable the correct way is to use uintptr_t for the translation and C99 dot format This allows you move the pointer anywhere within the struct and it sets correctly

                myUint16struct_s myStruct4 = { .myFunctPtrTruncated = (uint16_t)(uintptr_t)&myDummyFunc };

                In C99, uintptr_t will put some safety around your code because it is defined as

                an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer

                In vino veritas

                A Offline
                A Offline
                arnold_w
                wrote on last edited by
                #7

                I still get the same error message.

                L 1 Reply Last reply
                0
                • A arnold_w

                  I still get the same error message.

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

                  Set the compiler flags -std=c11 or -std=c99 either standard will accept the code The portable case has to work or you are on an old C89 compiler which I find odd given it accepts the shortcut syntax in 1 The only other choice is you are on something like a PIC where you have to use builtins to get function addresses because of the crazy 32K block arrangements on memory

                  In vino veritas

                  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