Is this code well defined by using sizeof operator? - c

#include <stdio.h>
void test(int arr[]);
int main ()
{
int *arr[3];
int ar1[2] = { 1, 2 };
int ar2[3] = { 3, 4, 5 };
int vla[ar2[1]];
arr[0] = ar1;
arr[1] = ar2;
arr[2] = vla;
for (int i = 0; i < 3; i++)
{
test(arr[i]);
}
}
void test(int arr[])
{
printf("%zu\r\n", sizeof(arr));
}
As the title say: is this valid? and if so, is there a way to make test() output different values by using sizeof on function argument handed in like on array?

Yes it is valid and will give the size of an int pointer (that's what the type of the arr parameter is, there are no array parameters in C) in bytes. 1
To get the size of an array in bytes with sizeof, the argument has to be an actual array, not a pointer.
Consequently, it's not possible to get the size of an array passed as a parameter inside a function without passing an extra parameter specifying the size.
So,
is there a way to make test() output different values by using sizeof on function argument handed in like on array?
no. (Without editing the function body.)
1 If you're wondering how it's possible to pass an array as a pointer parameter, it's because of the implicit array-to-pointer conversion, known as array decaying.

Is this:
void test(int arr[]) {
printf("%d\r\n", sizeof(arr));
}
valid?
It is NOT a valid1 code, however it is equivalent to: sizeof(int*), not size of the array, arr, because as you pass the array as an argument it decays to a pointer2 i.e. it looses the information about the size of the whole array. The only way to convey this information into a function is through an additional, second, parameter.
Is there a way to make test() output different values by using sizeof on function argument handed in like on array?
If you want to print the size of the array you are passing, you could use something like: sizeof(array) as an second argument of the function, where the function signature would be:
void test(int arr[], size_t size);
you could insert the above as second argument and get the size of the first argument.
1. There is a type mismatch between size_t(the returning type of sizeof()) and int (the expected type matching the specifier "%d" in the printf(),, which leads to undefined behaviour.
2. arr[] outside the function represents the whole array as an object and that is why if you apply sizeof() you will get the size of the whole array, however, when passed as argument, arr decays to a pointer of the array's first element and if you apply sizeof() you'll get the size of the type of the pointer.

Is this code well defined by using sizeof operator?
Pedantically: No
sizeof() returns type size_t. "%d" expects type int. Using mis-match type results in undefined behavior (UB). Step 1: Use matching specifier
// printf("%d\r\n", sizeof(arr));
printf("%zu\r\n", sizeof(arr));
// or
printf("%d\r\n", (int) sizeof(arr));
The following prints the size of a pointer arr. The code in main() is not relevant.
void test(int arr[]) {
printf("%zu\r\n", sizeof(arr));
}
// or simply: remove (), \r of dubious value
printf("%zu\n", sizeof arr);

Related

Multidimensional arrays understanding for c

I have a question regarding passing an array to another function.
#include <stdio.h>
void print (int ar[]);
main () {
int array[2][2] = {1,2,3,4};
print(array);
}
void print (int ar[]) {
printf("%d\n", ar[0]);
printf("%d\n", *(ar+1));
}
So let's say if i'm passing array to function print. Am I passing address of the first 1-D array (array[0]) or am i just passing the address of the very first variable (array[0][0]).
And as for the print function, in this case, am I correct to say that by printing ar[0], I am printing array[0][0]?
But why is it that for the case of printing *(ar+1), I am actually printing array[0][1] instead of array[1][0]?
Thank you everyone in advance!
If you are passing a two-dimensional array to a function:
int array[NROWS][NCOLUMNS];
print(array);
the function's declaration must match:
void print(int array[][NCOLUMNS])
{ ... }
or
void print(int (*ap)[NCOLUMNS]) /* ap is a pointer to an array */
{ ... }
The 2D arrays which is array of arrays decays a pointer to an array rather than a pointer to a pointer.
So let's say if [I]'m passing array to function print. Am I passing address of the first 1-D array (array[0]) or am [I] just passing the address of the very first variable (array[0][0]).
You are passing a pointer to the first element of array, array[0], which is itself an array. That pointer has the same value as a pointer to array[0][0], but different type. In fact, your code is incorrect in that the argument's type and the function parameter's type do not agree, but as long as the types int(*)[] and int * have the same representation, the reinterpretation will work in practice.
And as for the print function, in this case, am I correct to say that by printing ar[0], I am printing array[0][0]?
Yes, when you call print() as you do in your example, provided that type representations agree as described above.
But why is it that for the case of printing *(ar+1), I am actually printing array[0][1] instead of array[1][0]?
Because ar is a pointer to the first element of array, i.e. the 1D array array[0]. Its elements are array[0][0], array[0][1], etc.. ar + 1 is therefore a pointer to the second element of array[0], which is array[0][1].
You have two options to make your code correct, both of which might help clarify the issues involved. You could change the argument you pass to print() to agree with the function:
print(array[0]);
Alternatively, you could change the declared type of print()'s argument, whith a corresponding alteration to its use:
void print(int (*ar)[2]) {
printf("%d\n", ar[0][0]);
printf("%d\n", *(ar+1)[0]);
}
or
void print(int ar[][2]) {
printf("%d\n", ar[0][0]);
printf("%d\n", *(ar+1)[0]);
}
The latter two change the meaning of *(ar + 1).
Your code is probably not doing what you want. Compile with Wall and you will see some warnings.
You need to change print argument to accept a 2D array (now you are passing int (*)[2] but the function is expecting int *), and then you can print the values correctly.
#include <stdio.h>
void print (int ar[][2]);
int main () {
int array[2][2] = {
{1,2},
{3,4}
};
print(array);
return 0;
}
void print (int ar[][2]) {
printf("%d\n", ar[0][0]); // 1
printf("%d\n", ar[1][0]); // 4
}
When you pass an array to a function, you are using "pass-by-reference" meaning you pass the address of the array.
Am I passing address of the first 1-D array (array[0]) or am i just passing the address of the very first variable (array[0][0]).
No. The way you are passing array currently you are giving the function the 2-D array.
And as for the print function, in this case, am I correct to say that by printing ar[0], I am printing array[0][0]?
No. You still need to specify the number you want to print from ar[0]
But why is it that for the case of printing *(ar+1), I am actually printing array[0][1] instead of array[1][0]?
This is because you are telling the program to go to array in memory and use pointer arithmetic to traverse the array. For example, if you have a char * str variable that contains characters abcde\0 and want to get the character at position 2 you can either do str[2] or *(str+2) which means the same thing and both give the character 'c'.

Find the Size of integer array received as an argument to a function in c [duplicate]

This question already has answers here:
C sizeof a passed array [duplicate]
(7 answers)
Closed 8 years ago.
i would like to find the size of integer array passed as an argument to a function.
Here is my code
void getArraySize(int arr[]){
int len = (sizeof(arr)/sizeof(arr[0])
printf("Array Length:%d\n",len);
}
int main(){
int array[] = {1,2,3,4,5};
getArraySize(array);
return 0;
}
I am getting the following warning
sizeof on array function parameter will return
size of 'int *' instead of 'int []' [-Wsizeof-array-argument]
Please help so that i can find the length of integer array inside the function getArraySize
However am able to find the size of the array inside the main function.Since it is passed as a pointer, am not able to find the length from with in the function.
i do have an idea though.I could put this with in a try/catch block(C does not have try catch,Only jumpers which is OS dependent) and loop until i get a segmentation fault.
Is there any other way i could use to find the length of integer array inside the function
You cannot do it that way. When you pass an array to a function, it decays into a pointer to the first element, at which point knowledge of its size is lost.
If you want to know the size of an array passed to the function, you need to work it out before decay and pass that information with the array, something like:
void function (size_t sz, int *arr) { ... }
:
{
int x[20];
function (sizeof(x)/sizeof(*x), x);
}
When you pass an array to a function, its address is passed to the function as a pointer.
So void getArraySize(int arr[]) is equivalent to void getArraySize(int* arr).
As a result, sizeof(arr) yields sizeof(int*), which is probably not what you want.
You can safely use sizeof(arr)/sizeof(arr[0]) only within the scope of declaration of arr.
In your case, the scope of declaration of arr is function main.
The array decays to a pointer when passed.
So sizeof only works to find the length of the array if you apply it to the original array.
So you need to pass length of array as separate argument to function.
There is no way to determine the length inside the function. However you pass arr, sizeof(arr) will always return the pointer size. So the best way is to pass the number of elements as a separate argument.
sizeof only works to find the length of the array if you apply it to the original array.
int arr[5]; //real array. NOT a pointer
sizeof(arr); // :)
However, by the time the array decays into a pointer, sizeof will give the size of the pointer and not of the array.
void getArraySize(int arr[]){
sizeof(arr); // will give the pointer size
}
There is some reasoning as to why this would take place. How could we make things so that a C array also knows its length?
A first idea would be not having arrays decaying into pointers when they are passed to a function and continuing to keep the array length in the type system.
When you pass an array to a function it decays to pointer. So the sizeof function will return the size of int *. This is the warning that your compiler complining about-
sizeof on array function parameter will return size of 'int *' instead of 'int []'
As i suggested when you pass the array to the function you need to pass the Number of elements also-
getArraySize(array, 5); // 5 is the number of elements in array
Catch it by-
void getArraySize(int arr[], int element){
// your stuff
}
Else general way to calculate array size-
void getArraySize(int arr[], int len){
// your stuff
printf("Array Length:%d\n",len);
}
int main(){
int array[] = {1,2,3,4,5};
int len = (sizeof(arr)/sizeof(arr[0]); // will return the size of array
getArraySize(array, len);
return 0;
}

array returning error in c

I am getting an error in the return line. "Incompatible pointer to integer conversion returning 'int (*)[2]' from a function with result type 'int'" can someone explain what is theory behind this error and how to fix it? still I am getting right result, but don't know about this error. (hints: I am very beginner )
here is my testing code.
#include <stdio.h>
#include<string.h>
/* two diminsanl array testing*/
int array_function(int phase,int array[][2]);
int main()
{
int phase =1;
int array[][2]={};
array_function(phase, array);
phase =2;
array_function(phase, array);
return 0;
}
int array_function(int phase, int array[][2])
{
if(phase==1)
{
array[0][0]=1;
array[0][1]=2;
array[1][0]=3;
array[1][1]=4;
}
if(phase==2)
{
printf("%d\n",array[0][0]);
}
return array; //<------------- error line
}
Well, first of all, your function is expecting an int return, but you're trying to return an int[][].
And, you can't return an array by value in c. You'll need to return a pointer, or wrap the array as part of a struct.
You have int as return type of function ( int array_function() ) but are trying to return a pointer(return array;). Since it look that you don't need to return anything just have the return type as void or return 0. Since array is passed by reference it automatically gets the changes that you do to it inside the function.
If you statically create an array you have to specify both dimensions.
Arrays are passed as pointers and if you pass a static array it is good practice to give the dimensions in the parameters of the function. Simply pass the arrays name to any function even if you allocated it dynamically. If you want to return an array you should return an int* or int** for a 2D array.
Let's say you want to create an array in a function and let the caller have it.
int *createArray(int size)
{
int *array = malloc(size * sizeof(int));
return array;
}
You can call this function from your main.
int *list;
list = createArray(2);
And modify list like any other array.
This is your code properly.
#include <stdio.h>
/* two diminsanl array testing*/
void array_function(int phase, int array[2][2]);
int main()
{
int phase = 1;
int array[2][2];
array_function(phase, array);
phase = 2;
array_function(phase, array);
return 0;
}
void array_function(int phase, int array[2][2])
{
if (phase == 1)
{
array[0][0] = 1;
array[0][1] = 2;
array[1][0] = 3;
array[1][1] = 4;
}
if (phase == 2)
{
printf("%d\n",array[0][0]);
}
}
First this line, is not a legal assignment:
int array[][2]={};
For what you are doing, this line would work:
int array[][2]={0,0,0,0};
second As others have pointed out, this line is attempting to return int[][]. Two problems with this, 1) C cannot return the value representation of an array of ints, (although it can return pointers, such as int **, you don't need to here. See note at bottom). And 2) the prototype clearly calls for int
return array; //<------------- error line
For now, simply change the line to:
return 0;
Those two changes will result in your code populating array[][] with no errors.
Note: because you are passing your array by reference, ( array_function(phase, array); ) the values assigned to array within array_function() are made available back in the main() function without having them returned as a return. (i.e. int ** array_function(phase, array) )
So, first of all, the type of the expression array in array_function is int (*)[2], or "pointer to 2-element array of int".
Except when it is the operand of the sizeof or unary & operator, or is a string literal being used to initialize another array in a declaration, 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.
When you call phase_array from main, like so:
array_function(phase, array);
the expression array has type "2-element array of 2-element array of int"; since it is not the operand of the sizeof or unary & operators, it is converted to an expression of type "pointer to 2-element array of int", and its value is set to the address of the first element (&array[0]). This pointer value is what gets passed to array_function.
In the context of a function parameter list, declarations of the forms T a[N] and T a[] will be interpreted as T *a; all three declare a as a pointer to T. So,
int array_function(int phase, int array[][2])
is the same as
int array_function(int phase, int (*array)[2])
Which brings us to your error message: you've declared array_function to return an int (which you don't ever use in your main function, btw), but the type of the expression array is int (*)[2]; hence the error message. The two types are not *compatible", and the compiler flags this as an error.
Since you've passed the address of the first element of array to array_function, any changes you make to the array contents will be reflected in main, so you really don't need to return the array. As others have suggested, just change the type of the function to void and don't return anything.

What type does & return for an Array Parameter inside a C Function?

When passing an Array Argument to a Function, it's memory address is copied into an Array Parameter. Because of this:
sizeof() returns the size of the entire array for the Array Argument (inside caller)
sizeof() returns the size of a pointer for the Array Parameter (inside called Function)
My question is, what type is the Array Parameter inside the Function? And more specifically, what type is returned when using the & Operator on an Array Parameter? It's not a Pointer to Array of Type, nor is it a Pointer to Type, as shown in this code (labeled BAD):
void doSomething(int arrayParam[10]);
int main()
{
int array[10] = { 0 };
int (*arrayPtr)[] = &array; // OK
printf("%p\n", array); // 0x7fff5fbff790
doSomething(array);
return 0;
}
void doSomething(int arrayParam[10])
{
printf("%p\n", arrayParam); // 0x7fff5fbff790
int (*arrayPtr)[] = &arrayParam; // BAD: Initialization from incompatible pointer type
int * element0Ptr = &arrayParam; // BAD: Initialization from incompatible pointer type
element0Ptr = arrayParam; // OK
element0Ptr = &arrayParam[0]; // OK
}
Thanks for any help you can offer! :)
Most of the time, when you use an array, it decays to a pointer to its initial element. So, if you have:
void f(int* x);
int array[10];
int* initial_element_of_array = array; // array decays to a pointer to initial element
f(array); // same here
f() gets a pointer to the initial element of array.
Something that is rather confusing at first is that if a function has a parameter that is of an array type (like if you had void f(int x[])), this is actually converted such that it is exactly the same as void f(int* x). There is no difference between them: array type parameters are the same as pointer type parameters.
Once you pass an array to a function, all you have is a pointer to its initial element, so if you apply the & operator to the int*, you get an int** (a pointer to an int*).

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