invalid use of array with unspecified bounds - c

i had a question in my program. When I pass the 3D int array CodedGreen to the function Green_Decode_Tree. An error message"invalid use of array with unspecified bounds" displayed. What is the mistake in my program? Thanks for your help.
for(i=0;i<256;i++){
for(j=0;j<256;j++){
Decode_Tree(green[0], CodedGreen,0,i,j);
}
}
void Green_Decode_Tree(node* tree, int code[][][], int num,int row,int col)
{
int i;
i=num;
if((tree->left == NULL) && (tree->right == NULL)){
fprintf(DecodGreen,"%s\n", tree->ch);
}
else
{
if(code[row][col][num]==1){
i++;
Green_Decode_Tree(tree->left,code,i,row,col);
}
else if (code[row][col][num]==0){
i++;
Green_Decode_Tree(tree->right,code,i,row,col);
}
}
}

i will reveal you a secret. 2d (and 3d) arrays are represented as liner memory arrays. when you have array NxM and access it like a[i][j] it is actually translated to a[i*M + j] as you might notice compiler must know M here to do this conversion, otherwise it will not be able to translate it. So thats what he asks. You must provide all except first sizes in array: int code[][M][N]

Remember that in most contexts, array expressions have their types implicitly converted ("decay") from "N-element array of T" to "pointer to T" and evaluate to the address of the first element. When you pass CodedGreen (type int [X][Y][Z]) to Green_Decode_Tree, what the function receives is a pointer value of type int (*)[Y][Z].
So your prototype for Green_Decode_Tree needs to be
void Green_Decode_Tree(node *tree, int (*code)[Y][Z], int num, int row, int col)
Note that in the context of a function parameter declaration, int *a is synonymous with int a[] (no size), so int (*code)[Y][Z] could also be written as int code[][Y][Z]. I prefer using pointer notation, since that's what the function actually receives, but either will work. Note that in your function you will subscript it as normal:
if (code[row][num][col] == 1)
since the subscript operator implicitly dereferences the pointer (i.e., code[row] == *(code+row)).
This may be helpful:
Declaration Expression Type Decays to
----------- ---------- ---- ---------
T a[X]; a T [X] T *
&a T (*)[X]
T b[X][Y]; b T [X][Y] T (*)[Y]
&b T (*)[X][Y]
b[i] T [Y] T *
&b[i] T (*)[Y]
T c[X][Y][Z]; c T [X][Y][Z] T (*)[Y][Z]
&c T (*)[X][Y][Z]
c[i] T [Y][Z] T (*)[Z]
&c[i] T (*)[Y][Z]
c[i][j] T [Z] T *
The expressions a, b, b[i], c, c[i], and c[i][j] are all array expressions, so their types will decay to pointer types in most contexts. The exceptions are when the array expressions are operands of the sizeof or address-of & operators (as is shown in the table), or when the array expression is a string literal being used to initialize another array in a declaration.

Related

Some misunderstand about casting in generic function

