From the wiki article:
Type and length are fixed in size (usually 1-4 bytes)
So, I would change nTag and nLength to some type of fixed length. int size is platform dependent and this may cause some problems. Correct their sizes for your protocol and use int8_t , int16_t or int32_t etc. For nLength you can even use unsigned.
Since the value can be any type, I would use void* for pValue instead of unsigned char* .
How will you use this data structure? How do you want to access different TLVs?
My point is - do you need a linked list? Or, a linked list would be the best option for your business / application / goals / etc?
I'm trying to say that you can remove the pNext element and just treat the TLV as elements of a (dynamically growing) array. It really depends on your needs.
Most likely, when implementing TLVs, you will need to send them through some kind of connection, right? If so, you need to think about some kind of protocol. I would do something like this - send the total number of TLVs at the very beginning, and I would NOT use a linked list, but a dynamic array.
You must be careful when sending such a data structure over the network - pNext pointers pNext not be valid, they must be reset on the other side of the connection.
You also need to send data carefully, but I think you know that. I just wanted to mention them.
EDIT I see that you have some problems that understand what a nested TLV means.
A nested TLV is just a TLV element that has a TLV type value. And this has nothing to do with the TLV “container” - a dynamic array or linked list.
Here's an untested example to get this idea. I would do it like this:
struct TLV { uint32_t nTag; uint32_t nLength; void* pValue; };
NOTE: once again, this is not verified code, but I think you get the point. Hope this helps.