0

ok,i know very little on C from university course, so i hope you will understand my question. im using FFmpeg library for android so i just need to understand somethings in their C code.

so, i have this struct:

typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8
    /**
     * pointer to the picture/channel planes.

     */
    uint8_t *data[AV_NUM_DATA_POINTERS];

  .......(some more types)
}

thats all, but when i look at the function in other file-i see the next line,and getting confuse,

outside the function:

static AVFrame  *picture_hq;

and inside the function:

picture_hq->data[0][y * picture_hq->linesize[0] + x] = native_video_frame_data[0];

Don't pay attention to the unknown arguments, i just don't understand how 1 dimension array data[] from the struct above,become a 2 dimensions array data[0][bla bla bla..]?

is it related to the uint8_t type?

yarin
  • 543
  • 1
  • 5
  • 18
  • 4
    It’s an array of pointers to `uint8_t`. So it’s like `*(picture_hq->data[0] + y * picture_hq->linesize[0] + x) = native_video_frame_data[0];`. – Ry- Oct 22 '13 at 02:26
  • now i confused more, as i understand, the next expression `(picture_hq->data[0] + y * picture_hq->linesize[0] + x)` is a number , so `*(picture_hq->data[0] + y * picture_hq->linesize[0] + x)` is apointer to number? i have to learn C . – yarin Oct 22 '13 at 02:54
  • The relationship between arrays and pointers in C is often confusing -- and you'll find a lot of misinformation about it. Section 6 of the [comp.lang.c FAQ](http://www.c-faq.com/) explains it very well. – Keith Thompson Oct 22 '13 at 06:52

2 Answers2

0

The data array is not an array of 8 uint_8 but rather an array of 8 pointers to uint_8. Note the asterik before the data. - The type is uint8_t* - that is pointer to uint8_t.

uint8_t *data[AV_NUM_DATA_POINTERS];

In C, an array is similar to a pointer, so if you have a pointer to uint8_t, you can access the addresses it points to, and subsequent addresses, as an array.

You do need to have this allocated properly or you will either get a segmentation fault, or some data you don't expect - but this is probably handled properly by your library.

C also uses special arithmetic for pointers (pointer arithmetic) - so the type of pointer determines the "spacing" between elements - so if you have a pointer to a uint8_t, array elements will be handled with each element being 1 byte from the previous. If the type is uint32_t, then each element would be 4 bytes from the previous element - to accomodate the larger type.

You can find more info on C arrays and pointer arithmetic here:

C arrays and pointer arithmetic

So since data[] is an array of pointers to uint8_t, then data[0] is a pointer to uint8_t. Since you can treat this pointer as the start of an array of uint8_t then

picture_hq->data[0][y * picture_hq->linesize[0] + x] = native_video_frame_data[0];

access the (y * picture_hq->linesize[0] + x) offset from the address pointed to by data[0], and treats it as a uint8_t.

Avi Perel
  • 422
  • 3
  • 8
  • 1
    "*In C, an array is similar to a pointer*" -- No, it really isn't. And your [linked article](http://www-ee.eng.hawaii.edu/~tep/EE160/Book/chap7/section2.1.3.html) is badly misleading; for example, declaring an array object *does not* allocate a pointer object. Read section 6 of the [comp.lang.c FAQ](http://www.c-faq.com); it explains this stuff clearly *and correctly*. – Keith Thompson Oct 22 '13 at 06:51
  • @Keith Thompson - respectfully, I was not saying that declaring an array allocates a pointer, and also specifically noted that declaring a pointer does not allocates an array - it is the programmers responsibilty to do this (3rd paragraph). – Avi Perel Oct 22 '13 at 06:59
  • 1
    The article you linked to says "Thus, the declaration of an array causes the compiler to allocate the specified number of contiguous cells of the indicated type, as well as to allocate an appropriate pointer cell, initialized to point to the first cell of the array." That was actually true in C as it existed about 40 years ago, but it's simply wrong now. And my main quibble is with your statement that "an array is similar to a pointer". An array is a contiguous sequence of elements; a pointer contains a memory address. They are not similar. – Keith Thompson Oct 22 '13 at 07:04
0

The way to read the declaration is this:

uint8_t *data[AV_NUM_DATA_POINTERS];
        ^   ^                    ^
        |   |                    |
        |  1. the identifier...  |
        |                        |
        |           2. ... is an array...
        |
  3. ...of pointers.

The important thing about this is that the array subscript operator [] has a higher precedence than the dereference operator *. Consequently, when the compiler sees

data[1][2]

it will do the following:

  1. It looks up the symbol data. This has an array type uint8_t *()[]

  2. The array decays to a pointer to the first element uint8_t **

  3. The first array subscript operator [1] accesses the first element of the array by performing pointer arithmetic on the decayed pointer. It is equivalent to *(data + 1), the result is of type uint8_t *

  4. The second array subscript operator [2] does the same with the pointer read from the array *(*(data + 1) + 2), yielding a result of type uint8_t

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106