I have some misunderstanding of the tutorial from my class. There is function called print_Arr(), it's generic function that gets pointer to arrays of double or integers and prints it.
Here is the code:
int main() {
int a[] = { 2,7,6,4,1 };
double b[] = { 12.5,2.7,3.0,5.5,5.9,1.0 };
print_Arr(a, sizeof(a)/sizeof(a[0]), sizeof(int), print_int);
print_Arr(b, sizeof(b)/sizeof(b[0]), sizeof(double), print_double);
}
void print_Arr(void* a, int size, int m, void (*print_func)(void* )) {
for (int i = 0; i <= size-1; i++)
{
print_func((char*)a + m*i);
}
}
void print_int(int* p) {
printf("%d\n", *p);
}
void print_double(double* num) {
printf("%f\n", *num);
}
Why do I have to make cast a to (char*) in this row:
print_func((char*)a + m*i);
I sent to print_Arr() generic function two type of arrays integers or doubles,
thus it is logically to cast a to int * or to double*.
But why is it casted to char*? What do I miss?
First, a word on why the cast is needed:
Pointer arithmetic makes use of the size of the type being pointed to. void is a forever incomplete type, that cannot be completed, so pointer arithmetic is not possible on a pointer to void type.
To add, for the additive operators, quoting from C11, chapter §6.5.6, constraints:
For addition, either both operands shall have arithmetic type, or one operand shall be a
pointer to a complete object type and the other shall have integer type.
and, from chapter §6.2.5,
The void type comprises an empty set of values; it is an incomplete object type that
cannot be completed.
That said, why the cast is to char* :
Pointer arithmetic makes use of the type being pointed to. Quoting the spec once again
[...] if the expression P points to
the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and
(P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of
the array object, provided they exist.
Here, look at your construct:
((char*)a + m*i);
where m is the size of the actual object type pointed to by the actual argument. So, if you cast the pointer to the actual type, the calculation would be wrong. To present a comparison, say:
sizeof (char) is 1, mandated by standard.
sizeof (int) == 4 , say in your platform.
So, for an array int arr[ ] = {1, 2, 3, 4}, the expressions
(char*)a + (sizeof(int)*1)
and
(int*) a + 1
are equivalent.
Finally, touching the topic of converting another type of pointer to char* and accessing it:
[...] When a pointer to an object is converted to a pointer to a character type,
the result points to the lowest addressed byte of the object. Successive increments of the
result, up to the size of the object, yield pointers to the remaining bytes of the object. [....]
You need the char * cast because you do pointer arithmetic on the pointer, to get a byte offset from the beginning, but you can't do that on a void *.
A void pointer doesn't have a type size, so you can't calculate with it.
public:
int num=0;
int c;
int doubleToChar(double a){
while ((a-1)>=0){
num++;
}
c=a;
return a*10;
}/* int doubleToCharhundred(double a){
while ((a-1)>=0){
num++;
}
return a*100-c;
}*/
double a=12.12345;
char *tenDivide ;
char *intPart;
//u can add hundred or thousand by another char;
tenDivide =doubleToChar(a);
if(num<128)
intPart=num;
else{
while(num-1){
//same doubleToChar
}
}

reducing array by reassigning it to one of its elements with & operator in c

I wrote a simple recursive function for binary search that takes three arguments: an array of integers, the length of the array and a value to find. The idea is that at every recursive call it either halves the length and keeps the array[0] in place or moves the starting index to the middle (third line from the bottom in my sample). That is until the value is found or length is 0.
Then I saw this disccussion: How do you shift the starting index of an array in C?
It is said here that an array name is a constant and cannot be reassigned in C. So my question is why this code works?
int rsearch( int needle, int haystack[], int size ) {
if (size == 0) {
printf("%i not found\n", needle);
return 0;
}
int mid = size / 2;
if (haystack[mid] == needle) {
printf( "found %i in the array\n", needle );
return 1;
} else if (haystack[mid] > needle) {
return rsearch( needle, haystack, size / 2 );
} else {
haystack = &haystack[mid + 1];
return rsearch( needle, haystack, (size - 1) / 2 );
}
I'm just studying, and my knowledge of pointers is very limited. And there's no practical application here. Just curious.
P.S.
The other question is what happens to the memory allocated to the original array when it's reduced this way? Is it made available again or is it a memory leak?
Arrays when used as function arguments actually mean a pointer to an array, but not the array as value. So the following function signatures are equivalent: void test(int xptr[10]), void test(int xptr[]), and void test(int *xptr).
At the point where an array is defined, however, you can only initialise it's value, but you cannot assign any other value later on.
When you pass an array, let's say int x[10] to a function by just using x as parameter, like in test(x), then array x automatically decays to a pointer to the first element of x.
See the following code showing the difference:
#include <stdio.h>
void test(int xptr[10]) {
printf("value of xptr[0]: %d\n", xptr[0]); // -> 0
xptr = &xptr[2]; // OK; xptr will point to element 2
printf("value of xptr[0]: %d\n", xptr[0]); // -> 2
}
int main(){
int x[10] = { 0,1,2,3,4,5,6,7,8,9 };
// x = &x[2]; // Error: Array type 'int [10]' is not assignable
// but:
test(x); // OK; and is eqivalent to...
test (&x[0]); // OK;
return 0;
}
As a function argument, this:
int haystack[]
Is equivalent to:
int *haystack
This is mainly because an array decays to a pointer to the first element when passed to a function.
So what you have is not an array but a pointer. Unlike an array, a pointer is a modifiable lvalue, so it is allowed to assign to it.
According to the C Standard (6.7.6.3 Function declarators (including prototypes))
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted
to ‘‘qualified pointer to type’’...
and (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
Thus in this function declaration
int rsearch( int needle, int haystack[], int size );
the parameter int haystack[] is adjusted to int *haystack. So these function declarations
int rsearch( int needle, int haystack[100], int size );
int rsearch( int needle, int haystack[10], int size );
int rsearch( int needle, int haystack[], int size );
int rsearch( int needle, int *haystack, int size );
declare the same one function. You may include all these declarations in your program because a function declaration may appear more than one time. However the function shall be defined only one time (if it is not an inline function).
Accordingly the array passed to the function as argument is implicitly converted to pointer to its first element.
Take into account that it would be better to declare the function like
int rsearch( int needle, const int *haystack, int size );
^^^^^
In this case the function can be used also with constant arrays.
It is said here that an array name is a constant and cannot be
reassigned in C.
It would be correctly to say that array is not a modifiable lvalue.
From the C Standard (6.5.16 Assignment operators)
2 An assignment operator shall have a modifiable lvalue as its left
operand.
and (6.3.2.1 Lvalues, arrays, and function designators)
...A modifiable lvalue is an lvalue that does not have array type,...

C : How do you input integers row by row into a 2 dimensional matrix and then get it back from a function to main()?

Edit: Ok returning the matrix bit is now ok but still can't get entering rows of values down. It still only gives one value.
Quite new to C so apologies for the long read and terrible coding.
This is for a homework hence why it has to be so specific but the homework reads as:
Prompt for the size of the multiplier, which may be no bigger than ten in either dimension. Read
the elements by row, one row per line of input. If the
actual input matrix has different number of row or column as specified in the former step, print an error message and end the program.
So it needs to read in
1 0 0
1 0 0
1 0 0
and see if thats the size as declared earlier. It needs to do this for two separate matrices hence why I'm using a function, and then it will multiply the two matrices. What I currently have is
void matrix(int x, int y)
{
int i, j;
char c;
i = 0;
j = 0;
while (j < x)
{
while (c != '\n')
{
scanf("%d%c", &input[i][j], &c);
}
++j;
c = 0;
}
}
Where x and y are the size of the matrix and input[10][10] is a global array which I'm using to transfer the values out of the function to main.
Is there a way to do this with pointers? I know there are ways of doing it but my problem is that cause its for a homework we can only use what we "know" so I can only use scanf to read in variables.
Another problem I'm having is reading in the row elements, it only accepts the last element I input (which it takes as the first element) and leaves the rest blank.
Best way to do this is to pass the array as a parameter to the function, rather than try to return it.
C's treatment of arrays is special. Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" is converted ("decays") to an expression of type "pointer to T" and the value of the expression is the location of the first element of the array1.
For example, let's assume the following code:
int main( void )
{
int arr[10]; // start with a 1D array for now
foo( arr );
return 0;
}
In the function call foo( arr ), the expression arr has type "10-element array of int" (int [10]). Since it's not the operand of the sizeof or unary & operators, it "decays" to an expression of type "pointer to int" (int *), and the value of the expression is the address of arr[0].
Thus, the definition of foo would look like this:
void foo( int *a ) { ... }
What foo receives is a pointer value, not an array. C allows you to write that prototype as
void foo( int a[] ) { ... }
or even
void foo( int a[10] ) { ... }
But, in the context of a function parameter declaration, T a[] and T a[N] are interpreted as T *a; they declare a as a pointer to T, not an array of T.
The subscript operator [] is defined in terms of pointer arithmetic - a[i] == *(a + i). This means that the [] operator can be applied to pointer expressions as well as array expressions; thus, a[i] will work2 whether a is an array of T or a pointer to T.
So, applying that to your code:
int main( void )
{
int a, b;
int input[10][10]; // make input local to main
...
matrix( a, b, input );
...
}
void matrix( int x, int y, int (*input)[10] ) // or input[][10], or input[10][10]
{
...
scanf( "%d%c", &input[i][j], &c );
...
}
Having said that, you will want to send an extra parameter specifying the number of rows in the array:
matrix( a, b, rows, input );
void matrix( int x, int y, size_t rows, int (*input)[10] )
{
...
}
A pointer to an N-element array is a different type than a pointer to a M-element array (where N != M), so you can't pass anything but an N x 10-element array to matrix. However, there's no way for you to know the value of N unless you pass it as a separate parameter.
A note on syntax
A pointer to an array has the form T (*p)[N]. The parens are required since the postfix [] operator has a higher precedence than the unary * operator. *p[N] is parsed as *(p[N]) - IOW, index into p and dereference the result. (*p)[N] will first dereference p, then index into the result.
An expression of type T [N][M] will "decay" to type T (*)[M].
If you're curious why this is the case, check out this paper by Ritchie describing the development of C.
Assuming i doesn't fall outside the bounds of the array or sequence being pointed to.
This isn't rocket science.
void matrix(int x, int y, int input[x][y])
{
... // fill up input[i][j] here
}
This is possible since arrays, whenever passed to functions, decay into a pointer to the first element. So with this function you will change the contents of the original array.

Trouble working with 2d array passed by reference C

So I am working on an assignment and I am having trouble figuring out how to use this 2d array which was passed by reference.
What I am given is this
int main(){
//cap and flow initialized
maximum_flow(1000, &(cap[0][0]), &(flow[0][0]));
}
So I wanted to copy the contents of cap over to another 2d array I dynamically allocated, but after hitting an error I decided to print out the values I have in cap2 and capacity, I'm not getting back all the values that I should.
void maximum_flow(int n, int *capacity, int *flow){
int **cap2;
cap2 = (int**) malloc(sizeof(int *)*n);
for (i = 0; i < n; i++)
{
cap2[i] = (int*) malloc(sizeof(int)*n);
}
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
cap2[i][j] = (*(capacity + i*n + j));
(*(flow + i*n + j)) = 0;
}
}
}
This isn't going to be a terribly useful answer, since your code doesn't actually show the problem described; based on what's presented, I see no obvious reason why cap and cap2 shouldn't have the same contents by the end of the maximum_flow function. But I'd like to offer some background and a suggestion.
I'm going to assume cap and flow are declared as n by n arrays of int in main, where n is known at compile time.
The reason your instructor is using this interface is that passing multidimensional arrays as function arguments is problematic in C. Remember that unless it's the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaraiton, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
So, assuming a declaration like
int cap[10][10];
int flow[10][10];
the expressions cap and flow will each "decay" to type int (*)[10] (pointer to 10-element array of int). So if you wrote your function call as
maximum_flow( 1000, cap, flow );
then the function definition would have to be written as
void maximum_flow( int n, int (*cap)[10], int (*flow)[10] ) { ... }
or
void maximum_flow( int n, int cap[][10], int flow[][10] ) { ... }
In the context of a function parameter declaration, T a[][N] and T (*a)[N] mean the same thing.
The size of the outer dimension has to be specified in the array pointer declaration, and the problem is that a pointer to a 10-element array is a different, incompatible type from a pointer to an any-value-other-than-10-element array; thus, maximum_flow could only ever be used for N x 10-element arrays, limiting its usefulness. One way around this problem is to have the function receive an explicit pointer to the first element, and treat that pointer as a 1D array of size N * M.
Long story short, since you're treating your input parameters as 1D arrays, you are probably better off creating cap2 as a 1D array as well:
int *cap2 = malloc( sizeof *cap2 * n * n );
...
cap2[i * n + j] = capacity[i * n + j]; // use array subscript notation instead
flow[i * n + j] = 0; // of explicit dereferences
From the code you've posted, it's not clear what maximum_flow is supposed to do, nor why you need cap2. Note also that at some point you need to free the memory allocated to cap2, otherwise you have a memory leak.
If you're using a C99 or later compiler, you should be able to use a variable-length array instead of malloc:
int cap2[n * n]; // or int cap2[n][n], but like I said above, if you're
// treating your inputs as 1D arrays, you should also treat
// cap2 as a 1D array.
The advantage of a VLA is that you don't need to know the size at compile time, and it's treated like any other auto variable, meaning the memory for it will be released when the function exits.
The disadvantage of a VLA is that you can't use it as anything but a local variable; you can't have a VLA as a struct or union member, nor can you declare one static or at file scope. Neither can you explicitly initialize a VLA.

Return an array in c

I would like to know if there is any way to return an char array.
I tried something like this "char[] fun()" but I am getting error.
I don't want a pointer solution.
Thanks!
You can return an array by wrapping it in a struct:
struct S {
char a[100];
};
struct S f() {
struct S s;
strcpy( s.a, "foobar" );
return s;
}
Arrays cannot be passed or returned by value in C.
You will need to either accept a pointer and a size for a buffer to store your results, or you will have to return a different type, such as a pointer. The former is often preferred, but doesn't always fit.
C functions cannot return array types. Function return types can be anything other than "array of T" or "function returning T". Note also that you cannot assign array types; i.e., code like the following won't work:
int a[10];
a = foo();
Arrays in C are treated differently than other types; in most contexts, the type of an array expression is implicitly converted ("decays") from "N-element array of T" to "pointer to T", and its value is set to point to the first element in the array. The exceptions to this rule are when the array expression is an operand of either the sizeof or address-of (&) operators, or when the expression is a string literal being used to initialize another array in a declaration.
Given the declaration
T a[N];
for any type T, then the following are true:
Expression Type Decays to Notes
---------- ---- --------- -----
a T [N] T * Value is address of first element
&a T (*)[N] n/a Value is address of array (which
is the same as the address of the
first element, but the types are
different)
sizeof a size_t n/a Number of bytes (chars) in array =
N * sizeof(T)
sizeof a[i] size_t n/a Number of bytes in single element =
sizeof(T)
a[i] T n/a Value of i'th element
&a[i] T * n/a Address of i'th element
Because of the implicit conversion rule, when you pass an array argument to a function, what the function receives is a pointer value, not an array value:
int a[10];
...
foo(a);
...
void foo(int *a)
{
// do something with a
}
Note also that doing something like
int *foo(void)
{
int arr[N];
...
return arr;
}
doesn't work; one the function exits, the array arr technically no longer exists, and its contents may be overwritten before you get a chance to use it.
If you are not dynamically allocating buffers, your best bet is to pass the arrays you want to modify as arguments to the function, along with their size (since the function only receives a pointer value, it cannot tell how big the array is):
int a[10];
init(a, sizeof a / sizeof a[0]); // divide the total number of bytes in
... // in the array by the number of bytes
void init(int *a, size_t len) // a single element to get the number
{ // of elements
size_t i;
for (i = 0; i < len; i++)
a[i] = i;
}
arrays aren't 1st class objects in C, you have to deal with them via pointers, if the array is created in your function you will also have to ensure its on the heap and the caller cleans up the memory
A Very very basic code and very very basic explanation HOW TO Return
array back from a user defined function to main function..Hope It
helps!! Below I have given complete code to make any one understand
how exactly it works? :) :)
#include<iostream>
using namespace std;
char * function_Random()
{
int i;
char arr[2];
char j=65;//an ascII value 65=A and 66=B
cout<<"We are Inside FunctionRandom"<<endl;
for(i=0;i<2;i++)
{
arr[i]=j++;// first arr[0]=65=A and then 66=B
cout<<"\t"<<arr[i];
}
cout<<endl<<endl;
return arr;
}
int main()
{
char *arrptr;
arrptr=function_Random();
cout<<"We are Inside Main"<<endl;
for(int j=0;j<2;j++)
{
cout<<"\t"<<arrptr[j];
}
return 0;
}

Resources