This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

C2000: argument of type "volatile void *" is incompatible with parameter of type "void *"

Guru 19935 points

I am using C2000 compiler version 6.2.11.  

The compiler is generating the above error for memset()

 The issue I am having is similar .

However, for that issue I was able to change the data type the table accepted.

For the current issue I am not able to do that.  Also, casting the pointer to (void *) doesn't work.

Does anyone have a solution for this problem?

Note: I could store the pointer into a another void * variable and use that variable in the memset, however, I was wanting to know if there was another way to solve the problem.

Stephen

  • I forgot to mention I am using the c++ compiler.

  • stevenh said:
    Also, casting the pointer to (void *) doesn't work.

    I'm surprised to hear that.  Why doesn't it work?  Do you get a different compiler error?

    Are you trying to zero-initialize this object?  Is it a static object?

  • For some reason it now works.

    An example of what generated an error is as follows:

    memset(&myStruct1,0,sizeof(struct))

    where myStruct1 is volatile, i.e.

    volatile MYSTRUCT myStruct1;  

    and MYSTRUCT is a simple structure typef, i.e.

    typedef struct
    {
        int a;
        int b;
        int c;
    } MYSTRUCT;

    casting the point to a volatile struct type to a (void*) (i.e. memset((void*&myStruct1,0,sizeof(struct))) got rid of the error.

    previously that wasn't working for some reason.

  • I just posted a comment and its not showing up.

    Anyway, for some reason, the (void*) cast is working now and I not sure why, i.e.

    memset((void*)&mystruct1,0,sizeof(mystruct));

  • Strictly speaking, you should not call memset with a pointer to volatile data.  You might presume that memset initializes memory one word at a time, working from the low address to the high address.  And that probably is how it really works.  But it doesn't have to.  It could work from the high address to the low.  Or, it can do the even addresses, then the odd ones.  Or it can write multiple words at a time.  Moreover, this can change between compiler releases.  Depending on what side effects occur when this memory is written, some of these scenarios can be a big problem.

    After you consider all those unlikely possibilities, you could decide that it is still OK to use memset.  In that case, I suggest disabling the diagnostic.  You can do this with a command line option or a #pragma.  Please see the Compiler Diagnostics slides in the tips & tricks presentation on this wiki page.

    Thanks and regards,

    -George

  • Thanks George.

    I was wondering if there could be any issues. That helps a lot and gives me a better understanding of the situation.  

    Since I am setting the values to 0, I don't think the scenarios you described will be an issue. Do you agree?  

    What do you mean "Depending on what side effects occur when this memory is written"?

  • If it's truly a volatile object, it might represent (for instance) a memory-mapped peripheral, and modifying (or even reading) memory within the object could trigger something to happen in the peripheral, or change the values in the memory. If it's just plain old memory, you're probably fine. For such a small object, you might consider making it a class and letting the compiler zero-initialize it for you. I wouldn't expect you to need to use memset unless you need to re-use a particular object's memory.
  • "you might consider making it a class and letting the compiler zero-initialize it for you"

    Do you have a simple example.  The following doesn't seem to work:

    typedef struct
    {
        int a;
        int b;
        int c;
        int d;
    } TESTSTRUCT1;
    
    typedef struct
    {
        int x:1;
        int y:1;
        int z:1;
    }TESTSTRUCT2;
    
    class Test
    {
        public:
        static volatile TESTSTRUCT1 testStruct1;
        static volatile TESTSTRUCT2 testStruct2;
    };
    
    volatile TESTSTRUCT2 Test::testStruct2 = {2};
    volatile TESTSTRUCT1 Test::testStruct1 = {2};
    
    Test Test1;
    
    int main(void) {
    	
    	return 0;
    }

    Also, how would reading memory memory within the object trigger something to happen?

  • Sorry, I forgot you were using C2000, which doesn't support EABI. In COFF, the compiler doesn't initialize those extra members as the standard expects.
    BTW, your initializer for Test::teststruct2 won't fit in that 1-bit bit-field.
    Consider an input peripheral that queued the input one word at a time at a particular memory address. When you read the contents, the peripheral replaces the contents with the next word of input. The behavior of a memory-mapped peripheral can be whatever the hardware designer dreamed up.
  • Thanks for the info on the difference between EABI and COFF.