Why pass char pointer address rather than char array address

For this API, BaseType_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);

pvItemToQueue A pointer to the item that is to be placed on the queue. The size of the items the queue will hold was defined when the queue was created, so this many bytes will be copied from pvItemToQueue into the queue storage area.

I want to pass char array as parameter to pvItemToQueue argument.

char menu[]={"This is String"};

Case - 1:

xQueueSend(uart_write_queue,menu,portMAX_DELAY);

as menu will give starting address of array.

Case - 2:

char *pData = menu;
xQueueSend(uart_write_queue,&pData,portMAX_DELAY);

Second case is correct. But Can someone explain difference between two and why Case - 1 is wrong?

In the first case, it is the type checking in the compiler that fails on the second argument.

In the second case you explicitly create a pointer (using &), which is needed since the second parameter is of type void *.

The first case would probably compile if you add change “menu” to “&menu”.

char menu={“This is String”};

xQueueSend(uart_write_queue,menu,portMAX_DELAY);

How did you create the queue? It looks like you want the pass a pointer to a string to the queue, so that would ask for:

    #define QUEUE_LENGTH    20
    uart_write_queue = xQueueCreate( QUEUE_LENGTH, sizeof( char * ) );

xQueueSend() expects a pointer and it will send the pointee (what is pointed to). In your example, the 4 letters “This” will be sent to the queue.

as menu will give starting address of array.

char *pData = menu;
xQueueSend(uart_write_queue,&pData,portMAX_DELAY);

Second case is correct. But Can someone explain difference between two and why Case - 1 is wrong?

Now the pointee is the address of the string, which is what you probably want. A pointer will be stored.

As @johankraft suggests, you can also pass a pointer to menu[]:

    xQueueSend( uart_write_queue, ( void * ) &( menu ), portMAX_DELAY);

About this declaration:

char menu[] = { "This is String" };

Although this looks like an example, there is some risk: if this variable is declared on the stack, the RAM space may have been re-used by the time xQueueReceive() is called, thus altering the string.
Tip: you can use a second queue to return free buffers to the driver.

The first call has as its parameter the name of an array, which will decay into a pointer to the first element of that array, so the parameter is a pointer to the string “This is a String”, which (if I am counting correctly) is an object of 16 bytes, so the Queue should have been called with an item size of 16 bytes.

The second call, the parameter is a pointer to pData, which itself is a pointer to String. The size of the pointer is probably 2 or 4 bytes long, so the queue should have been created with that size (probably best to have been done with something like sizeof (char*)

The first puts the characters themselves into the queue, the second put the address of the characters into the queue. The later takes less space in the queue, but the sending program shouldn’t change the array contents until the receiver is done with the data. For the first case, the receiver should pass an array to put the data into, for the second, the address of a pointer that will be set to point to the buffer.
If the second is right, then the first can be made to work like it by setting a variable to point to the buffer and passing the address of that pointer to the queue. Something like:

char menu[] = …
char *menup = menu;

xQueueSend(uart_write_queue, &menup, portMAX_DELAY);