I have a 2D dynamic array.
I enter a line of 0's after line which has a biggest number:
void InsertZero(int **a, int pos){
int i, j;
a = (int**)realloc(a, n * sizeof(*a));
a[n-1] = (int*)calloc(n, sizeof(**a));
d = 0;
for(i = n-1; i > pos; i--){
for(j = 0; j < n; j++){
a[i][j] = a[i-1][j];
printf("%d ", a[i][j]);
}
}
for(i = 0; i < n; i++){
a[pos][i] = 0;
}
}
If i make a size of array 3, 5, 7, 9, ... it works correctly. But if a number of lines is 2, 4, 6, ... , it is an access violation error, when i try to print my array:
void Print(void){
int i, j;
for(i = 0; i < (n-d); i++){
for(j = 0; j < n; j++){
printf("%d\t", arr[i][j]);
}
printf("\n");
}
}
code: http://codepad.org/JcUis6W4
Looking at this I cannot make sense of.... Look at comment 1, you have n set somewhere to realloc a block of memory which a is of type int ** - a double pointer, how are you calling this function? Secondly, comment 2, Why did you call calloc when the realloc on a double pointer was called previously...? Assume n has value of 5, then, realloc is called on double pointer a, meaning a[0][1]..a[4][1], now calloc is called thus a[4] has a new block of memory...
void InsertZero(int **a, int pos){
int i, j;
/* 1. */
a = (int**)realloc(a, n * sizeof(*a));
/* Bzzzzt....if realloc failed, a gets overwritten! */
/* 2. */
a[n-1] = (int*)calloc(n, sizeof(**a));
/* 3. */
d = 0;
/* 4. */
for(i = n-1; i > pos; i--){
for(j = 0; j < n; j++){
a[i][j] = a[i-1][j];
printf("%d ", a[i][j]);
}
}
for(i = 0; i < n; i++){
a[pos][i] = 0;
}
}
Comment 3, what is d used for - useless variable?
Comment 4, you are under the presumption that the block of memory has array subscripts [0][0] to [4][4] if n had a value of 5!
Can you clarify all this?
Edit: Looking at it again... it is likely that a got overwritten when the call to realloc failed! I recommend this section of code to counteract this
int **tmpA;
tmpA = (int**)realloc(a, n * sizeof(*a));
if (tmpA != NULL){
a = tmpA;
....
a[n-1] = (int*)calloc(n, sizeof(**a));
for(i = n-1; i > pos; i--){
....
}
for(i = 0; i < n; i++){
....
}
}
In your function InsertZero you have a local variable a. This local variable is initially set with a the address of a pointer to an integer (you probably wanted the address of a pointer to an array of integers, i.e. int ***a).
When you call realloc you are assigning your local copy of a a pointer to a block of memory, however once you have finished with your function it is entirely possible for your local copy of a to be pointing somewhere different to the rest of your program. You probably wanted to say *a = (int **)realloc(a, n * sizeof(int *));.
Dangerously, you're using n which isn't passed to your function. It appears you've made the assumption that n is going to be 1 bigger than the previous size of the array - otherwise your call to calloc is superfluous and you are just rotating the array letting the last element drop off as a memory leak.
Let's use a simpler example with no arrays, no dimensions. Let's say you wanted to create a function:
void make_me_a_pointer( int **mynumber ) {
*mynumber = (int *)malloc( sizeof(int) );
**mynumber = 7; /* assign the value 7 to my allocated memory */
}
int main( void ) {
int *demoint;
make_me_a_pointer( &demoint );
printf( "Magic num is %d\n", *demoint );
}
However in your case you merely assigned a = realloc... and thus never communicated the new address of a outside your function.
Related
Related to dynamic allocation inside a function, most questions & answers are based on double pointers.
But I was recommended to avoid using double pointer unless I have to, so I want to allocate a 'array pointer' (not 'array of pointer') and hide it inside a function.
int (*arr1d) = calloc(dim1, sizeof(*arr1d));
int (*arr2d)[dim2] = calloc(dim1, sizeof(*arr2d));
Since the above lines are the typical dynamic-allocation of pointer of array, I tried the following.
#include <stdio.h>
#include <stdlib.h>
int allocateArray1D(int n, int **arr) {
*arr = calloc(n, sizeof(*arr));
for (int i = 0; i < n; i++) {
(*arr)[i] = i;
}
return 0;
}
int allocateArray2D(int nx, int ny, int *(*arr)[ny]) {
*arr[ny] = calloc(nx, sizeof(*arr));
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
(*arr)[i][j] = 10 * i + j;
}
}
return 0;
}
int main() {
int nx = 3;
int ny = 2;
int *arr1d = NULL; // (1)
allocateArray1D(nx, &arr1d);
int(*arr2d)[ny] = NULL; // (2)
allocateArray2D(nx, ny, &arr2d);
for (int i = 0; i < nx; i++) {
printf("arr1d[%d] = %d \n", i, arr1d[i]);
}
printf("\n");
printf("arr2d \n");
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
printf(" %d ", arr2d[i][j]);
}
printf("\n");
}
return 0;
}
And the error message already comes during the compilation.
03.c(32): warning #167: argument of type "int (**)[ny]" is incompatible with parameter of type "int *(*)[*]"
allocateArray2D(nx, ny, &arr2d);
^
It is evident from the error message that it has been messed up with the argument types (that I wrote as int *(*arr)[ny]) but what should I have to put there? I tried some variants like int *((*arr)[ny]), but didn't work).
And if I remove the 2D parts, then the code well compiles, and run as expected. But I wonder if this is the right practice, at least for 1D case since there are many examples where the code behaves as expected, but in fact there were wrong or un-standard lines.
Also, the above code is not satisfactory in the first place. I want to even remove the lines in main() that I marked as (1) and (2).
So in the end I want a code something like this, but all with the 'array pointers'.
int **arr2d;
allocateArray2D(nx, ny, arr2d);
How could this be done?
You need to pass the array pointer by reference (not pass an array pointer to an array of int*):
int *(*arr)[ny] -> int (**arr)[ny]
The function becomes:
int allocateArray2D(int nx, int ny, int (**arr)[ny]) {
*arr = calloc(nx, sizeof(int[ny])); // or sizeof(**arr)
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
(*arr)[i][j] = 10 * i + j;
}
}
return 0;
}
For details, check out Correctly allocating multi-dimensional arrays
Best practices with malloc family is to always check if allocation succeeded and always free() at the end of the program.
As a micro-optimization, I'd rather recommend to use *arr = malloc( sizeof(int[nx][ny]) );, since calloc just creates pointless overhead bloat in the form of zero initialization. There's no use of it here since every item is assigned explicitly anyway.
Wrong parameter type
Strange allocation
Wrong size type
I would return the array as void * too (at least to check if allocation did not fail).
void *allocateArray2D(size_t nx, size_t ny, int (**arr)[ny]) {
//*arr = calloc(nx, sizeof(**arr)); calloc is not needed here as you assign values to the array
*arr = malloc(nx * sizeof(**arr));
for (size_t i = 0; i < nx; i++) {
for (size_t j = 0; j < ny; j++) {
(*arr)[i][j] = 10 * i + j;
}
}
return *arr;
}
I'm writing a C for which I need to create a 2D array. I've found a solution to my problem using double pointers (pointers to pointers) in the following way:
#include <stdio.h>
#include <stdlib.h>
int d = 3;
#define DIM_MAX 9
void changeArray(int d, int *array[d]);
int main()
{
//alocate array of 'd' colummns and 'd' row using malloc using array of pointers
int **array = malloc(d*sizeof(int *));
for(int count = 0; count < d; count++)
{
array[count] = malloc(d*sizeof(int *));
}
/* Call changeArray function */
changeArray(d, array);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
for(int count = 0; count < d; count++)
{
free(array[count]);
}
return 0;
}
void changeArray(int n, int *array[d])
{
for(int i =0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
array[i][j] = i*j;
}
}
return;
}
The code above works pretty well (it seems), but I've read in the web that using pointer to pointer is not the correct way to create 2D arrays. So I've come up with the following code, which also works:
#include <stdio.h>
#include <stdlib.h>
#define DIM_MAX 9
int d = 3;
void changeArray(int d, int *array[d]);
int main()
{
//alocate array of 'd' colummns and 'd' row using malloc using array of pointers
int *array[DIM_MAX] = {0};
for(int count = 0; count < d; count++)
{
array[count] = (int *)malloc(d*sizeof(int *));
}
/* Call changeArray function */
changeArray(d, array);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
for(int count = 0; count < d; count++)
{
free(array[count]);
}
return 0;
}
void changeArray(int n, int *array[d])
{
for(int i =0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
array[i][j] = i*j;
}
}
return;
}
What is the difference in using any of the two ways above to write this code?
[Not an answer, but an alternative approach to achieve the desired result, namely defining a user-defined 2D array.]
Assuming the compiler in use supports VLAs you could do this:
#include <stddef.h> /* for size_t */
void init_a(size_t x, size_t y, int a[x][y]); /* Order matters here!
1st give the dimensions, then the array. */
{
for (size_t i = 0; i < x; ++i)
{
for (size_t j = 0; j < y; ++j)
{
a[i][j] = (int) (i * j); /* or whatever values you need ... */
}
}
}
int main(void)
{
size_t x, y;
/* Read in x and y from where ever ... */
{
int a[x][y]; /* Define array of user specified size. */
init_a(x, y, a); /* "Initialise" the array's elements. */
...
}
}
It is actually pretty simple. All you have to do is this:
int i[][];
You are overthinking it. Same as a normal array, but has two indexes.
Let's say you want to create a "table" of 4 x 4. You will need to malloc space for 4 pointers, first. Each of those index points will contain a pointer which references the location in memory where your [sub] array begins (in this case, let's say the first pointer points to the location in memory where your first of four arrays is). Now this array needs to be malloc for 4 "spaces" (in this case, let's assume of type INT). (so array[0] = the first array) If you wanted to set the values 1, 2, 3, 4 within that array, you'd be specifying array[0][0], array[0][1], array[0][2], array[0][3]. This would then be repeated for the other 3 arrays that create this table.
Hope this helps!
I made a structure who has two members (int and int**), and I return the pointer to this structure from one function to main(). It is fine to access the int value in the structure. However, in main() I got Segmentation fault : 11 when I tried to access the element of the 2D array.
#include<stdio.h>
#include<stdlib.h>
typedef struct Square {
int value;
int **array;
} Square;
Square * generate();
int main(int argc, char *argv[]){
Square *sqrptr = generate();
printf("%d\n", sqrptr -> value);
/* It prints 1 */
/* Print out the 2D array */
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3 ; j++){
printf("%d ", *(*((sqrptr -> array) + i) + j));
}
printf("\n");
}
/* It gives segmentation fault */
return 0;
}
Square * generate(){
Square mySquare;
mySquare.value = 1;
mySquare.array = malloc(sizeof(int*) * 3);
/* Initialize the 2D array */
for (int i = 0; i < 3; i++){
*(mySquare.array + i) = malloc(sizeof(int) * 3);
for (int j = 0; j < 3; j++){
*(*(mySquare.array + i) + j) = 0;
}
}
/* Print out the 2D array */
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3l ; j++){
printf("%d ", *(*(mySquare.array + i) + j));
}
printf("\n");
}
/* I can see the complete 2D array here */
Square *sqrptr = &mySquare;
return sqrptr;
}
I have tried to generate the Square in main(), and use one pointer of the structure to access my 2D array. It works fine, so I guess I have missed something when I use a pointer returned from other functions. On the other hand, I can access the int value successfully, so I have no clues now.
Could someone please explain the underlying reason for this segmentation fault? Thanks!
You're returning a pointer to a local variable (&mySquare). Stack memory (where local variables reside) is when the function returns, so the resulting pointer is pointing to invalid memory. Allocate the struct, and return the pointer to heap memory:
Square *my_square = malloc(sizeof *my_square);
//do stuff
return my_square;
Or pass a pointer to a stack variable as argument:
Square * generate(Square *my_square)
{
//in case pointer wasn't provided, allocate
if (my_square == NULL) {
my_square = malloc(sizeof *my_square);
if (!my_square)
return NULL; // or exit or whatever
}
//initialize members. To initialize array to 3x3 zero matrix, you can use:
for (int i=0;i<3;++i)
my_square.array[i] = calloc(3, sizeof *my_square->array[i]);
//or even, if you change array member to type int*:
my_square.array = calloc(3*3, sizeof *my_square->array);
//at the end:
return my_square;
}
The latter is arguably the most flexible solution: if you want to work on stack, you call the function like so:
Square my_stack_square;
generate(&my_stack_square);
If you need to use heap memory, you can use:
Square *my_heap_square = generate(NULL);
As Jonathan Leffler pointed out, for a small struct such as this, returning by value isn't too much of a cost. Getting a struct on heap can be achieved in the same way as returning any other type:
Square generate( void )
{
Square my_square;
//initialize
return my_square;
}
//call like so:
Square sq = generate();
The idea here is that you'll use a local variable in the generate function to create a new square, initialize the fields, and then return it. Because in C everything is passed by value, this essentially means the function will assign the value of the local variable from the generate function to the caller's scoped sq variable. For small structs such as this, that's perfectly fine.
What's more, a common thing for compilers to do is to optimise these kinds of functions to the equivalent of the second example I posted: Essentially your function will be creating a new Sqaure object on the stack memory of the caller. This can happen, that's not to say it will. It depends on the optimization levels used when compiling, and on the size of the struct you're returning.
Basically, if you want to keep the code as close to what you have now, it's probably easiest to stick to the first version (returning a heap pointer).
The more flexible approach is the second one (as it allows you to use stack and heap, depending on how you call the function).
For now, using the third approach is perfectly fine: the compiler will most likely optimize the code to whatever makes most sense anyway.
Try this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct Square {
int value;
int **array;
} Square;
Square * generate();
int main(int argc, char *argv[]){
Square *sqrptr = generate();
printf("%d\n", sqrptr -> value);
/* It prints 1 */
/* Print out the 2D array */
int i,j;
for (i = 0; i < 3; i++){
for (j = 0; j < 3 ; j++){
printf("%d ", *(*((sqrptr -> array) + i) + j));
}
printf("\n");
}
/* It gives segmentation fault */
return 0;
}
Square * generate(){
Square* mySquare = (Square*) malloc(sizeof(Square)); //c++ compiler
//Square* mySquare = (void*) malloc(sizeof(Square)); //c compiler
mySquare->value = 1;
mySquare->array = malloc(sizeof(int*) * 3);
/* Initialize the 2D array */
int i,j;
for (i = 0; i < 3; i++){
*(mySquare->array + i) = malloc(sizeof(int) * 3);
for (j = 0; j < 3; j++){
*(*(mySquare->array + i) + j) = 0;
}
}
/* Print out the 2D array */
for (i = 0; i < 3; i++){
for (j = 0; j < 3l ; j++){
printf("%d ", *(*(mySquare->array + i) + j));
}
printf("\n");
}
/* I can see the complete 2D array here */
return mySquare;
}
Here is a segment of my (incomplete) code
int rows(int board[][9]){
int badUnits = 0, i = 0, n = 9, j, z = 0;
int (*temp)[9];
//Sort each row of 2d array
for (z; z < n; z++){
for (i; i < n; i++){
for (j = i; j < n; j++){
if (board[z][i] > board[z][j]){
temp = board[z][i];
board[z][i] = board[z][j];
board[z][j] = temp;
}
}
}
}
printf ("%d\n", temp[1][0]);
printf ("%d\n", temp[1][1]);
return badUnits;
}
The function takes a 9*9 array.
I get a segmentation fault when the print statements are executed.
I believe my sort code is correct because it is similar to what I use for 1d arrays and I think everything else is correctly assigned.
So the culprit would be my temp variable. I have gone through and tried to assign values to it, tried to change the type, and have taken into account that the 2d array decays into a pointer but is not actually a pointer.
The conclusion I am left with is that this is a dynamic allocation issue. Can someone please lend a hand and assist me in fixing this? I have exhausted my knowledge base and am stuck.
To clarify: I decided to print the temp variable because I thought it would lend some information. The main problem was that the swap was not working, and I was still left with an unsorted array when I originally attempted to print out the board[][]. I know that board is what I am SUPPOSED to be printing.
Thank you for any help!
You assign an int value to temp
temp = board[z][i]; // Temp now is a what ever value was at
// That location in the array e.g. 42
You then treat temp as if it was the address in memory of an integer array
temp[1][1] // treat temp as a pointer and find the integer
// 10 integers further along then temp.
Also sometime temp will not have been initialised (never assigned to) in this case your going to get unexpected behaviour depending on what the last value stored where temp is now (Lets call it a random number).
Did you mean to output the values in board?
printf ("%d\n", board[1][0]);
printf ("%d\n", board[1][1]);
One thing to notice is that the variable temp will only get assigned to if a swap occurs, if the sorting algorithm was correct that is still a situation that could occur with a input corresponding to a sorted board.
But more importantly, the variable temp is used as an int during the swap. Later that integer value is interpreted as a pointer in the expressions temp[1][0] and temp[1][1], which in all likelihoods is not a valid address. You may want to change temp to be declared as:
int temp;
And figure out exactly what you would like to print. If it is whatever one of the two swapped values was (for the last swapped pair in the loop), then you would print it as:
printf("%d", temp);
Else, you would have to add logic according to what you really want to do.
Note that a single pass of this algorithm would not perform a complete sort, but I guess that's one of the reason why you said the provided code was not complete.
Something like this?
#include <stdio.h>
#include <stdlib.h>
void printArray(int** arr, int w, int h) {
for (int i = 0; i < w; ++i) {
for (int j = 0; j < h; ++j) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
void sortArray(int** arr, int w, int h) {
for (int row = 0; row < h; ++row) {
for (int col = 0; col < w; ++col) {
for (int i = 0; i < w; ++i) {
if (arr[row][i] > arr[row][col]) {
int tmp = arr[row][col];
arr[row][col] = arr[row][i];
arr[row][i] = tmp;
}
}
}
}
}
int main() {
int w = 9, h = 9;
int** arr = (int**)malloc(sizeof(int*) * w);
for (int i = 0; i < w; ++i) {
arr[i] = (int*)malloc(sizeof(int) * h);
for (int j = 0; j < h; ++j) {
arr[i][j] = rand() % 10;
}
}
printf("Unsorted:\n");
printArray(arr, w, h);
sortArray(arr, w, h);
printf("Sorted:\n");
printArray(arr, w, h);
for (int j = 0; j < h; ++j) {
free(arr[j]);
}
free(arr);
return 0;
}
I was writing a code the other day and I found it rather strange, that int** and int[][] does not behave the same way. Can anyone point out the differences between them? Below is my sample code, which fails with a segmentation fault, if I pass constant size 2d array, while it does work fine when I pass a dinamically allocated 2d array.
I am confused mainly because ant int[] array works the same as int*.
#include<stdio.h>
#include<stdlib.h>
void sort_by_first_row(int **t, int n, int m)
{
int i, j;
for(i = m-1 ; i > 0 ; --i)
{
for(j = 0 ; j < i; ++j)
{
if(t[0][j] < t[0][j+1])
{
int k;
for(k = 0 ; k < n ;++k)
{
int swap;
swap = t[k][j];
t[k][j] = t[k][j+1];
t[k][j+1] = swap;
}
}
}
}
}
int main(void) {
int i, j;
/* Working version */
/*int **t;
t =(int**) malloc(3*sizeof(int*));
for(i = 0; i < 3; ++i)
{
t[i] = (int*) malloc(6*sizeof(int));
}*/
/*WRONG*/
int t[3][6];
t[0][0] = 121;
t[0][1] = 85;
t[0][2] = 54;
t[0][3] = 89;
t[0][4] = 879;
t[0][5] = 11;
for( i = 0; i < 6; ++i )
t[1][i] = i+1;
t[2][0] = 2;
t[2][1] = 4;
t[2][2] = 5;
t[2][3] = 3;
t[2][4] = 1;
t[2][5] = 6;
sort_by_first_row(t, 3, 6);
for(i = 0; i < 3; ++i)
{
for(j = 0; j < 6; ++j)
printf("%d ", t[i][j]);
printf("\n");
}
return 0;
}
So based on the below answers I realize, that a multidimensional array is stored continuously in a row major order. After some modification, the below code works:
#include<stdio.h>
#include<stdlib.h>
void sort_by_first_row(int *t, int n, int m)
{
int i, j;
for(i = m-1 ; i > 0 ; --i)
{
for(j = 0 ; j < i; ++j)
{
if(t[j] < t[j+1])
{
int k;
for(k = 0 ; k < n ;++k)
{
int swap;
swap = t[k*m + j];
t[k*m + j] = t[k*m + j+1];
t[k*m + j+1] = swap;
}
}
}
}
}
int main(void) {
int i, j;
/* Working version */
/*int **t;
t =(int**) malloc(3*sizeof(int*));
for(i = 0; i < 3; ++i)
{
t[i] = (int*) malloc(6*sizeof(int));
}*/
/*WRONG*/
int t[3][6];
t[0][0] = 121;
t[0][1] = 85;
t[0][2] = 54;
t[0][3] = 89;
t[0][4] = 879;
t[0][5] = 11;
for( i = 0; i < 6; ++i )
t[1][i] = i+1;
t[2][0] = 2;
t[2][1] = 4;
t[2][2] = 5;
t[2][3] = 3;
t[2][4] = 1;
t[2][5] = 6;
sort_by_first_row(t, 3, 6);
for(i = 0; i < 3; ++i)
{
for(j = 0; j < 6; ++j)
printf("%d ", t[i][j]);
printf("\n");
}
return 0;
}
My new question is this: How to modify the code, so that the procedure works with int[][] and int** also?
Realize that int **t makes t a pointer to a pointer, while int t[3][6] makes t an array of an array. In most cases, when an array is used in an expression, it will become the value of the address of its first member. So, for int t[3][6], when t is passed to a function, the function will actually be getting the value of &t[0], which has type pointer to an array (in this case, int (*)[6]).
The type of what is being pointed at is important for how the pointer behaves when indexed. When a pointer to an object is incremented by 5, it points to the 5th object following the current object. Thus, for int **t, t + 5 will point to the 5th pointer, while for int (*t)[M], t + 5 will point to the 5th array. That is, the result of t + 5 is the same as the result of &t[5].
In your case, you have implemented void sort_by_first_row(int **t, int n, int m), but you are passing it an incompatible pointer. That is, the type of &t[0] (which is what t will become in main) is not the same as what the function wants, a int **t. Thus, when the sorting function starts to use that address, it will think its indexing into pointers, when the underlying structure is an array of arrays.
int** is quite different from int[][]. int** is simply a pointer to a pointer and would appear like the following:
in reality, you can access the entire multidimensional array with simply int* pointing to the first element, and doing simple math from that.
Here is the result of the separate allocations (in your commented code):
However when you allocate a multidimensional array, all of the memory is contiguous, and therefore easy to do simple math to reach the desired element.
int t[3][6];
int *t = (int*) malloc((3 * 6) * sizeof(int)); // <-- similarly
This will result in a contiguous chunk of memory for all elements.
You certainly can use the separate allocations, however you will need to walk the memory differently.
Hope this helps.
int t[3][6] is very nearly the same thing as int t[18]. A single contiguous block of 18 integers is allocated in both cases. The variable t provides the address of the start of this block of integers, just like the one-dimensional case.
Contrast this with the case you have marked as "working", where t gives you the address of a block of 3 pointers, each of which points to a block of memory with 6 integers. It's a totally different animal.
The difference between t[3][6] and t[18] is that the compiler remembers the size of each dimension of the array, and automatically converts 2D indices into 1D offsets. For example, the compiler automatically converts t[1][2] into *(t + 1*6 + 2) (equivalent to t[8] if it were declared as a one-dimensional array).
When you pass a multi-dimensional array to a function, there are two ways to handle it. The first is to declare the function argument as an array with known dimension sizes. The second is to treat your array like a 1D array.
If you are going to declare the size of your array, you would declare your function like this:
void sort_by_first_row(int t[][6], int n)
or this
void sort_by_first_row(int t[3][6])
You either have to declare all array dimension sizes, or you can leave out the first size. In both cases, you access elements of t using t[i][j]; you've given the compiler enough information to do the offset math that converts from 2D notation to a 1D index offset.
If you treat it as a 1D array, you have to pass the array dimensions and then do the offset math yourself.
Here's a full working example, where f and f2 both generate the same output:
void f(int* t, int m, int n)
{
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
std::cout << t[i * n + j] << " ";
std::cout << std::endl;
}
void f2(int t[][6], int m)
{
for (int i = 0; i < m; i++)
for (int j = 0; j < 6; j++)
std::cout << t[i][j] << " ";
std::cout << std::endl;
}
int main()
{
int t[3][6];
int val = 1;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 6; j++)
{
t[i][j] = val;
val++;
}
}
f(&(t[0][0]), 3, 6);
f2(t, 3);
return 0;
}
One thing to note is the hack-ish way I had to pass t to f. It's been a while since I wrote in C/C++, but I remember being able to pass t directly. Maybe somebody can fill me in on why my current compiler won't let me.
A int ** is a pointer to a pointer to an int, and can be a pointer to an array of pointers to arrays of ints. A int [][] is a 2-dimensional array of ints. A two-dimensional array is exactly the same as a one-dimensional array in C in one respect: It is fundamentally a pointer to the first object. The only difference is the accessing, a two-dimensional array is accessed with two different strides simultaneously.
Long story short, a int[][] is closer to an int* than an int**.