I picked up the code and came across such a thing:

Here is the code:

#include "stdio.h" void a_f(char str[][0]) /// !!! Если менять правый индекс то программа будет выводить адреса с интервалами которые равны индексу (сейчас это зафиксированно и указатель никак не меняется!) { int i = 4; while(i >= 0) { printf("%s - %p\n", str+i, str+i); --i; } } int main(void) { char a[][10] = {"hello", "world", "again", "repeat", "stop"}; printf("start:%p\nend:%p\n\n", a, a+4); a_f(a); return 0; } 

I can not explain why and why? Explain what a beast! In various manuals about arrays, I did not see this.

  • Is this a typo char str [] [0])? - Vlad from Moscow
  • @VladfromMoscow I corrected read the comment in the code - MaximPro
  • @VladfromMoscow, apparently, this is precisely his question. What is [][0] and why 0. - Qwertiy
  • @MaximPro And what is the question? What do you expect to receive, and what do you get? - Vlad from Moscow
  • @VladfromMoscow for what it is generally needed? Here is my question! - MaximPro

1 answer 1

If you have a pointer to an object of some type, such as

 T *p = &obj; 

so that with this pointer you can perform pointer arithmetic or dereference a pointer, you need to know the size of the object addressed by the pointer. In other words, you need to know the value of sizeof( T ) .

For example, if there is an expression ++p , the question arises: how much should the value stored in the pointer increase? Obviously, after this operation, the pointer must point to a place in memory after this object (or the next element of the array if the current object is an element of the array), that is, the pointer value must increase by the sizeof( obj ) size sizeof( obj ) . This means that the size of the object pointed to by the pointer must be known to the compiler.

Therefore, for this function

 void a_f(char str[][10]) /// !!! Если менять правый индекс то программа будет выводить адреса с интервалами которые равны индексу (сейчас это зафиксированно и указатель никак не меняется!) { int i = 4; while(i >= 0) { printf("%s - %p\n", str+i, str+i); --i; } } 

which is called with an argument declared as a two-dimensional array

 char a[][10] = {"hello", "world", "again", "repeat", "stop"}; 

the function parameter declared as an array is implicitly cast to the type of the pointer to the array element. In turn, the argument, that is, the two-dimensional array a , is converted implicitly to a pointer to its first element.

The element of this two-dimensional array is, in turn, a one-dimensional array having the type char[10] Therefore, if you have a pointer to the first element of this two-dimensional array, then to change it so that it points to the next, that is, the second element of the array, its value must be increased by the size of the addressable element. The size of the addressed element, that is, a one-dimensional array, is equal to sizeof( char[10] ) . The function must know the size of this addressable array in order to properly perform operations with pointers.

Thus a parameter of a function declared as

 void a_f(char str[][10]); 

is cast to type

 void a_f(char ( *str )[10]); 

that is, a pointer to an element of the array.

In turn, an array specified as a function argument is also converted to a pointer to its first element. This can be represented as follows.

 char ( *tmp )[10] = a; a_f( tmp ); 

Given this information about the size of the object (which is equal to sizeof( char[10] ), pointed to by the pointer char (* str) [10]), declared as a function parameter, the function can correctly calculate the expression str+i , which is equal to the value stored in str , plus a value of i * 10 * sizeof( char ) . That is, as a result, the pointer str would point to the i -th element of a two-dimensional array, the size of which element is 10 . This is the meaning of pointer arithmetic.

To make it clearer, you could introduce an alias of the type of the element of a dimensional array as follows

 typedef char T[10]; // ... T a[] = {"hello", "world", "again", "repeat", "stop"}; 

In turn, the function declaration will look like

 void a_f( T *str ); 

or how

 void a_f( T str[] ); 

These two declarations declare the same function.

Therefore, the size of the object pointed by the pointer will be equal to sizeof( T ) , which, according to the alias entered, is equal to sizeof( char[10] )

  • If I understand everything correctly now, then in the entry char (*str)[10] str is a pointer to an array of 10 elements of type char . If so, is it correct to compare the same pointer to the type int int *p with what I wrote above? Just as a matter of fact, if int = 4 байтам then the array from char[10] = 10 байтам . An increase with int more familiar with pointers than with an array of something. If you draw a line that the array of something can be called a special data type. Did I understand everything correctly? - MaximPro
  • @MaximPro I did not understand, and here the int * p pointer and with what you are going to compare it and why. - Vlad from Moscow
  • it's like a comparison, no more - MaximPro
  • @MaximPro An array is not a pointer, but in expressions with a rare disconnect, such as when used in the sizeof operator, the array is converted to a pointer to its first element. - Vlad from Moscow
  • And I'm not saying that the array is a pointer =) But yes, the address of the first element is taken in the expressions. But what does it have to do with it? - MaximPro