-2

I have this two functions and I need to pass the table array and modify his content.

void play_game(int mines, int c, int r) {
    char (*table)[c][r];
    build_field(*table, c, r);
}

void build_field(char *table ,int tamanhox, int tamanhoy) {
    int i, x; 
    for(i=1;i<tamanhoy+1;i++){        
        table[tamanhoy][tamanhox] = '-';          
        for(x=0;x<tamanhox-1;x++){
            table[tamanhoy][tamanhox] = '-';
    }
}

In this code,there's errors at table[tamanhoy][tamanhox].

  • 1
    If you're willing to assume a certain memory layout underneath you can pass your table as a `char**`. Otherwise you need to create your own matrix representation on a flat `char*` memory space and use that. There are plenty of good C-matrix libraries. – David Nov 18 '16 at 15:26
  • @David: `char **` is not a multidimensional array, cannot represent one or point to one! That is a completely different data structure. The type OP has can easily be passed to a function. And the solution is obvious. – too honest for this site Nov 18 '16 at 15:39
  • @Olaf: Yes, they're different data structures. But if you assume a certain memory layout you absolutely can use a char** to index into a multidimensional array. It's understandably bad form, but sometimes you can't get around it. I see you complained about this technique in the link I'm about to post as well, so I guess we'll just disagree. http://stackoverflow.com/questions/2565039/how-are-multi-dimensional-arrays-formatted-in-memory – David Nov 18 '16 at 18:19
  • @David: A pointer is not an array! That's the fundamental error of beginners and some "experts" who never adopted to modern C (i.e. C99 and the current standard). In C, an array is a single, uniform datastructure. Something like `char **` is not and cannot be! And you definitively cannot pass a `char (*)[]` as `char **`! That results in UB (not the "leave it to the implementation" kind!). I really wonder what your problem is using the correct approach and why you talk into those "jagged arrays". Apparently OP wants/has a simple rectangular array. – too honest for this site Nov 18 '16 at 18:28
  • @Olaf: First, I didn't say that a pointer was an array, I said that if they have the same underlying memory layout you can use one to index into the other and vice-versa. Second, I don't appreciate you insinuating that I have "a problem". It's rude and unprofessional. This site is a place for technical content and not personal attacks. – David Nov 18 '16 at 18:39
  • @David: You fundamental missconception is, that you assume they have or can have the same layout! They **don't** and cannot. And I did not say you had a problem, but that I wonder why you insists on using an outdated and incompatibel approach. Because that's the impresson your defense of an obviously incompatible (to the array OP apparently already has in his code) approach invokes. The term "problem" is by default not negatively connoated. But one can always apply the worst interpretation, of course. – too honest for this site Nov 18 '16 at 18:48
  • @Olaf: That is wrong. They do on plenty of popular architectures. – David Nov 18 '16 at 18:53
  • Non sequitur! That's not even close to a rationale argument. How was it with "unprofessional"? – too honest for this site Nov 18 '16 at 18:57
  • @Olaf: It's a factual statement about some compilers. Try it out. The following program works as expected on GCC 4.8.5: `int main(){ int mat[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; int *ptr = &mat[0][0]; int i; for(i = 0; i < 9; i++){ printf("%d\n", *(ptr+i)); } return 0; }` – David Nov 18 '16 at 20:13
  • By the way, that program works for values of `-std=c89`, `-std=c90`, `-std=c99`, and `-std=c11`. This has nothing to do with versions of the C standard, it just so happens that pretty much every compiler lays out 2D arrays in row-major order. – David Nov 18 '16 at 20:19
  • @David: Of course it works! But why would one want to work**against** the compiler/tools, instead of using their features to support you writing good code? And we talked about a "pointer to pointer", not an `int *`! Btw: crosswing sub-array boundaries invokes undefined behaviour. Your compiler is free to assume you use the `int *` correctly; there might be quite some bad surprises with specific code. Finally: The layout is implicitly given by the standard. It is not a matter of the implementation! – too honest for this site Nov 18 '16 at 20:42
  • @Olaf: A good professional has a toolkit full of alternatives. There's a reason I posted this as a comment rather than an answer. – David Nov 18 '16 at 20:47
  • A **good** professional does not deviate from the standard unless there are good reasons and there is proof from other sources the code will work. As I wrote: there is no reason not to use a 2D array and pass it as such (in the C context, of course) to the function. – too honest for this site Nov 18 '16 at 22:01

2 Answers2

1

You get an error because you declare the argument table to be a pointer to a char, not a pointer to an array of arrays. You also don't make table actually point anywhere.

Both these problems can be solved by not making table a pointer to an array of array, and by changing the order you pass the arguments to the build_field function:

char table[c][r];
build_field(c, r, table);

...

void build_field(int tamanhox, int tamanhoy, char table[][tamanhoy])
{
    // Use table like a normal array of array (i.e. table[x][y] = z)
}

There are a couple of other problems with the code you show as well, like you always using table[tamanhoy][tamanhox] in the build_field function, when you probably mean table[x][i].

You are also looping out of bounds in the function, remember that indexes are zero-based, so valid indexes for the first "dimension" is 0 to tamanhox - 1 (inclusive).

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    As a sidenote: Using both dimensions like `char table[tamanhox][tamanhoy]` yields the same, but is better from a documentatry view. It makes clear the two integers are the dimensions without an extra comment. Also the correct type for array dimensions is `size_t`, not `int`. This also makes clear you shall never pass a negatrive value. For certain systems, e.g. most 64 bit architectures, `int` cannot represent all indexes, as those allow more than what 32 bits can hold. On such systems, `size_t` typically is 64 bits. Similar for some 16 bit architectures with more than 16 bit address-space. – too honest for this site Nov 18 '16 at 18:30
1

This declaration

char (*table)[c][r];

does not declare an array. It is declares a pointer to an object of type char[c][r]. By the way why is not ?:)

char[r][c]
     ^^^^^

Thus before using this pointer it shall be correctly initialized.

In this function declaration

void build_field(char *table ,int tamanhox, int tamanhoy);

the first parameter has type char *. Types char ( * )[c][r] and the type char * are different incompatible types.

You could write the function declaration for example the following type

void build_field( int tamanhox, int tamanhoy, char ( *table )[tamanhox][tamanhoy] );

But inside the function you have to dereference the pointer. For example

( *tablw)[I][j]

The exact parameter declaration depends on how the pointer is initialized and what you are going to do. Maybe you mean the following declarations

char (*table)[r];

and

void build_field( int tamanhox, int tamanhoy, char ( *table )[tamanhoy] );

The compiler issues an error because the function parameter table has type char *. So table[I] is a scalar object of type char. Hense you may not apply to it the subscript operator like table[I][x]. And moreover this expression

table[tamanhoy][tamanhox]
      ^^^^^^^^  ^^^^^^^^^

in any case does not make sense because at least you should write

table[i][x]
     ^^^^^^
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335