-1

This is my code in plain old C. I want to add each column of the data. For example, 28+518+917, 34+512+914, et.al.:

short rawdata[][20]={
28,34,36,39,42,47,37,41,41,33,33,36,36,36,27,27,24,31,29,26,
518,512,507,508,521,522,524,525,519,512,506,511,511,501,501,495,497,500,508,504,
917,914,905,909,892,879,869,873,876,877,875,870,883,893,893,884,881,882,885,888
};

int aae( int nLenFrame, short **psDataBuffer, float *pFV )
{
    float sum = 0.0;
    int i=0, j;
    for (j=0; j<AXES; j++)
    {
        printf("Component: %d\n", *(*(psDataBuffer +j) + i));
    }
    return 1;
}


int main(int argc, char *argv[]){
    int arraySize;
    float pFV;
    int a;

    arraySize = sizeof(rawdata)/sizeof(int);
    a = aae( arraySize, rawdata, &pFV );
    printf("aae = %f\n", pFV);
}

I'm trying to pass rawdata to function aae but when I compile, I get the following errors/warnings from gcc, which naturally, crash my code. How should I pass rawdata into aae?

$ gcc aae.c -o aae
aae.c: In function ‘main’:
aae.c:31:2: warning: passing argument 2 of ‘aae’ from incompatible pointer type [enabled by default]
  a = aae( arraySize, rawdata, &pFV );
  ^
aae.c:13:5: note: expected ‘short int **’ but argument is of type ‘short int (*)[20]’
 int aae( int nLenFrame, short **psDataBuffer, float *pFV )
     ^

Thanks in advance for any help.

