views:

183

answers:

5

Hi

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);
}
+3  A: 
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
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
Amarghosh
@Amarghosh, 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
Amarghosh
A: 

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
That's not valid C syntax.
sepp2k
whoops mixing up languages... the first part is still valid.
bshields
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
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
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
A: 
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
A: 
Joseph Quinsey
+1  A: 

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
Thanks, casting var3 this way `int (*var3)[10] = (int (*)[10]) var1;` is the solution for me!
Framester
You understand *why* it works, right?
John Bode
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
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
@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