1

coming from this question "What does (int (*)[])var1 stand for?" I tried to access the result of the cast like a multidimensional array. But I get following error: "assignment from incompatible pointer type" followed by a segmentation fault. I tried also some other variations, but none of them worked. How can I access the elements in var1 in the function example directly?

Thank you!

 #include <stdlib.h>

int i(int n,int m,int var1[n][m]) {
  var1[0][0]=5;
  return var1[0][0];
}

int example() {
  int *var1 = malloc(100);

  // works
  int var2;
  var2 = i(10,10,(int (*)[])var1);
  printf("var2=%i",var2);
  //doesn't work I
  int *var3;
  var3=(int (*)[])var1; //"assignment from incompatible pointer type"
  printf("var3[0][0]=%i",var3[0][0]);


  //doesn't work II
  int *var4;
  var4=var1;
  printf("var4[0][0]=%i",var4[0][0]); //" error: subscripted value is neither array nor pointer"

  //doesn't work III
  int **var5;
  var5=var1;
  printf("var5[0][0]=%i",var5[0][0]); // assignment from incompatible pointer type


  return(1); 

} 

int main(){
  int a;
  a=example();
  return(1);
}
Community
  • 1
  • 1
Framester
  • 33,341
  • 51
  • 130
  • 192

5 Answers5

3
int *var3;
var3 = (int (*)[])var1;

You are casting var1 which is already int* to int(*)[] (pointer to array of int) and assigning it to var3 which again is int*.

Just do

var3 = var1
Amarghosh
  • 58,710
  • 11
  • 92
  • 121
  • Hi Amarghosh, I tried to implement your example, but I get the error message "subscripted value is neither array nor pointer". Maybe I misunderstood you. Could you check the edit I made to the question? Thanks! – Framester Jun 04 '10 at 12:19
  • @Framester you cannot subscript (use `[]` on) an `int*` twice. Either declare var3 as `int**` and assign `&var1` to it or just read `var3[0]`. What exactly are you trying to do? – Amarghosh Jun 04 '10 at 12:36
  • I want to avoid the detour using a separate function. I try to access `var1` in the function `example` as it is accessed in the function `i` via [][]. – Framester Jun 04 '10 at 12:40
  • @Framester Casting a pointer to a multidimensional array of same type works only upon function calls - in normal case you cannot just cast a pointer to array and assign to an array variable. If you explain why you need two dimensional access instead of one dimensional, may be we can help. Declaring var3 as int** and assigning `&var1` to it will compile, but will seg fault for values of i greater than one in `var3[i][j]` – Amarghosh Jun 04 '10 at 13:14
1

Give this a shot. The following compiled with no warnings and ran under C99 (gcc -std=c99 -pedantic -Wall):

#include <stdio.h>
#include <stdlib.h>

int i(int n, int m, int (*var1)[m]) // C89 requires constant expression for
{                                   // array size
  int j, k;
  for (j = 0; j < n; j++)
    for (k = 0; k < m; k++)
      var1[j][k] = j*m+k;
  return var1[0][0];
}

int example(void)
{
  int *var1 = malloc(100 * sizeof *var1);   // Thanks, Joseph!
  int var2 = i(10, 10, (int (*)[10]) var1); // note the cast of var1 includes
                                            // the array size
  int (*var3)[10] = (int (*)[10]) var1;     // note the type of var3

  int j, k;
  for (j = 0; j < 100; j++)
    printf("var1[%2d] = %d\n", j, var1[j]);

  for (j = 0; j < 10; j++)
    for (k = 0; k < 10; k++)
      printf("var3[%2d][%2d] = %d\n", j, k, var3[j][k]);

  free(var1);
  return var2;
}

int main(void)
{
  int x = example();
  printf("x = %d\n", x);
  return 0;
}