ElGranGeek
  • 20
  • 4
  • 2
    The error message contains a very clear hint as how to declare the argument (see the "note"). – Some programmer dude Jul 27 '15 at 18:47
  • either what Joachim said or (if you want the *dirtier* path) pass as `&(rawdata[0])` ... –  Jul 27 '15 at 18:48
  • @FelixPalmen The second solution might silence the error, but it's still not correct. See e.g. [this old answer of mine](http://stackoverflow.com/questions/18440205/casting-void-to-2d-array-of-int-c/18440456#18440456) for an explanation. – Some programmer dude Jul 27 '15 at 18:51
  • 1
    yes, you're right, it should be `&(rawdata[0][0])` and an argument taking just `short *`. applicable if you want this to work for different *row lengths* ... –  Jul 27 '15 at 18:53
  • @FelixPalmen, you can access a 2-dimensional array as if it were a 1-dimensional array, but strictly speaking the behavior is undefined: [take a look](http://stackoverflow.com/a/7785116/1606345). – David Ranieri Jul 27 '15 at 19:02
  • Thank you much for your answers, but I'm still getting the same errors as before. I've tried `&(rawdata[0])` and `&(rawdata[0][0])` with no success. I also tried `&rawdata[20]` and nothing. – ElGranGeek Jul 27 '15 at 19:05
  • define `int aae(int nLenFrame, int frameSize, short psDataBuffer[nLenFrame][frameSize], float *pFV )`, caller side `arraySize1 = sizeof(rawdata)/sizeof(*rawdata); arraySize2 = sizeof(*rawdata)/sizeof(**rawdata); a = aae( arraySize1, arraySize2, rawdata, &pFV);` – BLUEPIXY Jul 27 '15 at 19:09
  • @AlterMann no it's not, because arrays of any dimension are guaranteed to be stored contiguously. What Keith is talking about in the answer you linked here is the (false) assumption that any pointers were involved, that's why my first comment was wrong, as Joachim pointed out correctly. –  Jul 27 '15 at 19:11
  • `int aae( int nLenFrame, short psDataBuffer[][20], float *pFV )` – Nick Stoughton Jul 27 '15 at 19:11
  • Thank you Nick Stoughton. That did the trick. – ElGranGeek Jul 27 '15 at 19:18
  • And thank you too, BLUEPIXY. Your solution also worked. Much thanks to everyone. – ElGranGeek Jul 27 '15 at 19:26
  • 2
    I reiterate my original comment: Read the error message, it tells you what you should do. If you see the "note" the compiler says that you are passing `short int (*)[20]` as type, so just declare the argument like that, `short (*psDataBuffer)[20]`. The reason is that arrays, when you pass them to functions, decays to pointers, so an array of arrays decays to a pointer to an array, which is what the new declaration is. – Some programmer dude Jul 27 '15 at 19:28
  • @FelixPalmen, even if they are in contiguous areas, flattening the array with `short *p = &(rawdata[0][0])` and dereferencing `*(p + 21)` is UB: [Why is flattening a multidimensional array in C illegal?](http://stackoverflow.com/q/22143494/1606345) – David Ranieri Jul 27 '15 at 21:38
  • @AlterMann it's still not true, see in `C99` `6.2.5`, paragraph 20: "An array type describes a **contiguously allocated** nonempty set of objects" (highlighted by me). Of course, applying this recursively for multi-dimensional arrays gives you a guarantee about the layout in memory. So, it is *well-defined* behaviour. –  Jul 27 '15 at 22:00
  • @FelixPalmen: C99, Annex J.2 Undefined behavior: "_An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int a[4][5]) (6.5.6).undefined._", same for `rawdata[0][21]` or `*(p + 21)` given the declaration `short rawdata[3][20]` – David Ranieri Jul 27 '15 at 23:11
  • @AlterMann That's just not what you do. The conversion to pointer is *well-defined* and the access through a pointer offset is *well-defined*, too, because you have the guarantee about how the array is stored. –  Jul 28 '15 at 06:49
  • Again, the access through a pointer (a pointer to short) one past the last element of an array object (the last element of the first row in this case) is **NOT** well defined (even if "An array type describes a contiguously allocated nonempty set of objects"), please, read C99 6.5.6 – David Ranieri Jul 28 '15 at 09:19

1 Answers1

0

I answer this as an XY problem, as you want to sum the columns, and in doing so hit other problems, which you ask how to solve. But also answers from incomplete information which I have to guess.

You declared a 2D array short rawdata[][20] but supplied data as if it is a 1D array. You then fiddle with pointers and come up with a wrong answer.

This answer initialises a 2D array correctly, and sums the columns simply, by using array indexing.

#include <stdio.h>

#define AXES 3
#define COLS 20

short rawdata[AXES][COLS]={
    {28,34,36,39,42,47,37,41,41,33,33,36,36,36,27,27,24,31,29,26 },
    {518,512,507,508,521,522,524,525,519,512,506,511,511,501,501,495,497,500,508,504},
    {917,914,905,909,892,879,869,873,876,877,875,870,883,893,893,884,881,882,885,888}
};

void sumcols(short rawdata[][COLS]) {
    int col, axis;
    float sum;

    for (col=0; col<COLS; col++) {
        sum = 0;
        for (axis=0; axis<AXES; axis++) {
            sum += rawdata [axis][col];
        }
        printf("Column %2d sum = %f\n", col, sum);
    }
}

int main(void) {
    sumcols(rawdata);
    return 0;
}

Program output:

Column  0 sum = 1463.000000
Column  1 sum = 1460.000000
Column  2 sum = 1448.000000
Column  3 sum = 1456.000000
Column  4 sum = 1455.000000
Column  5 sum = 1448.000000
Column  6 sum = 1430.000000
Column  7 sum = 1439.000000
Column  8 sum = 1436.000000
Column  9 sum = 1422.000000
Column 10 sum = 1414.000000
Column 11 sum = 1417.000000
Column 12 sum = 1430.000000
Column 13 sum = 1430.000000
Column 14 sum = 1421.000000
Column 15 sum = 1406.000000
Column 16 sum = 1402.000000
Column 17 sum = 1413.000000
Column 18 sum = 1422.000000
Column 19 sum = 1418.000000
Community
  • 1
  • 1
Weather Vane
  • 33,872
  • 7
  • 36
  • 56