First of all, note the types and the casts (most importantly, note how they match up). Note that I am specifying the size of the array dimension in the pointer-to-array casts. Also note that I declare var3 as a pointer to an array, not a simple pointer.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • Thanks, casting var3 this way `int (*var3)[10] = (int (*)[10]) var1;` is the solution for me! – Framester Jun 07 '10 at 12:04
  • I think you meant `malloc(400)`, not `malloc(100)`, depending on your target. See http://stackoverflow.com/questions/2973856/can-i-access-type-int-with/2976113#2976113 for a clean way of doing this. – Joseph Quinsey Jun 08 '10 at 19:45
  • And, as a rule-of-thumb, if is best to avoid unnecessary casts (except in MSVC!). See the previous link for a cast-less solution. – Joseph Quinsey Jun 08 '10 at 19:50
  • 1
    @Joseph: Regarding the `malloc` call -- good catch. I've edited the code to fix that problem (it's always the stupid crap that trips me up). Regarding the "unnecessary" casts, my take on the OP's question was, given that he had a 1-D array, how could he access it *as though* it was a 2-D array? Hence the casts. Personally, I would not write code this way, but I think it's a useful exercise to think about the differences between array types. – John Bode Jun 08 '10 at 21:52
0

var3 needs to be a int** instead of an int*.

Edit

You're trying to use 2D array syntax where the actual data that you've created is actually a 1D array. You can use your i() function to give you the semantics you want but the data access needs to be converted to 1D indexing inside the function. Just make your function look like this:

int i(int n,int m,int* var1, int maxM) {
  return var1[(maxM * n) + m];
}
bshields
  • 3,563
  • 16
  • 16
  • whoops mixing up languages... the first part is still valid. – bshields Jun 04 '10 at 12:23
  • Hi bshields, I added an example of how I understood you. See `//doesn't work III` But I get the error message `// assignment from incompatible pointer type` – Framester Jun 04 '10 at 12:32
  • I understand, that the malloc here only creates a 1D array. But why can't I access var1 as a 2D array in the `example` function, when I can access it as a 2D array in the `i` function. *confused* – Framester Jun 04 '10 at 13:00
  • I think the answer is that your current i function isn't really working. You've got this compiling because you've casted it appropriately but have you verified that it actually works without crashing? I'm pretty sure this would crash. – bshields Jun 04 '10 at 13:08
0
int example() {
    int *var1 = malloc(100);

    ...

    int *var3;
    var3=var1;
    printf("var3[0][0]=%i",var3[0][0]); //" error: subscripted value is neither array nor pointer"

    return(1); 
} 

Here, var1 and var3 are both of type int*, which is roughly analogous to int[]. You've created a one-dimensional array and are trying to access them as a two-dimensional array. Change their type to int**, allocate the necessary memory, and that should fix your problem.

Haldean Brown
  • 12,411
  • 5
  • 43
  • 58
0

Perhaps what you are looking for is:

int (*var1)[10][10] = malloc(sizeof *var1); // 400 bytes
i(10, 10, *var1);
printf("var1[0][0]=%i\n", (*var1)[0][0]);

Added: A complete code fragment for gcc might be:

#include <stdio.h>
#include <stdlib.h>

void i(int n, int m, int var1[][m]) { // n not needed
    var1[0][0] = 5;
    var1[1][2] = 6;
}

int main(void) {
    int n = 10, m = 10;
    int (*var1)[n][m] = malloc(sizeof *var1); // 400 bytes
    i(n, m, *var1);
    printf("var1[0][0]=%i\n",(*var1)[0][0]);
    printf("var1[1][2]=%i\n",(*var1)[1][2]);
    return 0;
}

For msvc, you'll need to make n and m constants, as in:

enum {n = 10, m = 10};

void i(int var1[][m]) {
    var1[0][0] = 5;
    var1[1][2] = 6;
}

int main(void) {
    int (*var1)[n][m] = malloc(sizeof *var1);
    i(*var1);
    // ...
}
Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77